Skip to content

Commit

Permalink
Revert "Remove the impl logic, only keep the macro_rules one"
Browse files Browse the repository at this point in the history
This reverts commit c84776f.
  • Loading branch information
Urgau committed Feb 27, 2024
1 parent c84776f commit 2fc98d7
Show file tree
Hide file tree
Showing 4 changed files with 1,149 additions and 127 deletions.
1 change: 0 additions & 1 deletion compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![allow(dead_code)]
use std::num::NonZero;

use crate::errors::RequestedLevel;
Expand Down
250 changes: 124 additions & 126 deletions compiler/rustc_lint/src/non_local_def.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![allow(warnings)]

use rustc_hir::{Body, Item, ItemKind, OwnerNode, Path, QPath, TyKind};
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::{sym, symbol::kw, symbol::Ident, ExpnKind, MacroKind};
Expand Down Expand Up @@ -94,130 +92,130 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
};

match item.kind {
// ItemKind::Impl(impl_) => {
// // The RFC states:
// //
// // > An item nested inside an expression-containing item (through any
// // > level of nesting) may not define an impl Trait for Type unless
// // > either the **Trait** or the **Type** is also nested inside the
// // > same expression-containing item.
// //
// // To achieve this we get try to get the paths of the _Trait_ and
// // _Type_, and we look inside thoses paths to try a find in one
// // of them a type whose parent is the same as the impl definition.
// //
// // If that's the case this means that this impl block declaration
// // is using local items and so we don't lint on it.
//
// let mut parent_node_is_anon_const = {
// let mut parent_node_is_anon_const = None;
// move || {
// *parent_node_is_anon_const.get_or_insert_with(|| {
// matches!(
// parent_node(),
// OwnerNode::Item(Item {
// ident: Ident { name: kw::Underscore, .. },
// kind: ItemKind::Const(..),
// ..
// })
// )
// })
// }
// };
// let mut local_parent = {
// let mut local_parent_cache = None;
// move || {
// *local_parent_cache
// .get_or_insert_with(|| cx.tcx.parent(item.owner_id.to_def_id()))
// }
// };
// let mut extra_local_parent = {
// let mut extra_parent_cache = None;
// move |did| {
// *extra_parent_cache.get_or_insert_with(|| {
// parent_node_is_anon_const().then(|| cx.tcx.parent(did))
// })
// }
// };
//
// let self_ty_has_local_parent = match impl_.self_ty.kind {
// TyKind::Path(QPath::Resolved(_, ty_path)) => path_has_local_parent(
// ty_path,
// cx,
// &mut local_parent,
// &mut extra_local_parent,
// ),
// TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
// path_has_local_parent(
// principle_poly_trait_ref.trait_ref.path,
// cx,
// &mut local_parent,
// &mut extra_local_parent,
// )
// }
// TyKind::TraitObject([], _, _)
// | TyKind::InferDelegation(_, _)
// | TyKind::Slice(_)
// | TyKind::Array(_, _)
// | TyKind::Ptr(_)
// | TyKind::Ref(_, _)
// | TyKind::BareFn(_)
// | TyKind::Never
// | TyKind::Tup(_)
// | TyKind::Path(_)
// | TyKind::AnonAdt(_)
// | TyKind::OpaqueDef(_, _, _)
// | TyKind::Typeof(_)
// | TyKind::Infer
// | TyKind::Err(_) => false,
// };
//
// let of_trait_has_local_parent = impl_
// .of_trait
// .map(|of_trait| {
// path_has_local_parent(
// of_trait.path,
// cx,
// &mut local_parent,
// &mut extra_local_parent,
// )
// })
// .unwrap_or(false);
//
// // If none of them have a local parent (LOGICAL NOR) this means that
// // this impl definition is a non-local definition and so we lint on it.
// if !(self_ty_has_local_parent || of_trait_has_local_parent) {
// // Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in top-level module.
// if parent_node_is_anon_const() && self.body_depth == 1 {
// return;
// }
//
// let const_anon = if self.body_depth == 1
// && let OwnerNode::Item(item) = parent_node()
// && let ItemKind::Const(ty, _, _) = item.kind
// && let TyKind::Tup(&[]) = ty.kind
// {
// Some(item.ident.span)
// } else {
// None
// };
//
// cx.emit_span_lint(
// NON_LOCAL_DEFINITIONS,
// item.span,
// NonLocalDefinitionsDiag::Impl {
// depth: self.body_depth,
// body_kind_descr: "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */,
// body_name: parent_node()
// .ident()
// .map(|s| s.name.to_ident_string())
// .unwrap_or_else(|| "<unnameable>".to_string()),
// cargo_update: cargo_update(),
// const_anon,
// },
// )
// }
// }
ItemKind::Impl(impl_) => {
// The RFC states:
//
// > An item nested inside an expression-containing item (through any
// > level of nesting) may not define an impl Trait for Type unless
// > either the **Trait** or the **Type** is also nested inside the
// > same expression-containing item.
//
// To achieve this we get try to get the paths of the _Trait_ and
// _Type_, and we look inside thoses paths to try a find in one
// of them a type whose parent is the same as the impl definition.
//
// If that's the case this means that this impl block declaration
// is using local items and so we don't lint on it.

let mut parent_node_is_anon_const = {
let mut parent_node_is_anon_const = None;
move || {
*parent_node_is_anon_const.get_or_insert_with(|| {
matches!(
parent_node(),
OwnerNode::Item(Item {
ident: Ident { name: kw::Underscore, .. },
kind: ItemKind::Const(..),
..
})
)
})
}
};
let mut local_parent = {
let mut local_parent_cache = None;
move || {
*local_parent_cache
.get_or_insert_with(|| cx.tcx.parent(item.owner_id.to_def_id()))
}
};
let mut extra_local_parent = {
let mut extra_parent_cache = None;
move |did| {
*extra_parent_cache.get_or_insert_with(|| {
parent_node_is_anon_const().then(|| cx.tcx.parent(did))
})
}
};

let self_ty_has_local_parent = match impl_.self_ty.kind {
TyKind::Path(QPath::Resolved(_, ty_path)) => path_has_local_parent(
ty_path,
cx,
&mut local_parent,
&mut extra_local_parent,
),
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
path_has_local_parent(
principle_poly_trait_ref.trait_ref.path,
cx,
&mut local_parent,
&mut extra_local_parent,
)
}
TyKind::TraitObject([], _, _)
| TyKind::InferDelegation(_, _)
| TyKind::Slice(_)
| TyKind::Array(_, _)
| TyKind::Ptr(_)
| TyKind::Ref(_, _)
| TyKind::BareFn(_)
| TyKind::Never
| TyKind::Tup(_)
| TyKind::Path(_)
| TyKind::AnonAdt(_)
| TyKind::OpaqueDef(_, _, _)
| TyKind::Typeof(_)
| TyKind::Infer
| TyKind::Err(_) => false,
};

let of_trait_has_local_parent = impl_
.of_trait
.map(|of_trait| {
path_has_local_parent(
of_trait.path,
cx,
&mut local_parent,
&mut extra_local_parent,
)
})
.unwrap_or(false);

// If none of them have a local parent (LOGICAL NOR) this means that
// this impl definition is a non-local definition and so we lint on it.
if !(self_ty_has_local_parent || of_trait_has_local_parent) {
// Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in top-level module.
if parent_node_is_anon_const() && self.body_depth == 1 {
return;
}

let const_anon = if self.body_depth == 1
&& let OwnerNode::Item(item) = parent_node()
&& let ItemKind::Const(ty, _, _) = item.kind
&& let TyKind::Tup(&[]) = ty.kind
{
Some(item.ident.span)
} else {
None
};

cx.emit_span_lint(
NON_LOCAL_DEFINITIONS,
item.span,
NonLocalDefinitionsDiag::Impl {
depth: self.body_depth,
body_kind_descr: "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */,
body_name: parent_node()
.ident()
.map(|s| s.name.to_ident_string())
.unwrap_or_else(|| "<unnameable>".to_string()),
cargo_update: cargo_update(),
const_anon,
},
)
}
}
ItemKind::Macro(_macro, MacroKind::Bang)
if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) =>
{
Expand Down
Loading

0 comments on commit 2fc98d7

Please sign in to comment.