Auto merge of #144607 - camsteffen:impl-trait-header-option, r=lcnr

Limit impl_trait_header query to only trait impls

Changes `impl_trait_header` to panic on inherent impls intstead of returning None. A few downstream functions are split into option and non-option returning functions. This gets rid of a lot of unwraps where we know we have a trait impl, while there are still some cases where the Option is helpful.

Summary of changes to tcx methods:
* `impl_is_of_trait` (new)
* `impl_trait_header` -> `impl_trait_header`/`impl_opt_trait_header`
* `impl_trait_ref` -> `impl_trait_ref`/`impl_opt_trait_ref`
* `trait_id_of_impl` -> `impl_trait_id`/`impl_opt_trait_id`
This commit is contained in:
bors 2025-10-18 00:08:18 +00:00
commit 2170b4da84
82 changed files with 296 additions and 337 deletions

View file

@ -708,8 +708,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return (false, false, None);
}
let my_def = self.body.source.def_id();
let Some(td) =
tcx.trait_impl_of_assoc(my_def).and_then(|id| self.infcx.tcx.trait_id_of_impl(id))
let Some(td) = tcx.trait_impl_of_assoc(my_def).map(|id| self.infcx.tcx.impl_trait_id(id))
else {
return (false, false, None);
};

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

@ -148,8 +148,7 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>(
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
ty::ImplPolarity::Negative => "!",
};
let trait_name = tcx
.item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
let trait_name = tcx.item_name(tcx.impl_trait_id(impl_def_id.to_def_id()));
let mut err = struct_span_code_err!(
tcx.dcx(),
impl_span,
@ -187,8 +186,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let impl_span = tcx.def_span(impl_def_id.to_def_id());
let trait_name = tcx
.item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait"));
let trait_name = tcx.item_name(tcx.impl_trait_id(impl_def_id.to_def_id()));
let polarity = match tcx.impl_polarity(impl_def_id) {
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
ty::ImplPolarity::Negative => "!",
@ -212,8 +210,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>(
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id());
let fresh_adt_ty =
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
let fresh_adt_ty = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, fresh_impl_args).self_ty();
ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
.expect("equating fully generic trait ref should never fail");

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),
@ -1191,9 +1191,7 @@ fn check_impl_items_against_trait<'tcx>(
tcx,
ty_impl_item,
ty_trait_item,
tcx.impl_trait_ref(ty_impl_item.container_id(tcx))
.unwrap()
.instantiate_identity(),
tcx.impl_trait_ref(ty_impl_item.container_id(tcx)).instantiate_identity(),
);
}
ty::AssocKind::Const { .. } => {}

View file

@ -38,8 +38,7 @@ pub(super) fn compare_impl_item(
) -> Result<(), ErrorGuaranteed> {
let impl_item = tcx.associated_item(impl_item_def_id);
let trait_item = tcx.associated_item(impl_item.expect_trait_impl()?);
let impl_trait_ref =
tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
let impl_trait_ref = tcx.impl_trait_ref(impl_item.container_id(tcx)).instantiate_identity();
debug!(?impl_trait_ref);
match impl_item.kind {
@ -443,7 +442,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());
let trait_m = tcx.associated_item(impl_m.expect_trait_impl()?);
let impl_trait_ref =
tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity();
tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).instantiate_identity();
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during instantiation later.
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;

View file

@ -244,7 +244,7 @@ fn missing_items_err(
let snippet = with_types_for_signature!(suggestion_signature(
tcx,
trait_item,
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(),
tcx.impl_trait_ref(impl_def_id).instantiate_identity(),
));
let code = format!("{padding}{snippet}\n{padding}");
if let Some(span) = tcx.hir_span_if_local(trait_item.def_id) {

View file

@ -245,10 +245,10 @@ pub(super) fn check_item<'tcx>(
// won't be allowed unless there's an *explicit* implementation of `Send`
// for `T`
hir::ItemKind::Impl(ref impl_) => {
crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
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;
@ -1258,7 +1258,7 @@ fn check_impl<'tcx>(
// `#[rustc_reservation_impl]` impls are not real impls and
// therefore don't need to be WF (the trait's `Self: Trait` predicate
// won't hold).
let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
let trait_ref = tcx.impl_trait_ref(item.owner_id).instantiate_identity();
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
tcx.ensure_ok().coherent_trait(trait_ref.def_id)?;

View file

@ -377,7 +377,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
let unsize_trait = tcx.require_lang_item(LangItem::Unsize, span);
let source = tcx.type_of(impl_did).instantiate_identity();
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity();
let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity();
assert_eq!(trait_ref.def_id, coerce_unsized_trait);
let target = trait_ref.args.type_at(1);
@ -707,7 +707,7 @@ fn visit_implementation_of_coerce_pointee_validity(
checker: &Checker<'_>,
) -> Result<(), ErrorGuaranteed> {
let tcx = checker.tcx;
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).instantiate_identity().self_ty();
let span = tcx.def_span(checker.impl_def_id);
if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { 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

@ -22,7 +22,7 @@ pub(crate) fn orphan_check_impl(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
) -> Result<(), ErrorGuaranteed> {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
let trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity();
trait_ref.error_reported()?;
match orphan_check(tcx, impl_def_id, OrphanCheckMode::Proper) {
@ -294,7 +294,7 @@ fn orphan_check<'tcx>(
) -> Result<(), OrphanCheckErr<TyCtxt<'tcx>, FxIndexSet<DefId>>> {
// We only accept this routine to be invoked on implementations
// of a trait, not inherent implementations.
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
let trait_ref = tcx.impl_trait_ref(impl_def_id);
debug!(trait_ref = ?trait_ref.skip_binder());
// If the *trait* is local to the crate, ok.

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

@ -108,7 +108,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
let vtable_entries = match tcx.hir_item(id).kind {
hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity();
let trait_ref = tcx.impl_trait_ref(def_id).instantiate_identity();
if trait_ref.has_non_region_param() {
tcx.dcx().span_err(
attr.span(),

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

@ -118,8 +118,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
let impl_def_id = tcx.parent(fn_def_id);
let impl_trait_ref_args =
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args;
let impl_trait_ref_args = tcx.impl_trait_ref(impl_def_id).instantiate_identity().args;
let impl_assoc_args =
impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args);
@ -162,9 +161,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
if let Some(of_trait) = impl_.of_trait
&& of_trait.defaultness.is_default()
{
is_default_impl_trait = tcx
.impl_trait_ref(def_id)
.map(|t| ty::Binder::dummy(t.instantiate_identity()));
is_default_impl_trait =
Some(ty::Binder::dummy(tcx.impl_trait_ref(def_id).instantiate_identity()));
}
}
ItemKind::Trait(_, _, _, _, _, self_bounds, ..)
@ -350,9 +348,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// before uses of `U`. This avoids false ambiguity errors
// in trait checking. See `setup_constraining_predicates`
// for details.
if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
if let Node::Item(&Item { kind: ItemKind::Impl(impl_), .. }) = node {
let self_ty = tcx.type_of(def_id).instantiate_identity();
let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
let trait_ref =
impl_.of_trait.is_some().then(|| tcx.impl_trait_ref(def_id).instantiate_identity());
cgp::setup_constraining_predicates(
tcx,
&mut predicates,
@ -460,11 +459,12 @@ fn const_evaluatable_predicates_of<'tcx>(
}
if let hir::Node::Item(item) = node
&& let hir::ItemKind::Impl(_) = item.kind
&& let hir::ItemKind::Impl(impl_) = item.kind
{
if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
if impl_.of_trait.is_some() {
debug!("visit impl trait_ref");
of_trait.instantiate_identity().visit_with(&mut collector);
let trait_ref = tcx.impl_trait_ref(def_id);
trait_ref.instantiate_identity().visit_with(&mut collector);
}
debug!("visit self_ty");

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

@ -1387,10 +1387,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
(_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
// `Self` in an impl of a trait -- we have a concrete self type and a
// trait reference.
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
// A cycle error occurred, most likely.
self.dcx().span_bug(span, "expected cycle error");
};
let trait_ref = tcx.impl_trait_ref(impl_def_id);
self.probe_single_bound_for_assoc_item(
|| {
@ -1618,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

@ -56,6 +56,7 @@ mod min_specialization;
pub(crate) fn check_impl_wf(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
of_trait: bool,
) -> Result<(), ErrorGuaranteed> {
debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. });
@ -63,9 +64,9 @@ pub(crate) fn check_impl_wf(
// since unconstrained type/const params cause ICEs in projection, so we want to
// detect those specifically and project those to `TyKind::Error`.
let mut res = tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id);
res = res.and(enforce_impl_lifetime_params_are_constrained(tcx, impl_def_id));
res = res.and(enforce_impl_lifetime_params_are_constrained(tcx, impl_def_id, of_trait));
if tcx.features().min_specialization() {
if of_trait && tcx.features().min_specialization() {
res = res.and(check_min_specialization(tcx, impl_def_id));
}
res
@ -74,6 +75,7 @@ pub(crate) fn check_impl_wf(
pub(crate) fn enforce_impl_lifetime_params_are_constrained(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
of_trait: bool,
) -> Result<(), ErrorGuaranteed> {
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
@ -83,7 +85,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
let impl_generics = tcx.generics_of(impl_def_id);
let impl_predicates = tcx.predicates_of(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
let impl_trait_ref = of_trait.then(|| tcx.impl_trait_ref(impl_def_id).instantiate_identity());
impl_trait_ref.error_reported()?;
@ -171,7 +173,8 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained(
let impl_generics = tcx.generics_of(impl_def_id);
let impl_predicates = tcx.predicates_of(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
let impl_trait_ref =
tcx.impl_opt_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
impl_trait_ref.error_reported()?;

View file

@ -93,7 +93,7 @@ pub(super) fn check_min_specialization(
}
fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option<Node> {
let trait_ref = tcx.impl_trait_ref(impl1_def_id)?;
let trait_ref = tcx.impl_trait_ref(impl1_def_id);
let trait_def = tcx.trait_def(trait_ref.skip_binder().def_id);
let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?;
@ -215,7 +215,7 @@ fn unconstrained_parent_impl_args<'tcx>(
let impl_generic_predicates = tcx.predicates_of(impl_def_id);
let mut unconstrained_parameters = FxHashSet::default();
let mut constrained_params = FxHashSet::default();
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity();
// Unfortunately the functions in `constrained_generic_parameters` don't do
// what we want here. We want only a list of constrained parameters while
@ -224,7 +224,7 @@ fn unconstrained_parent_impl_args<'tcx>(
for (clause, _) in impl_generic_predicates.predicates.iter() {
if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() {
let unbound_trait_ref = proj.projection_term.trait_ref(tcx);
if Some(unbound_trait_ref) == impl_trait_ref {
if unbound_trait_ref == impl_trait_ref {
continue;
}
@ -373,7 +373,7 @@ fn check_predicates<'tcx>(
.map(|(c, _span)| c.as_predicate());
// Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
for arg in tcx.impl_trait_ref(impl1_def_id).instantiate_identity().args {
let Some(term) = arg.as_term() else {
continue;
};

View file

@ -3629,7 +3629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ocx = ObligationCtxt::new_with_diagnostics(self);
let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
let impl_trait_ref =
self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args);
self.tcx.impl_trait_ref(impl_def_id).instantiate(self.tcx, impl_args);
let cause = self.misc(base_expr.span);
// Match the impl self type against the base ty. If this fails,

View file

@ -711,7 +711,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
} else {
self.tcx
.impl_trait_ref(obligation.impl_or_alias_def_id)
.impl_opt_trait_ref(obligation.impl_or_alias_def_id)
.map(|impl_def| impl_def.skip_binder())
// It is possible that this is absent. In this case, we make no progress.
.ok_or(expr)?

View file

@ -285,7 +285,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
&& let ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container
{
let impl_def_id = item.container_id(tcx);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity();
let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
tcx,
impl_def_id,

View file

@ -18,8 +18,8 @@ use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
};
use rustc_middle::ty::{
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
TypeVisitableExt, UserArgs,
self, AssocContainer, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt,
TypeFoldable, TypeVisitableExt, UserArgs,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{DUMMY_SP, Span};
@ -272,7 +272,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
probe::InherentImplPick => {
let impl_def_id = pick.item.container_id(self.tcx);
assert!(
self.tcx.impl_trait_ref(impl_def_id).is_none(),
matches!(pick.item.container, AssocContainer::InherentImpl),
"impl {impl_def_id:?} is not an inherent impl"
);
self.fresh_args_for_item(self.span, impl_def_id)

View file

@ -242,7 +242,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *source {
// Note: this cannot come from an inherent impl,
// because the first probing succeeded.
CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def),
CandidateSource::Impl(def) => Some(self.tcx.impl_trait_id(def)),
CandidateSource::Trait(_) => None,
}
})

View file

@ -1176,9 +1176,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// things failed, so lets look at all traits, for diagnostic purposes now:
self.reset();
let span = self.span;
let tcx = self.tcx;
self.assemble_extension_candidates_for_all_traits();
let out_of_scope_traits = match self.pick_core(&mut Vec::new()) {
@ -1187,10 +1184,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
.into_iter()
.map(|source| match source {
CandidateSource::Trait(id) => id,
CandidateSource::Impl(impl_id) => match tcx.trait_id_of_impl(impl_id) {
Some(id) => id,
None => span_bug!(span, "found inherent method when looking at traits"),
},
CandidateSource::Impl(impl_id) => self.tcx.impl_trait_id(impl_id),
})
.collect(),
Some(Err(MethodError::NoMatch(NoMatchData {

View file

@ -1962,8 +1962,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Provide the best span we can. Use the item, if local to crate, else
// the impl, if local to crate (item may be defaulted), else nothing.
let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
self.associated_value(impl_trait_ref.skip_binder().def_id, item_name)
let impl_trait_id = self.tcx.impl_opt_trait_id(impl_did)?;
self.associated_value(impl_trait_id, item_name)
}) else {
continue;
};
@ -1978,7 +1978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let impl_ty = self.tcx.at(span).type_of(impl_did).instantiate_identity();
let insertion = match self.tcx.impl_trait_ref(impl_did) {
let insertion = match self.tcx.impl_opt_trait_ref(impl_did) {
None => String::new(),
Some(trait_ref) => {
format!(
@ -2013,7 +2013,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.note(note_str);
}
if let Some(sugg_span) = sugg_span
&& let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did)
&& let Some(trait_ref) = self.tcx.impl_opt_trait_ref(impl_did)
&& let Some(sugg) = print_disambiguation_help(
self.tcx,
err,
@ -3720,7 +3720,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
static_candidates.iter().all(|sc| match *sc {
CandidateSource::Trait(def_id) => def_id != info.def_id,
CandidateSource::Impl(def_id) => {
self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
self.tcx.impl_opt_trait_id(def_id) != Some(info.def_id)
}
})
})
@ -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

@ -1,14 +1,12 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::find_attr;
use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::Symbol;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::def_id::DefId;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
use crate::{LateContext, LateLintPass};
@ -52,27 +50,24 @@ declare_lint! {
@feature_gate = default_field_values;
}
#[derive(Default)]
pub(crate) struct DefaultCouldBeDerived;
impl_lint_pass!(DefaultCouldBeDerived => [DEFAULT_OVERRIDES_DEFAULT_FIELDS]);
declare_lint_pass!(DefaultCouldBeDerived => [DEFAULT_OVERRIDES_DEFAULT_FIELDS]);
impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
// Look for manual implementations of `Default`.
let Some(default_def_id) = cx.tcx.get_diagnostic_item(sym::Default) else { return };
let hir::ImplItemImplKind::Trait { trait_item_def_id, .. } = impl_item.impl_kind else {
return;
};
if !trait_item_def_id.is_ok_and(|id| cx.tcx.is_diagnostic_item(sym::default_fn, id)) {
return;
}
let hir::ImplItemKind::Fn(_sig, body_id) = impl_item.kind else { return };
let parent = cx.tcx.parent(impl_item.owner_id.to_def_id());
if find_attr!(cx.tcx.get_all_attrs(parent), AttributeKind::AutomaticallyDerived(..)) {
let impl_id = cx.tcx.local_parent(impl_item.owner_id.def_id);
if cx.tcx.is_automatically_derived(impl_id.to_def_id()) {
// We don't care about what `#[derive(Default)]` produces in this lint.
return;
}
let Some(trait_ref) = cx.tcx.impl_trait_ref(parent) else { return };
let trait_ref = trait_ref.instantiate_identity();
if trait_ref.def_id != default_def_id {
return;
}
let ty = trait_ref.self_ty();
let ty = cx.tcx.type_of(impl_id).instantiate_identity();
let ty::Adt(def, _) = ty.kind() else { return };
// We now know we have a manually written definition of a `<Type as Default>::default()`.
@ -150,11 +145,10 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
return;
}
let Some(local) = parent.as_local() else { return };
let hir_id = cx.tcx.local_def_id_to_hir_id(local);
let hir::Node::Item(item) = cx.tcx.hir_node(hir_id) else { return };
cx.tcx.node_span_lint(DEFAULT_OVERRIDES_DEFAULT_FIELDS, hir_id, item.span, |diag| {
mk_lint(cx.tcx, diag, type_def_id, parent, orig_fields, fields);
let hir_id = cx.tcx.local_def_id_to_hir_id(impl_id);
let span = cx.tcx.hir_span_with_body(hir_id);
cx.tcx.node_span_lint(DEFAULT_OVERRIDES_DEFAULT_FIELDS, hir_id, span, |diag| {
mk_lint(cx.tcx, diag, type_def_id, orig_fields, fields, span);
});
}
}
@ -163,9 +157,9 @@ fn mk_lint(
tcx: TyCtxt<'_>,
diag: &mut Diag<'_, ()>,
type_def_id: DefId,
impl_def_id: DefId,
orig_fields: FxHashMap<Symbol, &hir::FieldDef<'_>>,
fields: &[hir::ExprField<'_>],
impl_span: Span,
) {
diag.primary_message("`Default` impl doesn't use the declared default field values");
@ -186,18 +180,14 @@ fn mk_lint(
if removed_all_fields {
let msg = "to avoid divergence in behavior between `Struct { .. }` and \
`<Struct as Default>::default()`, derive the `Default`";
if let Some(hir::Node::Item(impl_)) = tcx.hir_get_if_local(impl_def_id) {
diag.multipart_suggestion_verbose(
msg,
vec![
(tcx.def_span(type_def_id).shrink_to_lo(), "#[derive(Default)] ".to_string()),
(impl_.span, String::new()),
],
Applicability::MachineApplicable,
);
} else {
diag.help(msg);
}
diag.multipart_suggestion_verbose(
msg,
vec![
(tcx.def_span(type_def_id).shrink_to_lo(), "#[derive(Default)] ".to_string()),
(impl_span, String::new()),
],
Applicability::MachineApplicable,
);
} else {
let msg = "use the default values in the `impl` with `Struct { mandatory_field, .. }` to \
avoid them diverging over time";

View file

@ -191,7 +191,7 @@ late_lint_methods!(
BuiltinCombinedModuleLateLintPass,
[
ForLoopsOverFallibles: ForLoopsOverFallibles,
DefaultCouldBeDerived: DefaultCouldBeDerived::default(),
DefaultCouldBeDerived: DefaultCouldBeDerived,
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
DropForgetUseless: DropForgetUseless,
ImproperCTypesLint: ImproperCTypesLint,

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

@ -679,7 +679,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
}
fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> {
self.impl_trait_ref(impl_def_id).unwrap()
self.impl_trait_ref(impl_def_id)
}
fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity {
@ -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 {
@ -3530,19 +3530,6 @@ impl<'tcx> TyCtxt<'tcx> {
crate::dep_graph::make_metadata(self)
}
/// Given an `impl_id`, return the trait it implements.
/// Return `None` if this is an inherent impl.
pub fn impl_trait_ref(
self,
def_id: impl IntoQueryParam<DefId>,
) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> {
Some(self.impl_trait_header(def_id)?.trait_ref)
}
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)
}
pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool {
if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) =
self.coroutine_kind(def_id)

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();
@ -1913,12 +1913,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
/// If it implements no trait, returns `None`.
pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id)
}
/// If the given `DefId` is an associated item, returns the `DefId` and `DefKind` of the parent trait or impl.
pub fn assoc_parent(self, def_id: DefId) -> Option<(DefId, DefKind)> {
if !self.def_kind(def_id).is_assoc() {
@ -1943,6 +1937,14 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
pub fn impl_is_of_trait(self, def_id: impl IntoQueryParam<DefId>) -> bool {
let def_id = def_id.into_query_param();
let DefKind::Impl { of_trait } = self.def_kind(def_id) else {
panic!("expected Impl for {def_id:?}");
};
of_trait
}
/// If the given `DefId` is an associated item of an impl,
/// returns the `DefId` of the impl; otherwise returns `None`.
pub fn impl_of_assoc(self, def_id: DefId) -> Option<DefId> {
@ -1970,6 +1972,40 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
self.impl_trait_header(def_id).polarity
}
/// Given an `impl_id`, return the trait it implements.
pub fn impl_trait_ref(
self,
def_id: impl IntoQueryParam<DefId>,
) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> {
self.impl_trait_header(def_id).trait_ref
}
/// Given an `impl_id`, return the trait it implements.
/// Returns `None` if it is an inherent impl.
pub fn impl_opt_trait_ref(
self,
def_id: impl IntoQueryParam<DefId>,
) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> {
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.
pub fn impl_trait_id(self, def_id: impl IntoQueryParam<DefId>) -> DefId {
self.impl_trait_ref(def_id).skip_binder().def_id
}
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
/// Returns `None` if it is an inherent impl.
pub fn impl_opt_trait_id(self, def_id: impl IntoQueryParam<DefId>) -> Option<DefId> {
let def_id = def_id.into_query_param();
self.impl_is_of_trait(def_id).then(|| self.impl_trait_id(def_id))
}
pub fn is_exportable(self, def_id: DefId) -> bool {
self.exportable_items(def_id.krate).contains(&def_id)
}
@ -2062,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

@ -45,7 +45,7 @@ pub trait Printer<'tcx>: Sized {
) -> Result<(), PrintError> {
let tcx = self.tcx();
let self_ty = tcx.type_of(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
let impl_trait_ref = tcx.impl_opt_trait_ref(impl_def_id);
let (self_ty, impl_trait_ref) = if tcx.generics_of(impl_def_id).count() <= args.len() {
(
self_ty.instantiate(tcx, args),

View file

@ -271,9 +271,7 @@ pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
pub(super) fn trait_impls_in_crate_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
let mut trait_impls = Vec::new();
for id in tcx.hir_free_items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
&& tcx.impl_trait_ref(id.owner_id).is_some()
{
if tcx.def_kind(id.owner_id) == (DefKind::Impl { of_trait: true }) {
trait_impls.push(id.owner_id.to_def_id())
}
}

View file

@ -44,7 +44,7 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
// First check if `body` is an `fn drop()` of `Drop`
if let DefKind::AssocFn = tcx.def_kind(def_id)
&& let Some(impl_id) = tcx.trait_impl_of_assoc(def_id.to_def_id())
&& let trait_ref = tcx.impl_trait_ref(impl_id).unwrap()
&& let trait_ref = tcx.impl_trait_ref(impl_id)
&& tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop)
// avoid erroneous `Drop` impls from causing ICEs below
&& let sig = tcx.fn_sig(def_id).instantiate_identity()

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

@ -649,7 +649,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
if let Some((impl_def_id, DefKind::Impl { of_trait })) = assoc_parent {
if of_trait
&& tcx.sess.opts.incremental.is_some()
&& tcx.is_lang_item(tcx.trait_id_of_impl(impl_def_id).unwrap(), LangItem::Drop)
&& tcx.is_lang_item(tcx.impl_trait_id(impl_def_id), LangItem::Drop)
{
// Put `Drop::drop` into the same cgu as `drop_in_place`
// since `drop_in_place` is the only thing that can

View file

@ -377,7 +377,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
if let hir::ImplItemImplKind::Trait { .. } = impl_item.impl_kind
&& let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id())
&& self.tcx.is_automatically_derived(impl_of)
&& let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity()
&& let trait_ref = self.tcx.impl_trait_ref(impl_of).instantiate_identity()
&& self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads)
{
if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind()
@ -486,12 +486,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
(self.tcx.local_parent(local_def_id), trait_item_id)
}
// impl items are live if the corresponding traits are live
DefKind::Impl { of_trait: true } => (
local_def_id,
self.tcx
.impl_trait_ref(local_def_id)
.and_then(|trait_ref| trait_ref.skip_binder().def_id.as_local()),
),
DefKind::Impl { of_trait: true } => {
(local_def_id, self.tcx.impl_trait_id(local_def_id).as_local())
}
_ => bug!(),
};

View file

@ -404,9 +404,7 @@ fn check_item<'tcx>(
let items = tcx.associated_item_def_ids(id.owner_id);
worklist.extend(items.iter().map(|ii_ref| ii_ref.expect_local()));
let Some(trait_def_id) = tcx.trait_id_of_impl(id.owner_id.to_def_id()) else {
unreachable!();
};
let trait_def_id = tcx.impl_trait_id(id.owner_id.to_def_id());
if !trait_def_id.is_local() {
return;

View file

@ -344,13 +344,14 @@ trait VisibilityLike: Sized {
// associated types for which we can't determine visibility precisely.
fn of_impl<const SHALLOW: bool>(
def_id: LocalDefId,
of_trait: bool,
tcx: TyCtxt<'_>,
effective_visibilities: &EffectiveVisibilities,
) -> Self {
let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
find.visit(tcx.type_of(def_id).instantiate_identity());
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref.instantiate_identity());
if of_trait {
find.visit_trait(tcx.impl_trait_ref(def_id).instantiate_identity());
}
find.min
}
@ -699,13 +700,20 @@ impl<'tcx> EmbargoVisitor<'tcx> {
// its trait if it exists (which require reaching the `DefId`s in them).
let item_ev = EffectiveVisibility::of_impl::<true>(
owner_id.def_id,
of_trait,
self.tcx,
&self.effective_visibilities,
);
self.update_eff_vis(owner_id.def_id, item_ev, None, Level::Direct);
self.reach(owner_id.def_id, item_ev).generics().predicates().ty().trait_ref();
{
let mut reach = self.reach(owner_id.def_id, item_ev);
reach.generics().predicates().ty();
if of_trait {
reach.trait_ref();
}
}
for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
@ -820,9 +828,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
}
fn trait_ref(&mut self) -> &mut Self {
if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) {
self.visit_trait(trait_ref.instantiate_identity());
}
self.visit_trait(self.ev.tcx.impl_trait_ref(self.item_def_id).instantiate_identity());
self
}
}
@ -1395,9 +1401,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
fn trait_ref(&mut self) -> &mut Self {
self.in_primary_interface = true;
if let Some(trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) {
let _ = self.visit_trait(trait_ref.instantiate_identity());
}
let _ = self.visit_trait(self.tcx.impl_trait_ref(self.item_def_id).instantiate_identity());
self
}
@ -1666,7 +1670,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
// A trait impl is public when both its type and its trait are public
// Subitems of trait impls have inherited publicity.
DefKind::Impl { of_trait } => {
let impl_vis = ty::Visibility::of_impl::<false>(def_id, tcx, &Default::default());
let impl_vis =
ty::Visibility::of_impl::<false>(def_id, of_trait, tcx, &Default::default());
// We are using the non-shallow version here, unlike when building the
// effective visisibilities table to avoid large number of false positives.
@ -1679,8 +1684,12 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
// lints shouldn't be emitted even if `from` effective visibility
// is larger than `Priv` nominal visibility and if `Priv` can leak
// in some scenarios due to type inference.
let impl_ev =
EffectiveVisibility::of_impl::<false>(def_id, tcx, self.effective_visibilities);
let impl_ev = EffectiveVisibility::of_impl::<false>(
def_id,
of_trait,
tcx,
self.effective_visibilities,
);
let mut check = self.check(def_id, impl_vis, Some(impl_ev));
@ -1694,7 +1703,10 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
// normalization they produce very ridiculous false positives.
// FIXME: Remove this when full normalization is implemented.
check.skip_assoc_tys = true;
check.ty().trait_ref();
check.ty();
if of_trait {
check.trait_ref();
}
for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
@ -1763,7 +1775,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
}
if let DefKind::Impl { of_trait: true } = tcx.def_kind(def_id) {
let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
let trait_ref = tcx.impl_trait_ref(def_id);
let trait_ref = trait_ref.instantiate_identity();
visitor.span =
tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().trait_ref.path.span;

View file

@ -189,7 +189,7 @@ impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> {
}
pub fn trait_impl(&self, impl_def: DefId) -> EarlyBinder<'tcx, TraitRef<'tcx>> {
self.tcx.impl_trait_ref(impl_def).unwrap()
self.tcx.impl_trait_ref(impl_def)
}
pub fn generics_of(&self, def_id: DefId) -> &'tcx ty::Generics {

View file

@ -10,8 +10,9 @@ use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_middle::bug;
use rustc_middle::ty::{
self, ExistentialPredicateStableCmpExt as _, Instance, InstanceKind, IntTy, List, TraitRef, Ty,
TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UintTy,
self, AssocContainer, ExistentialPredicateStableCmpExt as _, Instance, InstanceKind, IntTy,
List, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
UintTy,
};
use rustc_span::def_id::DefId;
use rustc_span::{DUMMY_SP, sym};
@ -466,20 +467,20 @@ fn implemented_method<'tcx>(
let method_id;
let trait_id;
let trait_method;
let ancestor = if let Some(impl_id) = tcx.impl_of_assoc(instance.def_id()) {
// Implementation in an `impl` block
trait_ref = tcx.impl_trait_ref(impl_id)?;
method_id = tcx.trait_item_of(instance.def_id())?;
let assoc = tcx.opt_associated_item(instance.def_id())?;
let ancestor = if let AssocContainer::TraitImpl(Ok(trait_method_id)) = assoc.container {
let impl_id = tcx.parent(instance.def_id());
trait_ref = tcx.impl_trait_ref(impl_id);
method_id = trait_method_id;
trait_method = tcx.associated_item(method_id);
trait_id = trait_ref.skip_binder().def_id;
impl_id
} else if let InstanceKind::Item(def_id) = instance.def
&& let Some(trait_method_bound) = tcx.opt_associated_item(def_id)
} else if let AssocContainer::Trait = assoc.container
&& let InstanceKind::Item(def_id) = instance.def
{
// Provided method in a `trait` block
trait_method = trait_method_bound;
method_id = instance.def_id();
trait_id = tcx.trait_of_assoc(method_id)?;
trait_method = assoc;
method_id = def_id;
trait_id = tcx.parent(method_id);
trait_ref = ty::EarlyBinder::bind(TraitRef::from_assoc(tcx, trait_id, instance.args));
trait_id
} else {

View file

@ -403,7 +403,7 @@ impl<'tcx> Printer<'tcx> for LegacySymbolMangler<'tcx> {
args: &'tcx [GenericArg<'tcx>],
) -> Result<(), PrintError> {
let self_ty = self.tcx.type_of(impl_def_id);
let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id);
let impl_trait_ref = self.tcx.impl_opt_trait_ref(impl_def_id);
let generics = self.tcx.generics_of(impl_def_id);
// We have two cases to worry about here:
// 1. We're printing a nested item inside of an impl item, like an inner

View file

@ -311,7 +311,7 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {
let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
let self_ty = self.tcx.type_of(impl_def_id);
let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id);
let impl_trait_ref = self.tcx.impl_opt_trait_ref(impl_def_id);
let generics = self.tcx.generics_of(impl_def_id);
// We have two cases to worry about here:
// 1. We're printing a nested item inside of an impl item, like an inner

View file

@ -574,7 +574,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(impl_item_def_id.to_def_id()) else {
return;
};
let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
let trait_ref = self.tcx.impl_trait_ref(impl_def_id);
let trait_args = trait_ref
.instantiate_identity()
// Replace the explicit self type with `Self` for better suggestion rendering

View file

@ -47,8 +47,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
);
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
let impl_trait_ref =
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args);
let impl_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
@ -58,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

@ -77,7 +77,7 @@ pub fn call_kind<'tcx>(
let container_id = assoc.container_id(tcx);
match assoc.container {
AssocContainer::InherentImpl => None,
AssocContainer::TraitImpl(_) => tcx.trait_id_of_impl(container_id),
AssocContainer::TraitImpl(_) => Some(tcx.impl_trait_id(container_id)),
AssocContainer::Trait => Some(container_id),
}
});

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

@ -354,7 +354,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
use std::fmt::Write;
let trait_ref = tcx.impl_trait_ref(impl_def_id)?.instantiate_identity();
let trait_ref = tcx.impl_opt_trait_ref(impl_def_id)?.instantiate_identity();
let mut w = "impl".to_owned();
#[derive(Debug, Default)]

View file

@ -44,8 +44,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.tcx.for_each_relevant_impl(trait_pred.def_id(), trait_self_ty, |def_id| {
let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
let impl_trait_ref =
tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
let impl_trait_ref = tcx.impl_trait_ref(def_id).instantiate(tcx, impl_args);
let impl_self_ty = impl_trait_ref.self_ty();

View file

@ -137,8 +137,8 @@ pub fn overlapping_trait_impls(
// Before doing expensive operations like entering an inference context, do
// a quick check via fast_reject to tell if the impl headers could possibly
// unify.
let impl1_args = tcx.impl_trait_ref(impl1_def_id).unwrap().skip_binder().args;
let impl2_args = tcx.impl_trait_ref(impl2_def_id).unwrap().skip_binder().args;
let impl1_args = tcx.impl_trait_ref(impl1_def_id).skip_binder().args;
let impl2_args = tcx.impl_trait_ref(impl2_def_id).skip_binder().args;
let may_overlap =
DeepRejectCtxt::relate_infer_infer(tcx).args_may_unify(impl1_args, impl2_args);
@ -209,8 +209,7 @@ fn fresh_impl_header<'tcx>(
impl_def_id,
impl_args,
self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
trait_ref: is_of_trait
.then(|| tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args)),
trait_ref: is_of_trait.then(|| tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args)),
predicates: tcx
.predicates_of(impl_def_id)
.instantiate(tcx, impl_args)

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

@ -835,10 +835,7 @@ fn is_impossible_associated_item(
let param_env = ty::ParamEnv::empty();
let fresh_args = infcx.fresh_args_for_item(tcx.def_span(impl_def_id), impl_def_id);
let impl_trait_ref = tcx
.impl_trait_ref(impl_def_id)
.expect("expected impl to correspond to trait")
.instantiate(tcx, fresh_args);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, fresh_args);
let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {

View file

@ -1979,7 +1979,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source;
let assoc_item_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let trait_def_id = tcx.impl_trait_id(impl_def_id);
let param_env = obligation.param_env;
let assoc_term = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {

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

@ -117,7 +117,7 @@ pub fn translate_args_with_cause<'tcx>(
param_env, source_impl, source_args, target_node
);
let source_trait_ref =
infcx.tcx.impl_trait_ref(source_impl).unwrap().instantiate(infcx.tcx, source_args);
infcx.tcx.impl_trait_ref(source_impl).instantiate(infcx.tcx, source_args);
// translate the Self and Param parts of the generic parameters, since those
// vary across impls
@ -176,11 +176,7 @@ fn fulfill_implication<'tcx>(
let target_trait_ref = ocx.normalize(
cause,
param_env,
infcx
.tcx
.impl_trait_ref(target_impl)
.expect("expected source impl to be a trait impl")
.instantiate(infcx.tcx, target_args),
infcx.tcx.impl_trait_ref(target_impl).instantiate(infcx.tcx, target_args),
);
// do the impls unify? If not, no specialization.
@ -256,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:
//
@ -307,11 +303,7 @@ pub(super) fn specializes(
let parent_impl_trait_ref = ocx.normalize(
cause,
param_env,
infcx
.tcx
.impl_trait_ref(parent_impl_def_id)
.expect("expected source impl to be a trait impl")
.instantiate(infcx.tcx, parent_args),
infcx.tcx.impl_trait_ref(parent_impl_def_id).instantiate(infcx.tcx, parent_args),
);
// do the impls unify? If not, no specialization.

View file

@ -38,7 +38,7 @@ enum Inserted<'tcx> {
impl<'tcx> Children {
/// Insert an impl into this set of children without comparing to any existing impls.
fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
let trait_ref = tcx.impl_trait_ref(impl_def_id).skip_binder();
if let Some(st) =
fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer)
{
@ -54,7 +54,7 @@ impl<'tcx> Children {
/// an impl with a parent. The impl must be present in the list of
/// children already.
fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
let trait_ref = tcx.impl_trait_ref(impl_def_id).skip_binder();
let vec: &mut Vec<DefId>;
if let Some(st) =
fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer)
@ -164,7 +164,7 @@ impl<'tcx> Children {
if le && !ge {
debug!(
"descending as child of TraitRef {:?}",
tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity()
tcx.impl_trait_ref(possible_sibling).instantiate_identity()
);
// The impl specializes `possible_sibling`.
@ -172,7 +172,7 @@ impl<'tcx> Children {
} else if ge && !le {
debug!(
"placing as parent of TraitRef {:?}",
tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity()
tcx.impl_trait_ref(possible_sibling).instantiate_identity()
);
replace_children.push(possible_sibling);
@ -242,7 +242,7 @@ impl<'tcx> Graph {
assert!(impl_def_id.is_local());
// FIXME: use `EarlyBinder` in `self.children`
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
let trait_ref = tcx.impl_trait_ref(impl_def_id).skip_binder();
let trait_def_id = trait_ref.def_id;
debug!(
@ -354,7 +354,7 @@ pub(crate) fn assoc_def(
impl_def_id: DefId,
assoc_def_id: DefId,
) -> Result<LeafDef, ErrorGuaranteed> {
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let trait_def_id = tcx.impl_trait_id(impl_def_id);
let trait_def = tcx.trait_def(trait_def_id);
// This function may be called while we are still building the

View file

@ -42,12 +42,14 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
));
tcx.arena.alloc_slice(&assumed_wf_types)
}
DefKind::Impl { .. } => {
DefKind::Impl { of_trait } => {
// Trait arguments and the self type for trait impls or only the self type for
// inherent impls.
let tys = match tcx.impl_trait_ref(def_id) {
Some(trait_ref) => trait_ref.skip_binder().args.types().collect(),
None => vec![tcx.type_of(def_id).instantiate_identity()],
let tys = if of_trait {
let trait_ref = tcx.impl_trait_ref(def_id);
trait_ref.skip_binder().args.types().collect()
} else {
vec![tcx.type_of(def_id).instantiate_identity()]
};
let mut impl_spans = impl_spans(tcx, def_id);
@ -111,7 +113,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
tcx,
impl_def_id.to_def_id(),
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args,
tcx.impl_trait_ref(impl_def_id).instantiate_identity().args,
);
tcx.arena.alloc_from_iter(
ty::EarlyBinder::bind(tcx.assumed_wf_types_for_rpitit(rpitit_def_id))

View file

@ -131,7 +131,7 @@ fn resolve_associated_item<'tcx>(
assert!(!rcvr_args.has_infer());
assert!(!trait_ref.has_infer());
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
let trait_def_id = tcx.impl_trait_id(impl_data.impl_def_id);
let trait_def = tcx.trait_def(trait_def_id);
let leaf_def = trait_def
.ancestors(tcx, impl_data.impl_def_id)?

View file

@ -62,24 +62,6 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
self.span = old;
}
fn parent_impl_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
let parent = self.parent()?;
if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity())
} else {
None
}
}
fn parent(&self) -> Option<LocalDefId> {
match self.tcx.def_kind(self.item) {
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
Some(self.tcx.local_parent(self.item))
}
_ => None,
}
}
#[instrument(level = "trace", skip(self))]
fn collect_taits_declared_in_body(&mut self) {
let body = self.tcx.hir_body_owned_by(self.item).value;
@ -236,13 +218,12 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
// This avoids having to do normalization of `Self::AssocTy` by only
// supporting the case of a method defining opaque types from assoc types
// in the same impl block.
if let Some(impl_trait_ref) = self.parent_impl_trait_ref() {
if let Some(parent) = self.tcx.trait_impl_of_assoc(self.item.to_def_id()) {
let impl_trait_ref = self.tcx.impl_trait_ref(parent).instantiate_identity();
// If the trait ref of the associated item and the impl differs,
// then we can't use the impl's identity args below, so
// just skip.
if alias_ty.trait_ref(self.tcx) == impl_trait_ref {
let parent = self.parent().expect("we should have a parent here");
for &assoc in self.tcx.associated_items(parent).in_definition_order() {
trace!(?assoc);
if assoc.expect_trait_impl() != Ok(alias_ty.def_id) {

View file

@ -88,7 +88,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
DefKind::Impl { of_trait } => {
if of_trait {
let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().trait_ref.path.span;
let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..];
let args = &tcx.impl_trait_ref(item).instantiate_identity().args[1..];
try_visit!(visitor.visit(span, args));
}
let span = match tcx.hir_node_by_def_id(item).ty() {

View file

@ -34,7 +34,7 @@ pub(crate) fn synthesize_blanket_impls(
'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() {
trace!("considering impl `{impl_def_id:?}` for trait `{trait_def_id:?}`");
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
let trait_ref = tcx.impl_trait_ref(impl_def_id);
if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
continue;
}

View file

@ -448,7 +448,7 @@ pub(crate) fn build_impl(
let tcx = cx.tcx;
let _prof_timer = tcx.sess.prof.generic_activity("build_impl");
let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder);
let associated_trait = tcx.impl_opt_trait_ref(did).map(ty::EarlyBinder::skip_binder);
// Do not inline compiler-internal items unless we're a compiler-internal crate.
let is_compiler_internal = |did| {
@ -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 {

View file

@ -2403,7 +2403,7 @@ fn get_id_for_impl(tcx: TyCtxt<'_>, impl_id: ItemId) -> String {
(ty, Some(ty::TraitRef::new(tcx, trait_, [ty])))
}
ItemId::Blanket { impl_id, .. } | ItemId::DefId(impl_id) => {
if let Some(trait_ref) = tcx.impl_trait_ref(impl_id) {
if let Some(trait_ref) = tcx.impl_opt_trait_ref(impl_id) {
let trait_ref = trait_ref.skip_binder();
(trait_ref.self_ty(), Some(trait_ref))
} else {

View file

@ -847,7 +847,7 @@ fn trait_impls_for<'a>(
for &trait_ in tcx.doc_link_traits_in_scope(module) {
tcx.for_each_relevant_impl(trait_, ty, |impl_| {
let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
let trait_ref = tcx.impl_trait_ref(impl_);
// Check if these are the same type.
let impl_type = trait_ref.skip_binder().self_ty();
trace!(

View file

@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
return;
}
let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
let trait_ref = cx.tcx.impl_trait_ref(impl_id);
// Only care about `impl PartialOrd<Foo> for Foo`
// For `impl PartialOrd<B> for A, input_types is [A, B]

View file

@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(
return;
}
let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
let trait_ref = cx.tcx.impl_trait_ref(impl_id);
// Only care about `impl PartialEq<Foo> for Foo`
// For `impl PartialEq<B> for A, input_types is [A, B]

View file

@ -52,11 +52,9 @@ declare_lint_pass!(FallibleImplFrom => [FALLIBLE_IMPL_FROM]);
impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
// check for `impl From<???> for ..`
if let hir::ItemKind::Impl(_) = &item.kind
&& let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
&& cx
.tcx
.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id)
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = &item.kind
&& let impl_trait_id = cx.tcx.impl_trait_id(item.owner_id)
&& cx.tcx.is_diagnostic_item(sym::From, impl_trait_id)
{
lint_impl_body(cx, item.owner_id, item.span);
}

View file

@ -76,8 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
// `impl Into<target_ty> for self_ty`
&& let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
&& span_is_local(item.span)
&& let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
.map(ty::EarlyBinder::instantiate_identity)
&& let middle_trait_ref = cx.tcx.impl_trait_ref(item.owner_id).instantiate_identity()
&& cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)
&& !matches!(middle_trait_ref.args.type_at(1).kind(), ty::Alias(ty::Opaque, _))
&& self.msrv.meets(cx, msrvs::RE_REBALANCING_COHERENCE)

View file

@ -339,8 +339,7 @@ fn check_with_condition<'tcx>(
ExprKind::Path(QPath::TypeRelative(_, name)) => {
if name.ident.name == sym::MIN
&& let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_assoc(const_id)
&& let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
&& let Some(impl_id) = cx.tcx.inherent_impl_of_assoc(const_id)
&& cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
{
print_lint_and_sugg(cx, var_name, expr);
@ -350,8 +349,7 @@ fn check_with_condition<'tcx>(
if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind
&& name.ident.name == sym::min_value
&& let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_assoc(func_id)
&& let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
&& let Some(impl_id) = cx.tcx.inherent_impl_of_assoc(func_id)
&& cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
{
print_lint_and_sugg(cx, var_name, expr);

View file

@ -10,8 +10,7 @@ use super::SUSPICIOUS_SPLITN;
pub(super) fn check(cx: &LateContext<'_>, method_name: Symbol, expr: &Expr<'_>, self_arg: &Expr<'_>, count: u128) {
if count <= 1
&& let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_assoc(call_id)
&& cx.tcx.impl_trait_ref(impl_id).is_none()
&& let Some(impl_id) = cx.tcx.inherent_impl_of_assoc(call_id)
&& let self_ty = cx.tcx.type_of(impl_id).instantiate_identity()
&& (self_ty.is_slice() || self_ty.is_str())
{

View file

@ -167,7 +167,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
let container_id = assoc_item.container_id(cx.tcx);
let trait_def_id = match assoc_item.container {
AssocContainer::Trait => Some(container_id),
AssocContainer::TraitImpl(_) => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
AssocContainer::TraitImpl(_) => Some(cx.tcx.impl_trait_id(container_id)),
AssocContainer::InherentImpl => None,
};

View file

@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{Block, Body, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, LangItem, UnOp};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::{EarlyBinder, TyCtxt, TypeckResults};
use rustc_middle::ty::{TyCtxt, TypeckResults};
use rustc_session::impl_lint_pass;
use rustc_span::sym;
use rustc_span::symbol::kw;
@ -173,10 +173,11 @@ impl LateLintPass<'_> for NonCanonicalImpls {
}
});
let trait_impl = cx.tcx.impl_trait_ref(item.owner_id).skip_binder();
match trait_ {
Trait::Clone => {
if let Some(copy_trait) = self.copy_trait
&& let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder)
&& implements_trait(cx, trait_impl.self_ty(), copy_trait, &[])
{
for (assoc, _, block) in assoc_fns {
@ -185,10 +186,9 @@ impl LateLintPass<'_> for NonCanonicalImpls {
}
},
Trait::PartialOrd => {
if let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder)
// If `Self` and `Rhs` are not the same type, then a corresponding `Ord` impl is not possible,
// since it doesn't have an `Rhs`
&& let [lhs, rhs] = trait_impl.args.as_slice()
// If `Self` and `Rhs` are not the same type, then a corresponding `Ord` impl is not possible,
// since it doesn't have an `Rhs`
if let [lhs, rhs] = trait_impl.args.as_slice()
&& lhs == rhs
&& let Some(ord_trait) = self.ord_trait
&& implements_trait(cx, trait_impl.self_ty(), ord_trait, &[])

View file

@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
&& send_trait == trait_id
&& of_trait.polarity == ImplPolarity::Positive
&& let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
&& let ty_trait_ref = cx.tcx.impl_trait_ref(item.owner_id)
&& let self_ty = ty_trait_ref.instantiate_identity().self_ty()
&& let ty::Adt(adt_def, impl_trait_args) = self_ty.kind()
{

View file

@ -6,9 +6,9 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::hir_id::HirIdMap;
use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Node, PatKind, TraitItem, TraitItemKind};
use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemImplKind, ImplItemKind, Node, PatKind, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, ConstKind, EarlyBinder, GenericArgKind, GenericArgsRef};
use rustc_middle::ty::{self, ConstKind, GenericArgKind, GenericArgsRef};
use rustc_session::impl_lint_pass;
use rustc_span::Span;
use rustc_span::symbol::{Ident, kw};
@ -320,15 +320,14 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
Node::ImplItem(&ImplItem {
kind: ImplItemKind::Fn(ref sig, _),
owner_id,
impl_kind,
..
}) => {
if let Node::Item(item) = cx.tcx.parent_hir_node(owner_id.into())
&& let Some(trait_ref) = cx
.tcx
.impl_trait_ref(item.owner_id)
.map(EarlyBinder::instantiate_identity)
&& let Some(trait_item_id) = cx.tcx.trait_item_of(owner_id)
if let ImplItemImplKind::Trait { trait_item_def_id, .. } = impl_kind
&& let Ok(trait_item_id) = trait_item_def_id
{
let impl_id = cx.tcx.parent(owner_id.into());
let trait_ref = cx.tcx.impl_trait_ref(impl_id).instantiate_identity();
(
trait_item_id,
FnKind::ImplTraitFn(

View file

@ -113,10 +113,9 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse {
) {
if matches!(kind, FnKind::Method(_, _))
// We are only interested in methods, not in functions or associated functions.
&& let Some(impl_def) = cx.tcx.impl_of_assoc(fn_def.to_def_id())
// We don't want this method to be te implementation of a trait because the
// `#[must_use]` should be put on the trait definition directly.
&& cx.tcx.trait_id_of_impl(impl_def).is_none()
&& cx.tcx.inherent_impl_of_assoc(fn_def.to_def_id()).is_some()
{
let hir_id = cx.tcx.local_def_id_to_hir_id(fn_def);
check_method(cx, decl, fn_def, span, hir_id.expect_owner());

View file

@ -85,9 +85,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
/// get desugared to match.
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'tcx>) {
let fn_def_id = block.hir_id.owner.to_def_id();
if let Some(impl_id) = cx.tcx.impl_of_assoc(fn_def_id)
&& let Some(trait_id) = cx.tcx.trait_id_of_impl(impl_id)
{
if let Some(impl_id) = cx.tcx.trait_impl_of_assoc(fn_def_id) {
let trait_id = cx.tcx.impl_trait_id(impl_id);
// We don't want to lint inside io::Read or io::Write implementations, as the author has more
// information about their trait implementation than our lint, see https://github.com/rust-lang/rust-clippy/issues/4836
if let Some(trait_name) = cx.tcx.get_diagnostic_name(trait_id)

View file

@ -10,7 +10,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
use rustc_hir::{
self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParamKind, HirId, Impl,
ImplItemKind, Item, ItemKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, Ty, TyKind,
ImplItemImplKind, ImplItemKind, Item, ItemKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, Ty, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty as MiddleTy;
@ -142,13 +142,14 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
// We want to skip types in trait `impl`s that aren't declared as `Self` in the trait
// declaration. The collection of those types is all this method implementation does.
if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind
&& let ImplItemImplKind::Trait { .. } = impl_item.impl_kind
&& let Some(&mut StackItem::Check {
impl_id,
ref mut types_to_skip,
..
}) = self.stack.last_mut()
&& let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id)
{
let impl_trait_ref = cx.tcx.impl_trait_ref(impl_id);
// `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
// `Self`.
let self_ty = impl_trait_ref.instantiate_identity().self_ty();

View file

@ -26,10 +26,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
items,
..
}) = &item.kind
&& let Some(trait_ref) = cx
.tcx
.impl_trait_ref(item.owner_id)
.map(EarlyBinder::instantiate_identity)
&& let trait_ref = cx.tcx.impl_trait_ref(item.owner_id).instantiate_identity()
&& internal_paths::EARLY_LINT_PASS.matches(cx, trait_ref.def_id)
&& let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind()
&& self_ty_def.is_struct()