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:
commit
2170b4da84
82 changed files with 296 additions and 337 deletions
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 { .. } => {}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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 }));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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..]);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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()?;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)?
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ late_lint_methods!(
|
|||
BuiltinCombinedModuleLateLintPass,
|
||||
[
|
||||
ForLoopsOverFallibles: ForLoopsOverFallibles,
|
||||
DefaultCouldBeDerived: DefaultCouldBeDerived::default(),
|
||||
DefaultCouldBeDerived: DefaultCouldBeDerived,
|
||||
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
|
||||
DropForgetUseless: DropForgetUseless,
|
||||
ImproperCTypesLint: ImproperCTypesLint,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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<'_>>> {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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!(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)| {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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(()) => {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)?
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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, &[])
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue