Auto merge of #112802 - lukas-code:fancy-bool, r=Nilstrieb

use ErrorGuaranteed instead of booleans in rustc_builtin_macros

implements https://github.com/rust-lang/rust/pull/112366#discussion_r1233821873

No functional changes.

Best reviewed with whitespace diff disabled.

r? `@Nilstrieb`
This commit is contained in:
bors 2023-06-24 11:43:41 +00:00
commit ed1ce580ec
2 changed files with 63 additions and 66 deletions

View File

@ -8,7 +8,7 @@ use rustc_feature::AttributeTemplate;
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::{ErrorGuaranteed, Span};
pub(crate) struct Expander(pub bool); pub(crate) struct Expander(pub bool);
@ -22,7 +22,7 @@ impl MultiItemModifier for Expander {
_: bool, _: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> { ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
let sess = ecx.sess; let sess = ecx.sess;
if report_bad_target(sess, &item, span) { if report_bad_target(sess, &item, span).is_err() {
// We don't want to pass inappropriate targets to derive macros to avoid // We don't want to pass inappropriate targets to derive macros to avoid
// follow up errors, all other errors below are recoverable. // follow up errors, all other errors below are recoverable.
return ExpandResult::Ready(vec![item]); return ExpandResult::Ready(vec![item]);
@ -103,7 +103,11 @@ fn dummy_annotatable() -> Annotatable {
}) })
} }
fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { fn report_bad_target(
sess: &Session,
item: &Annotatable,
span: Span,
) -> Result<(), ErrorGuaranteed> {
let item_kind = match item { let item_kind = match item {
Annotatable::Item(item) => Some(&item.kind), Annotatable::Item(item) => Some(&item.kind),
Annotatable::Stmt(stmt) => match &stmt.kind { Annotatable::Stmt(stmt) => match &stmt.kind {
@ -116,9 +120,9 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
let bad_target = let bad_target =
!matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..))); !matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..)));
if bad_target { if bad_target {
sess.emit_err(errors::BadDeriveTarget { span, item: item.span() }); return Err(sess.emit_err(errors::BadDeriveTarget { span, item: item.span() }));
} }
bad_target Ok(())
} }
fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) { fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {

View File

@ -8,7 +8,7 @@ use rustc_ast_pretty::pprust;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_expand::base::*; use rustc_expand::base::*;
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{FileNameDisplayPreference, Span}; use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
use std::iter; use std::iter;
use thin_vec::{thin_vec, ThinVec}; use thin_vec::{thin_vec, ThinVec};
@ -128,12 +128,15 @@ pub fn expand_test_or_bench(
}; };
}; };
// has_*_signature will report any errors in the type so compilation // check_*_signature will report any errors in the type so compilation
// will fail. We shouldn't try to expand in this case because the errors // will fail. We shouldn't try to expand in this case because the errors
// would be spurious. // would be spurious.
if (!is_bench && !has_test_signature(cx, &item)) let check_result = if is_bench {
|| (is_bench && !has_bench_signature(cx, &item)) check_bench_signature(cx, &item, &fn_)
{ } else {
check_test_signature(cx, &item, &fn_)
};
if check_result.is_err() {
return if is_stmt { return if is_stmt {
vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))] vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
} else { } else {
@ -523,72 +526,62 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
} }
} }
fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { fn check_test_signature(
cx: &ExtCtxt<'_>,
i: &ast::Item,
f: &ast::Fn,
) -> Result<(), ErrorGuaranteed> {
let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
let sd = &cx.sess.parse_sess.span_diagnostic; let sd = &cx.sess.parse_sess.span_diagnostic;
match &i.kind {
ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" });
return false;
}
if let ast::Async::Yes { span, .. } = sig.header.asyncness {
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" });
return false;
}
// If the termination trait is active, the compiler will check that the output if let ast::Unsafe::Yes(span) = f.sig.header.unsafety {
// type implements the `Termination` trait as `libtest` enforces that. return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
let has_output = match &sig.decl.output {
ast::FnRetTy::Default(..) => false,
ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
_ => true,
};
if !sig.decl.inputs.is_empty() {
sd.span_err(i.span, "functions used as tests can not have any arguments");
return false;
}
if has_should_panic_attr && has_output {
sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
return false;
}
if generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime))
{
sd.span_err(
i.span,
"functions used as tests can not have any non-lifetime generic parameters",
);
return false;
}
true
}
_ => {
// should be unreachable because `is_test_fn_item` should catch all non-fn items
debug_assert!(false);
false
}
} }
}
fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { if let ast::Async::Yes { span, .. } = f.sig.header.asyncness {
let has_sig = match &i.kind { return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }));
// N.B., inadequate check, but we're running }
// well before resolve, can't get too deep.
ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1, // If the termination trait is active, the compiler will check that the output
_ => false, // type implements the `Termination` trait as `libtest` enforces that.
let has_output = match &f.sig.decl.output {
ast::FnRetTy::Default(..) => false,
ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
_ => true,
}; };
if !has_sig { if !f.sig.decl.inputs.is_empty() {
cx.sess.parse_sess.span_diagnostic.span_err( return Err(sd.span_err(i.span, "functions used as tests can not have any arguments"));
}
if has_should_panic_attr && has_output {
return Err(sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"));
}
if f.generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime)) {
return Err(sd.span_err(
i.span,
"functions used as tests can not have any non-lifetime generic parameters",
));
}
Ok(())
}
fn check_bench_signature(
cx: &ExtCtxt<'_>,
i: &ast::Item,
f: &ast::Fn,
) -> Result<(), ErrorGuaranteed> {
// N.B., inadequate check, but we're running
// well before resolve, can't get too deep.
if f.sig.decl.inputs.len() != 1 {
return Err(cx.sess.parse_sess.span_diagnostic.span_err(
i.span, i.span,
"functions used as benches must have \ "functions used as benches must have \
signature `fn(&mut Bencher) -> impl Termination`", signature `fn(&mut Bencher) -> impl Termination`",
); ));
} }
has_sig Ok(())
} }