1
Fork 0

Auto merge of #79322 - jyn514:refactor-impl, r=estebank

Separate out a `hir::Impl` struct

This makes it possible to pass the `Impl` directly to functions, instead
of having to pass each of the many fields one at a time. It also
simplifies matches in many cases.

See `rustc_save_analysis::dump_visitor::process_impl` or `rustdoc::clean::clean_impl` for a good example of how this makes `impl`s easier to work with.

r? `@petrochenkov` maybe?
This commit is contained in:
bors 2021-01-13 01:40:41 +00:00
commit 150d1fee04
61 changed files with 258 additions and 246 deletions

View file

@ -2011,11 +2011,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"generic `Self` types are currently not permitted in anonymous constants",
);
if let Some(hir::Node::Item(&hir::Item {
kind: hir::ItemKind::Impl { self_ty, .. },
kind: hir::ItemKind::Impl(ref impl_),
..
})) = tcx.hir().get_if_local(def_id)
{
err.span_note(self_ty.span, "not a concrete type");
err.span_note(impl_.self_ty.span, "not a concrete type");
}
err.emit();
tcx.ty_error()

View file

@ -692,11 +692,17 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
}
hir::ItemKind::Fn(..) => {} // entirely within check_item_body
hir::ItemKind::Impl { ref items, .. } => {
hir::ItemKind::Impl(ref impl_) => {
debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id);
let impl_def_id = tcx.hir().local_def_id(it.hir_id);
if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
check_impl_items_against_trait(tcx, it.span, impl_def_id, impl_trait_ref, items);
check_impl_items_against_trait(
tcx,
it.span,
impl_def_id,
impl_trait_ref,
&impl_.items,
);
let trait_def_id = impl_trait_ref.def_id;
check_on_unimplemented(tcx, trait_def_id, it);
}

View file

@ -103,35 +103,28 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
//
// won't be allowed unless there's an *explicit* implementation of `Send`
// for `T`
hir::ItemKind::Impl {
defaultness,
defaultness_span,
polarity,
ref of_trait,
ref self_ty,
..
} => {
hir::ItemKind::Impl(ref impl_) => {
let is_auto = tcx
.impl_trait_ref(tcx.hir().local_def_id(item.hir_id))
.map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
let sp = of_trait.as_ref().map(|t| t.path.span).unwrap_or(item.span);
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map(|t| t.path.span).unwrap_or(item.span);
let mut err =
tcx.sess.struct_span_err(sp, "impls of auto traits cannot be default");
err.span_labels(defaultness_span, "default because of this");
err.span_labels(impl_.defaultness_span, "default because of this");
err.span_label(sp, "auto trait");
err.emit();
}
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
match (tcx.impl_polarity(def_id), polarity) {
match (tcx.impl_polarity(def_id), impl_.polarity) {
(ty::ImplPolarity::Positive, _) => {
check_impl(tcx, item, self_ty, of_trait);
check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
}
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
// FIXME(#27579): what amount of WF checking do we need for neg impls?
if let hir::Defaultness::Default { .. } = defaultness {
if let hir::Defaultness::Default { .. } = impl_.defaultness {
let mut spans = vec![span];
spans.extend(defaultness_span);
spans.extend(impl_.defaultness_span);
struct_span_err!(
tcx.sess,
spans,

View file

@ -55,7 +55,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
let sp = match tcx.hir().expect_item(impl_hir_id).kind {
ItemKind::Impl { self_ty, .. } => self_ty.span,
ItemKind::Impl(ref impl_) => impl_.self_ty.span,
_ => bug!("expected Drop impl item"),
};
@ -80,7 +80,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
Ok(()) => {}
Err(CopyImplementationError::InfrigingFields(fields)) => {
let item = tcx.hir().expect_item(impl_hir_id);
let span = if let ItemKind::Impl { of_trait: Some(ref tr), .. } = item.kind {
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
tr.path.span
} else {
span
@ -100,7 +100,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
Err(CopyImplementationError::NotAnAdt) => {
let item = tcx.hir().expect_item(impl_hir_id);
let span =
if let ItemKind::Impl { self_ty, .. } = item.kind { self_ty.span } else { span };
if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };
tcx.sess.emit_err(CopyImplOnNonAdt { span });
}
@ -453,7 +453,9 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
return err_info;
} else if diff_fields.len() > 1 {
let item = tcx.hir().expect_item(impl_hir_id);
let span = if let ItemKind::Impl { of_trait: Some(ref t), .. } = item.kind {
let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) =
item.kind
{
t.path.span
} else {
tcx.hir().span(impl_hir_id)

View file

@ -45,7 +45,9 @@ struct InherentCollect<'tcx> {
impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) {
let (ty, assoc_items) = match item.kind {
hir::ItemKind::Impl { of_trait: None, ref self_ty, items, .. } => (self_ty, items),
hir::ItemKind::Impl(hir::Impl { of_trait: None, ref self_ty, items, .. }) => {
(self_ty, items)
}
_ => return,
};

View file

@ -26,7 +26,10 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) {
let def_id = self.tcx.hir().local_def_id(item.hir_id);
// "Trait" impl
if let hir::ItemKind::Impl { generics, of_trait: Some(ref tr), self_ty, .. } = &item.kind {
if let hir::ItemKind::Impl(hir::Impl {
generics, of_trait: Some(ref tr), self_ty, ..
}) = &item.kind
{
debug!(
"coherence2::orphan check: trait impl {}",
self.tcx.hir().node_to_string(item.hir_id)

View file

@ -86,8 +86,13 @@ impl UnsafetyChecker<'tcx> {
impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> {
fn visit_item(&mut self, item: &'v hir::Item<'v>) {
if let hir::ItemKind::Impl { unsafety, polarity, ref generics, .. } = item.kind {
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
self.check_unsafety_coherence(
item,
Some(&impl_.generics),
impl_.unsafety,
impl_.polarity,
);
}
}

View file

@ -189,7 +189,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
| hir::ItemKind::Enum(_, generics)
| hir::ItemKind::TraitAlias(generics, _)
| hir::ItemKind::Trait(_, _, generics, ..)
| hir::ItemKind::Impl { generics, .. }
| hir::ItemKind::Impl(hir::Impl { generics, .. })
| hir::ItemKind::Struct(_, generics) => (generics, true),
hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
| hir::ItemKind::TyAlias(_, generics) => (generics, false),
@ -531,7 +531,7 @@ fn type_param_predicates(
Node::Item(item) => {
match item.kind {
ItemKind::Fn(.., ref generics, _)
| ItemKind::Impl { ref generics, .. }
| ItemKind::Impl(hir::Impl { ref generics, .. })
| ItemKind::TyAlias(_, ref generics)
| ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
| ItemKind::Enum(_, ref generics)
@ -1310,7 +1310,8 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
Node::Item(item) => {
match item.kind {
ItemKind::Fn(.., ref generics, _) | ItemKind::Impl { ref generics, .. } => generics,
ItemKind::Fn(.., ref generics, _)
| ItemKind::Impl(hir::Impl { ref generics, .. }) => generics,
ItemKind::TyAlias(_, ref generics)
| ItemKind::Enum(_, ref generics)
@ -1638,7 +1639,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
match tcx.hir().expect_item(hir_id).kind {
hir::ItemKind::Impl { ref of_trait, .. } => of_trait.as_ref().map(|ast_trait_ref| {
hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
}),
@ -1651,29 +1652,39 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
let item = tcx.hir().expect_item(hir_id);
match &item.kind {
hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Negative(span),
of_trait,
..
}) => {
if is_rustc_reservation {
let span = span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(*span));
tcx.sess.span_err(span, "reservation impls can't be negative");
}
ty::ImplPolarity::Negative
}
hir::ItemKind::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Positive,
of_trait: None,
..
}) => {
if is_rustc_reservation {
tcx.sess.span_err(item.span, "reservation impls can't be inherent");
}
ty::ImplPolarity::Positive
}
hir::ItemKind::Impl {
polarity: hir::ImplPolarity::Positive, of_trait: Some(_), ..
} => {
hir::ItemKind::Impl(hir::Impl {
polarity: hir::ImplPolarity::Positive,
of_trait: Some(_),
..
}) => {
if is_rustc_reservation {
ty::ImplPolarity::Reservation
} else {
ty::ImplPolarity::Positive
}
}
ref item => bug!("impl_polarity: {:?} not an impl", item),
item => bug!("impl_polarity: {:?} not an impl", item),
}
}
@ -1777,11 +1788,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
Node::Item(item) => {
match item.kind {
ItemKind::Impl { defaultness, ref generics, .. } => {
if defaultness.is_default() {
ItemKind::Impl(ref impl_) => {
if impl_.defaultness.is_default() {
is_default_impl_trait = tcx.impl_trait_ref(def_id);
}
generics
&impl_.generics
}
ItemKind::Fn(.., ref generics, _)
| ItemKind::TyAlias(_, ref generics)
@ -2113,14 +2124,14 @@ fn const_evaluatable_predicates_of<'tcx>(
let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
if let hir::Node::Item(item) = node {
if let hir::ItemKind::Impl { ref of_trait, ref self_ty, .. } = item.kind {
if let Some(of_trait) = of_trait {
if let hir::ItemKind::Impl(ref impl_) = item.kind {
if let Some(of_trait) = &impl_.of_trait {
debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
collector.visit_trait_ref(of_trait);
}
debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
collector.visit_ty(self_ty);
collector.visit_ty(impl_.self_ty);
}
}
@ -2952,7 +2963,7 @@ fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span:
if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
let parent_id = tcx.hir().get_parent_item(hir_id);
let parent_item = tcx.hir().expect_item(parent_id);
if let hir::ItemKind::Impl { of_trait: Some(_), .. } = parent_item.kind {
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
tcx.sess
.struct_span_err(
attr_span,

View file

@ -243,9 +243,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
icx.to_ty(ty)
}
}
ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
icx.to_ty(self_ty)
}
ItemKind::TyAlias(ref self_ty, _)
| ItemKind::Impl(hir::Impl { ref self_ty, .. }) => icx.to_ty(self_ty),
ItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
tcx.mk_fn_def(def_id.to_def_id(), substs)

View file

@ -80,10 +80,10 @@ struct ImplWfCheck<'tcx> {
impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
if let hir::ItemKind::Impl { ref items, .. } = item.kind {
if let hir::ItemKind::Impl(ref impl_) = item.kind {
let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
enforce_impl_params_are_constrained(self.tcx, impl_def_id, items);
enforce_impl_items_are_distinct(self.tcx, items);
enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_.items);
enforce_impl_items_are_distinct(self.tcx, impl_.items);
if self.min_specialization {
check_min_specialization(self.tcx, impl_def_id.to_def_id(), item.span);
}