Improve proc macro attribute diagnostics
This commit is contained in:
parent
ef4046e4f3
commit
f92000816e
@ -707,3 +707,24 @@ passes_ignored_derived_impls =
|
||||
[one] trait {$trait_list}, but this is
|
||||
*[other] traits {$trait_list}, but these are
|
||||
} intentionally ignored during dead code analysis
|
||||
|
||||
passes_proc_macro_typeerror = mismatched {$kind} signature
|
||||
.label = found {$found}, expected type `proc_macro::TokenStream`
|
||||
.note = {$kind}s must have a signature of `{$expected_signature}`
|
||||
|
||||
passes_proc_macro_diff_arg_count = mismatched {$kind} signature
|
||||
.label = found unexpected {$count ->
|
||||
[one] argument
|
||||
*[other] arguments
|
||||
}
|
||||
.note = {$kind}s must have a signature of `{$expected_signature}`
|
||||
|
||||
passes_proc_macro_missing_args = mismatched {$kind} signature
|
||||
.label = {$kind} must have {$expected_input_count ->
|
||||
[one] one argument
|
||||
*[other] two arguments
|
||||
} of type `proc_macro::TokenStream`
|
||||
|
||||
passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"`
|
||||
|
||||
passes_proc_macro_unsafe = proc macro functions may not be `unsafe`
|
||||
|
@ -6,11 +6,12 @@
|
||||
|
||||
use crate::errors::{
|
||||
self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
|
||||
OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
|
||||
OnlyHasEffectOn, ProcMacroDiffArguments, ProcMacroInvalidAbi, ProcMacroMissingArguments,
|
||||
ProcMacroTypeError, ProcMacroUnsafe, TransparentIncompatible, UnrecognizedReprHint,
|
||||
};
|
||||
use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{fluent, Applicability, MultiSpan};
|
||||
use rustc_errors::{fluent, Applicability, IntoDiagnosticArg, MultiSpan};
|
||||
use rustc_expand::base::resolve_path;
|
||||
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_hir as hir;
|
||||
@ -19,11 +20,11 @@ use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{
|
||||
self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
|
||||
};
|
||||
use rustc_hir::{MethodKind, Target};
|
||||
use rustc_hir::{MethodKind, Target, Unsafety};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::{ParamEnv, TyCtxt};
|
||||
use rustc_session::lint::builtin::{
|
||||
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES,
|
||||
};
|
||||
@ -31,6 +32,7 @@ use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use std::cell::Cell;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
pub(crate) fn target_from_impl_item<'tcx>(
|
||||
@ -62,8 +64,27 @@ enum ItemLike<'tcx> {
|
||||
ForeignItem,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) enum ProcMacroKind {
|
||||
FunctionLike,
|
||||
Derive,
|
||||
Attribute,
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for ProcMacroKind {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||
match self {
|
||||
ProcMacroKind::Attribute => "attribute proc macro",
|
||||
ProcMacroKind::Derive => "derive proc macro",
|
||||
ProcMacroKind::FunctionLike => "function-like proc macro",
|
||||
}
|
||||
.into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
struct CheckAttrVisitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
abort: Cell<bool>,
|
||||
}
|
||||
|
||||
impl CheckAttrVisitor<'_> {
|
||||
@ -172,7 +193,7 @@ impl CheckAttrVisitor<'_> {
|
||||
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
|
||||
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
|
||||
sym::macro_export => self.check_macro_export(hir_id, attr, target),
|
||||
sym::ignore | sym::should_panic | sym::proc_macro_derive => {
|
||||
sym::ignore | sym::should_panic => {
|
||||
self.check_generic_attr(hir_id, attr, target, Target::Fn)
|
||||
}
|
||||
sym::automatically_derived => {
|
||||
@ -182,6 +203,16 @@ impl CheckAttrVisitor<'_> {
|
||||
self.check_generic_attr(hir_id, attr, target, Target::Mod)
|
||||
}
|
||||
sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
|
||||
sym::proc_macro => {
|
||||
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
|
||||
}
|
||||
sym::proc_macro_attribute => {
|
||||
self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
|
||||
}
|
||||
sym::proc_macro_derive => {
|
||||
self.check_generic_attr(hir_id, attr, target, Target::Fn);
|
||||
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -2052,6 +2083,90 @@ impl CheckAttrVisitor<'_> {
|
||||
errors::Unused { attr_span: attr.span, note },
|
||||
);
|
||||
}
|
||||
|
||||
fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
|
||||
let expected_input_count = match kind {
|
||||
ProcMacroKind::Attribute => 2,
|
||||
ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1,
|
||||
};
|
||||
|
||||
let expected_signature = match kind {
|
||||
ProcMacroKind::Attribute => "fn(TokenStream, TokenStream) -> TokenStream",
|
||||
ProcMacroKind::Derive | ProcMacroKind::FunctionLike => "fn(TokenStream) -> TokenStream",
|
||||
};
|
||||
|
||||
let tcx = self.tcx;
|
||||
if target == Target::Fn {
|
||||
let Some(tokenstream) = tcx.get_diagnostic_item(sym::TokenStream) else {return};
|
||||
let tokenstream = tcx.type_of(tokenstream);
|
||||
|
||||
let id = hir_id.expect_owner();
|
||||
let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap();
|
||||
|
||||
let sig = tcx.fn_sig(id);
|
||||
|
||||
if sig.abi() != Abi::Rust {
|
||||
tcx.sess
|
||||
.emit_err(ProcMacroInvalidAbi { span: hir_sig.span, abi: sig.abi().name() });
|
||||
self.abort.set(true);
|
||||
}
|
||||
|
||||
if sig.unsafety() == Unsafety::Unsafe {
|
||||
tcx.sess.emit_err(ProcMacroUnsafe { span: hir_sig.span });
|
||||
self.abort.set(true);
|
||||
}
|
||||
|
||||
let output = sig.output().skip_binder();
|
||||
|
||||
// Typecheck the output
|
||||
if tcx.normalize_erasing_regions(ParamEnv::empty(), output) != tokenstream {
|
||||
tcx.sess.emit_err(ProcMacroTypeError {
|
||||
span: hir_sig.decl.output.span(),
|
||||
found: output,
|
||||
kind,
|
||||
expected_signature,
|
||||
});
|
||||
self.abort.set(true);
|
||||
}
|
||||
|
||||
// Typecheck "expected_input_count" inputs, emitting
|
||||
// `ProcMacroMissingArguments` if there are not enough.
|
||||
if let Some(args) = sig.inputs().skip_binder().get(0..expected_input_count) {
|
||||
for (arg, input) in args.iter().zip(hir_sig.decl.inputs) {
|
||||
if tcx.normalize_erasing_regions(ParamEnv::empty(), *arg) != tokenstream {
|
||||
tcx.sess.emit_err(ProcMacroTypeError {
|
||||
span: input.span,
|
||||
found: *arg,
|
||||
kind,
|
||||
expected_signature,
|
||||
});
|
||||
self.abort.set(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tcx.sess.emit_err(ProcMacroMissingArguments {
|
||||
expected_input_count,
|
||||
span: hir_sig.span,
|
||||
kind,
|
||||
expected_signature,
|
||||
});
|
||||
self.abort.set(true);
|
||||
}
|
||||
|
||||
// Check that there are not too many arguments
|
||||
let body_id = tcx.hir().body_owned_by(id.def_id);
|
||||
let excess = tcx.hir().body(body_id).params.get(expected_input_count..);
|
||||
if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess {
|
||||
tcx.sess.emit_err(ProcMacroDiffArguments {
|
||||
span: begin.span.to(end.span),
|
||||
count: excess.len(),
|
||||
kind,
|
||||
expected_signature,
|
||||
});
|
||||
self.abort.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
||||
@ -2214,12 +2329,15 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>)
|
||||
}
|
||||
|
||||
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
let check_attr_visitor = &mut CheckAttrVisitor { tcx };
|
||||
let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) };
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor);
|
||||
if module_def_id.is_top_level_module() {
|
||||
check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
|
||||
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
|
||||
}
|
||||
if check_attr_visitor.abort.get() {
|
||||
tcx.sess.abort_if_errors()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
|
@ -12,6 +12,7 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{MainDefinition, Ty};
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
|
||||
use crate::check_attr::ProcMacroKind;
|
||||
use crate::lang_items::Duplicate;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
@ -1508,3 +1509,52 @@ pub struct ChangeFieldsToBeOfUnitType {
|
||||
#[suggestion_part(code = "()")]
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_proc_macro_typeerror)]
|
||||
#[note]
|
||||
pub(crate) struct ProcMacroTypeError<'tcx> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub found: Ty<'tcx>,
|
||||
pub kind: ProcMacroKind,
|
||||
pub expected_signature: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_proc_macro_diff_arg_count)]
|
||||
pub(crate) struct ProcMacroDiffArguments {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub count: usize,
|
||||
pub kind: ProcMacroKind,
|
||||
pub expected_signature: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_proc_macro_missing_args)]
|
||||
pub(crate) struct ProcMacroMissingArguments {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub expected_input_count: usize,
|
||||
pub kind: ProcMacroKind,
|
||||
pub expected_signature: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_proc_macro_invalid_abi)]
|
||||
pub(crate) struct ProcMacroInvalidAbi {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub abi: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_proc_macro_unsafe)]
|
||||
pub(crate) struct ProcMacroUnsafe {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -287,6 +287,7 @@ symbols! {
|
||||
Target,
|
||||
ToOwned,
|
||||
ToString,
|
||||
TokenStream,
|
||||
Try,
|
||||
TryCaptureGeneric,
|
||||
TryCapturePrintable,
|
||||
|
@ -74,6 +74,7 @@ pub fn is_available() -> bool {
|
||||
///
|
||||
/// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`
|
||||
/// and `#[proc_macro_derive]` definitions.
|
||||
#[rustc_diagnostic_item = "TokenStream"]
|
||||
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct TokenStream(Option<bridge::client::TokenStream>);
|
||||
|
28
tests/ui/proc-macro/proc-macro-abi.rs
Normal file
28
tests/ui/proc-macro/proc-macro-abi.rs
Normal file
@ -0,0 +1,28 @@
|
||||
#![crate_type = "proc-macro"]
|
||||
#![allow(warnings)]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro]
|
||||
pub extern "C" fn abi(a: TokenStream) -> TokenStream {
|
||||
//~^ ERROR proc macro functions may not be `extern
|
||||
a
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
|
||||
//~^ ERROR proc macro functions may not be `extern
|
||||
a
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub extern fn abi3(a: TokenStream) -> TokenStream {
|
||||
//~^ ERROR proc macro functions may not be `extern
|
||||
a
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub extern "Rust" fn abi4(a: TokenStream) -> TokenStream {
|
||||
a
|
||||
}
|
20
tests/ui/proc-macro/proc-macro-abi.stderr
Normal file
20
tests/ui/proc-macro/proc-macro-abi.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error: proc macro functions may not be `extern "C"`
|
||||
--> $DIR/proc-macro-abi.rs:8:1
|
||||
|
|
||||
LL | pub extern "C" fn abi(a: TokenStream) -> TokenStream {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: proc macro functions may not be `extern "system"`
|
||||
--> $DIR/proc-macro-abi.rs:14:1
|
||||
|
|
||||
LL | pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: proc macro functions may not be `extern "C"`
|
||||
--> $DIR/proc-macro-abi.rs:20:1
|
||||
|
|
||||
LL | pub extern fn abi3(a: TokenStream) -> TokenStream {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
29
tests/ui/proc-macro/signature-proc-macro-attribute.rs
Normal file
29
tests/ui/proc-macro/signature-proc-macro-attribute.rs
Normal file
@ -0,0 +1,29 @@
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn bad_input(input: String) -> TokenStream {
|
||||
//~^ ERROR mismatched attribute proc macro signature
|
||||
::proc_macro::TokenStream::new()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn bad_output(input: TokenStream) -> String {
|
||||
//~^ ERROR mismatched attribute proc macro signature
|
||||
//~| ERROR mismatched attribute proc macro signature
|
||||
String::from("blah")
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn bad_everything(input: String) -> String {
|
||||
//~^ ERROR mismatched attribute proc macro signature
|
||||
//~| ERROR mismatched attribute proc macro signature
|
||||
input
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
|
||||
//~^ ERROR mismatched attribute proc macro signature
|
||||
}
|
42
tests/ui/proc-macro/signature-proc-macro-attribute.stderr
Normal file
42
tests/ui/proc-macro/signature-proc-macro-attribute.stderr
Normal file
@ -0,0 +1,42 @@
|
||||
error: mismatched attribute proc macro signature
|
||||
--> $DIR/signature-proc-macro-attribute.rs:7:1
|
||||
|
|
||||
LL | pub fn bad_input(input: String) -> TokenStream {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
|
||||
|
||||
error: mismatched attribute proc macro signature
|
||||
--> $DIR/signature-proc-macro-attribute.rs:13:42
|
||||
|
|
||||
LL | pub fn bad_output(input: TokenStream) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: attribute proc macros must have a signature of `fn(TokenStream, TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched attribute proc macro signature
|
||||
--> $DIR/signature-proc-macro-attribute.rs:13:1
|
||||
|
|
||||
LL | pub fn bad_output(input: TokenStream) -> String {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
|
||||
|
||||
error: mismatched attribute proc macro signature
|
||||
--> $DIR/signature-proc-macro-attribute.rs:20:41
|
||||
|
|
||||
LL | pub fn bad_everything(input: String) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: attribute proc macros must have a signature of `fn(TokenStream, TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched attribute proc macro signature
|
||||
--> $DIR/signature-proc-macro-attribute.rs:20:1
|
||||
|
|
||||
LL | pub fn bad_everything(input: String) -> String {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
|
||||
|
||||
error: mismatched attribute proc macro signature
|
||||
--> $DIR/signature-proc-macro-attribute.rs:27:49
|
||||
|
|
||||
LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
|
||||
| ^^^^^^^^^ found unexpected argument
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
28
tests/ui/proc-macro/signature-proc-macro-derive.rs
Normal file
28
tests/ui/proc-macro/signature-proc-macro-derive.rs
Normal file
@ -0,0 +1,28 @@
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro_derive(Blah)]
|
||||
pub fn bad_input(input: String) -> TokenStream {
|
||||
//~^ ERROR mismatched derive proc macro signature
|
||||
TokenStream::new()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Bleh)]
|
||||
pub fn bad_output(input: TokenStream) -> String {
|
||||
//~^ ERROR mismatched derive proc macro signature
|
||||
String::from("blah")
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Bluh)]
|
||||
pub fn bad_everything(input: String) -> String {
|
||||
//~^ ERROR mismatched derive proc macro signature
|
||||
//~| ERROR mismatched derive proc macro signature
|
||||
input
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Blih)]
|
||||
pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
|
||||
//~^ ERROR mismatched derive proc macro signature
|
||||
}
|
40
tests/ui/proc-macro/signature-proc-macro-derive.stderr
Normal file
40
tests/ui/proc-macro/signature-proc-macro-derive.stderr
Normal file
@ -0,0 +1,40 @@
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature-proc-macro-derive.rs:7:25
|
||||
|
|
||||
LL | pub fn bad_input(input: String) -> TokenStream {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature-proc-macro-derive.rs:13:42
|
||||
|
|
||||
LL | pub fn bad_output(input: TokenStream) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature-proc-macro-derive.rs:19:41
|
||||
|
|
||||
LL | pub fn bad_everything(input: String) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature-proc-macro-derive.rs:19:30
|
||||
|
|
||||
LL | pub fn bad_everything(input: String) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature-proc-macro-derive.rs:26:33
|
||||
|
|
||||
LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
28
tests/ui/proc-macro/signature-proc-macro.rs
Normal file
28
tests/ui/proc-macro/signature-proc-macro.rs
Normal file
@ -0,0 +1,28 @@
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn bad_input(input: String) -> TokenStream {
|
||||
//~^ ERROR mismatched function-like proc macro signature
|
||||
::proc_macro::TokenStream::new()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn bad_output(input: TokenStream) -> String {
|
||||
//~^ ERROR mismatched function-like proc macro signature
|
||||
String::from("blah")
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn bad_everything(input: String) -> String {
|
||||
//~^ ERROR mismatched function-like proc macro signature
|
||||
//~| ERROR mismatched function-like proc macro signature
|
||||
input
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
|
||||
//~^ ERROR mismatched function-like proc macro signature
|
||||
}
|
40
tests/ui/proc-macro/signature-proc-macro.stderr
Normal file
40
tests/ui/proc-macro/signature-proc-macro.stderr
Normal file
@ -0,0 +1,40 @@
|
||||
error: mismatched function-like proc macro signature
|
||||
--> $DIR/signature-proc-macro.rs:7:25
|
||||
|
|
||||
LL | pub fn bad_input(input: String) -> TokenStream {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched function-like proc macro signature
|
||||
--> $DIR/signature-proc-macro.rs:13:42
|
||||
|
|
||||
LL | pub fn bad_output(input: TokenStream) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched function-like proc macro signature
|
||||
--> $DIR/signature-proc-macro.rs:19:41
|
||||
|
|
||||
LL | pub fn bad_everything(input: String) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched function-like proc macro signature
|
||||
--> $DIR/signature-proc-macro.rs:19:30
|
||||
|
|
||||
LL | pub fn bad_everything(input: String) -> String {
|
||||
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched function-like proc macro signature
|
||||
--> $DIR/signature-proc-macro.rs:26:33
|
||||
|
|
||||
LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
@ -8,6 +8,10 @@ extern crate proc_macro;
|
||||
|
||||
#[proc_macro_derive(A)]
|
||||
pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
//~^ ERROR: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn
|
||||
//~^ ERROR: mismatched derive proc macro signature
|
||||
//~| mismatched derive proc macro signature
|
||||
//~| mismatched derive proc macro signature
|
||||
//~| proc macro functions may not be `extern
|
||||
//~| proc macro functions may not be `unsafe
|
||||
loop {}
|
||||
}
|
||||
|
@ -1,20 +1,36 @@
|
||||
error[E0277]: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
|
||||
error: proc macro functions may not be `extern "C"`
|
||||
--> $DIR/signature.rs:10:1
|
||||
|
|
||||
LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
LL | |
|
||||
LL | | loop {}
|
||||
LL | | }
|
||||
| | ^
|
||||
| | |
|
||||
| |_call the function in a closure: `|| unsafe { /* code */ }`
|
||||
| required by a bound introduced by this call
|
||||
LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: proc macro functions may not be `unsafe`
|
||||
--> $DIR/signature.rs:10:1
|
||||
|
|
||||
= help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
note: required by a bound in `ProcMacro::custom_derive`
|
||||
--> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
|
||||
LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature.rs:10:49
|
||||
|
|
||||
LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
| ^^^ found u32, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature.rs:10:33
|
||||
|
|
||||
LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
| ^^^ found i32, expected type `proc_macro::TokenStream`
|
||||
|
|
||||
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
|
||||
|
||||
error: mismatched derive proc macro signature
|
||||
--> $DIR/signature.rs:10:38
|
||||
|
|
||||
LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
|
||||
| ^^^^^^ found unexpected argument
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user