Skip to content

Simplify proc macro signature validity check #109136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 15, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -5139,6 +5139,7 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"tracing",
]

1 change: 1 addition & 0 deletions compiler/rustc_passes/Cargo.toml
Original file line number Diff line number Diff line change
@@ -22,3 +22,4 @@ rustc_span = { path = "../rustc_span" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_feature = { path = "../rustc_feature" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
21 changes: 1 addition & 20 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
@@ -720,26 +720,7 @@ passes_ignored_derived_impls =
*[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`
passes_proc_macro_bad_sig = {$kind} has incorrect signature

passes_skipping_const_checks = skipping const checks

173 changes: 88 additions & 85 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
@@ -19,9 +19,10 @@ use rustc_hir::{
use rustc_hir::{MethodKind, Target, Unsafety};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{ParamEnv, TyCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
UNUSED_ATTRIBUTES,
@@ -30,6 +31,9 @@ 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 rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
use std::cell::Cell;
use std::collections::hash_map::Entry;

@@ -2188,100 +2192,99 @@ impl CheckAttrVisitor<'_> {
///
/// If this best effort goes wrong, it will just emit a worse error later (see #102923)
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",
};
if target != Target::Fn {
return;
}

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).subst_identity();

let id = hir_id.expect_owner();
let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap();

let sig =
tcx.liberate_late_bound_regions(id.to_def_id(), tcx.fn_sig(id).subst_identity());
let sig = tcx.normalize_erasing_regions(ParamEnv::empty(), sig);

// We don't currently require that the function signature is equal to
// `fn(TokenStream) -> TokenStream`, but instead monomorphizes to
// `fn(TokenStream) -> TokenStream` after some substitution of generic arguments.
//
// Properly checking this means pulling in additional `rustc` crates, so we don't.
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey };

if sig.abi != Abi::Rust {
tcx.sess.emit_err(errors::ProcMacroInvalidAbi {
span: hir_sig.span,
abi: sig.abi.name(),
});
self.abort.set(true);
}
let Some(token_stream_def_id) = tcx.get_diagnostic_item(sym::TokenStream) else { return; };
let Some(token_stream) = tcx.type_of(token_stream_def_id).no_bound_vars() else { return; };

if sig.unsafety == Unsafety::Unsafe {
tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span });
self.abort.set(true);
}
let def_id = hir_id.expect_owner().def_id;
let param_env = ty::ParamEnv::empty();

let output = sig.output();
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);

// Typecheck the output
if !drcx.types_may_unify(output, tokenstream) {
tcx.sess.emit_err(errors::ProcMacroTypeError {
span: hir_sig.decl.output.span(),
found: output,
kind,
expected_signature,
});
self.abort.set(true);
}
let span = tcx.def_span(def_id);
let fresh_substs = infcx.fresh_substs_for_item(span, def_id.to_def_id());
let sig = tcx.liberate_late_bound_regions(
def_id.to_def_id(),
tcx.fn_sig(def_id).subst(tcx, fresh_substs),
);

if sig.inputs().len() < expected_input_count {
tcx.sess.emit_err(errors::ProcMacroMissingArguments {
expected_input_count,
span: hir_sig.span,
kind,
expected_signature,
});
self.abort.set(true);
}
let mut cause = ObligationCause::misc(span, def_id);
let sig = ocx.normalize(&cause, param_env, sig);

// Check that the inputs are correct, if there are enough.
if sig.inputs().len() >= expected_input_count {
for (arg, input) in
sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count)
{
if !drcx.types_may_unify(*arg, tokenstream) {
tcx.sess.emit_err(errors::ProcMacroTypeError {
span: input.span,
found: *arg,
kind,
expected_signature,
});
self.abort.set(true);
// proc macro is not WF.
let errors = ocx.select_where_possible();
if !errors.is_empty() {
return;
}

let expected_sig = tcx.mk_fn_sig(
std::iter::repeat(token_stream).take(match kind {
ProcMacroKind::Attribute => 2,
ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1,
}),
token_stream,
false,
Unsafety::Normal,
Abi::Rust,
);

if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) {
let mut diag = tcx.sess.create_err(errors::ProcMacroBadSig { span, kind });

let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id);
if let Some(hir_sig) = hir_sig {
match terr {
TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => {
if let Some(ty) = hir_sig.decl.inputs.get(idx) {
diag.set_span(ty.span);
cause.span = ty.span;
} else if idx == hir_sig.decl.inputs.len() {
let span = hir_sig.decl.output.span();
diag.set_span(span);
cause.span = span;
}
}
TypeError::ArgCount => {
if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) {
diag.set_span(ty.span);
cause.span = ty.span;
}
}
TypeError::UnsafetyMismatch(_) => {
// FIXME: Would be nice if we had a span here..
}
TypeError::AbiMismatch(_) => {
// FIXME: Would be nice if we had a span here..
}
TypeError::VariadicMismatch(_) => {
// FIXME: Would be nice if we had a span here..
}
_ => {}
}
}

// 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(errors::ProcMacroDiffArguments {
span: begin.span.to(end.span),
count: excess.len(),
kind,
expected_signature,
});
self.abort.set(true);
}
infcx.err_ctxt().note_type_err(
&mut diag,
&cause,
None,
Some(ValuePairs::Sigs(ExpectedFound { expected: expected_sig, found: sig })),
terr,
false,
false,
);
diag.emit();
self.abort.set(true);
}

let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
self.abort.set(true);
}
}
}
45 changes: 2 additions & 43 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1546,52 +1546,11 @@ pub struct ChangeFieldsToBeOfUnitType {
}

#[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 {
#[diag(passes_proc_macro_bad_sig)]
pub(crate) struct ProcMacroBadSig {
#[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,
}

#[derive(Diagnostic)]
15 changes: 15 additions & 0 deletions tests/ui/proc-macro/bad-projection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// force-host
// no-prefer-dynamic

#![crate_type = "proc-macro"]
#![allow(warnings)]

extern crate proc_macro;

trait Project {
type Assoc;
}

#[proc_macro]
pub fn uwu() -> <() as Project>::Assoc {}
//~^ ERROR the trait bound `(): Project` is not satisfied
9 changes: 9 additions & 0 deletions tests/ui/proc-macro/bad-projection.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0277]: the trait bound `(): Project` is not satisfied
--> $DIR/bad-projection.rs:14:17
|
LL | pub fn uwu() -> <() as Project>::Assoc {}
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Project` is not implemented for `()`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
6 changes: 3 additions & 3 deletions tests/ui/proc-macro/proc-macro-abi.rs
Original file line number Diff line number Diff line change
@@ -9,19 +9,19 @@ use proc_macro::TokenStream;

#[proc_macro]
pub extern "C" fn abi(a: TokenStream) -> TokenStream {
//~^ ERROR proc macro functions may not be `extern "C"`
//~^ ERROR function-like proc macro has incorrect signature
a
}

#[proc_macro]
pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
//~^ ERROR proc macro functions may not be `extern "system"`
//~^ ERROR function-like proc macro has incorrect signature
a
}

#[proc_macro]
pub extern fn abi3(a: TokenStream) -> TokenStream {
//~^ ERROR proc macro functions may not be `extern "C"`
//~^ ERROR function-like proc macro has incorrect signature
a
}

21 changes: 15 additions & 6 deletions tests/ui/proc-macro/proc-macro-abi.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
error: proc macro functions may not be `extern "C"`
error: function-like proc macro has incorrect signature
--> $DIR/proc-macro-abi.rs:11:1
|
LL | pub extern "C" fn abi(a: TokenStream) -> TokenStream {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
|
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `extern "C" fn(proc_macro::TokenStream) -> proc_macro::TokenStream`

error: proc macro functions may not be `extern "system"`
error: function-like proc macro has incorrect signature
--> $DIR/proc-macro-abi.rs:17:1
|
LL | pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "system" fn
|
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `extern "system" fn(proc_macro::TokenStream) -> proc_macro::TokenStream`

error: proc macro functions may not be `extern "C"`
error: function-like proc macro has incorrect signature
--> $DIR/proc-macro-abi.rs:23:1
|
LL | pub extern fn abi3(a: TokenStream) -> TokenStream {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
|
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `extern "C" fn(proc_macro::TokenStream) -> proc_macro::TokenStream`

error: aborting due to 3 previous errors

10 changes: 4 additions & 6 deletions tests/ui/proc-macro/signature-proc-macro-attribute.rs
Original file line number Diff line number Diff line change
@@ -8,25 +8,23 @@ use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn bad_input(input: String) -> TokenStream {
//~^ ERROR mismatched attribute proc macro signature
//~^ ERROR attribute proc macro has incorrect 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
//~^ ERROR attribute proc macro has incorrect 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
//~^ ERROR attribute proc macro has incorrect signature
input
}

#[proc_macro_attribute]
pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
//~^ ERROR mismatched attribute proc macro signature
//~^ ERROR attribute proc macro has incorrect signature
}
46 changes: 21 additions & 25 deletions tests/ui/proc-macro/signature-proc-macro-attribute.stderr
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
error: mismatched attribute proc macro signature
error: attribute proc macro has incorrect signature
--> $DIR/signature-proc-macro-attribute.rs:10: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:16:42
|
LL | pub fn bad_output(input: TokenStream) -> String {
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
= note: attribute proc macros must have a signature of `fn(TokenStream, TokenStream) -> TokenStream`
= note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(std::string::String) -> proc_macro::TokenStream`

error: mismatched attribute proc macro signature
error: attribute proc macro has incorrect signature
--> $DIR/signature-proc-macro-attribute.rs:16: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:23:41
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
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`
= note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(proc_macro::TokenStream) -> std::string::String`

error: mismatched attribute proc macro signature
--> $DIR/signature-proc-macro-attribute.rs:23:1
error: attribute proc macro has incorrect signature
--> $DIR/signature-proc-macro-attribute.rs:22:1
|
LL | pub fn bad_everything(input: String) -> String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
|
= note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(std::string::String) -> std::string::String`

error: mismatched attribute proc macro signature
--> $DIR/signature-proc-macro-attribute.rs:30:49
error: attribute proc macro has incorrect signature
--> $DIR/signature-proc-macro-attribute.rs:28:52
|
LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
| ^^^^^^^^^ found unexpected argument
| ^^^^^^ incorrect number of function parameters
|
= note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream`

error: aborting due to 6 previous errors
error: aborting due to 4 previous errors

9 changes: 4 additions & 5 deletions tests/ui/proc-macro/signature-proc-macro-derive.rs
Original file line number Diff line number Diff line change
@@ -8,24 +8,23 @@ use proc_macro::TokenStream;

#[proc_macro_derive(Blah)]
pub fn bad_input(input: String) -> TokenStream {
//~^ ERROR mismatched derive proc macro signature
//~^ ERROR derive proc macro has incorrect signature
TokenStream::new()
}

#[proc_macro_derive(Bleh)]
pub fn bad_output(input: TokenStream) -> String {
//~^ ERROR mismatched derive proc macro signature
//~^ ERROR derive proc macro has incorrect 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
//~^ ERROR derive proc macro has incorrect signature
input
}

#[proc_macro_derive(Blih)]
pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
//~^ ERROR mismatched derive proc macro signature
//~^ ERROR derive proc macro has incorrect signature
}
40 changes: 19 additions & 21 deletions tests/ui/proc-macro/signature-proc-macro-derive.stderr
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
error: mismatched derive proc macro signature
error: derive proc macro has incorrect signature
--> $DIR/signature-proc-macro-derive.rs:10:25
|
LL | pub fn bad_input(input: String) -> TokenStream {
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
| ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
|
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(std::string::String) -> proc_macro::TokenStream`

error: mismatched derive proc macro signature
error: derive proc macro has incorrect signature
--> $DIR/signature-proc-macro-derive.rs:16:42
|
LL | pub fn bad_output(input: TokenStream) -> String {
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
| ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
|
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(proc_macro::TokenStream) -> std::string::String`

error: mismatched derive proc macro signature
--> $DIR/signature-proc-macro-derive.rs:22: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
error: derive proc macro has incorrect signature
--> $DIR/signature-proc-macro-derive.rs:22:30
|
LL | pub fn bad_everything(input: String) -> String {
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
| ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
|
= note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(std::string::String) -> std::string::String`

error: mismatched derive proc macro signature
--> $DIR/signature-proc-macro-derive.rs:29:33
error: derive proc macro has incorrect signature
--> $DIR/signature-proc-macro-derive.rs:28:36
|
LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
| ^^^^^^^^^^^ incorrect number of function parameters
|
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream`

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

9 changes: 4 additions & 5 deletions tests/ui/proc-macro/signature-proc-macro.rs
Original file line number Diff line number Diff line change
@@ -8,24 +8,23 @@ use proc_macro::TokenStream;

#[proc_macro]
pub fn bad_input(input: String) -> TokenStream {
//~^ ERROR mismatched function-like proc macro signature
//~^ ERROR function-like proc macro has incorrect signature
::proc_macro::TokenStream::new()
}

#[proc_macro]
pub fn bad_output(input: TokenStream) -> String {
//~^ ERROR mismatched function-like proc macro signature
//~^ ERROR function-like proc macro has incorrect 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
//~^ ERROR function-like proc macro has incorrect signature
input
}

#[proc_macro]
pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
//~^ ERROR mismatched function-like proc macro signature
//~^ ERROR function-like proc macro has incorrect signature
}
40 changes: 19 additions & 21 deletions tests/ui/proc-macro/signature-proc-macro.stderr
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
error: mismatched function-like proc macro signature
error: function-like proc macro has incorrect signature
--> $DIR/signature-proc-macro.rs:10:25
|
LL | pub fn bad_input(input: String) -> TokenStream {
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
| ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
|
= note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(std::string::String) -> proc_macro::TokenStream`

error: mismatched function-like proc macro signature
error: function-like proc macro has incorrect signature
--> $DIR/signature-proc-macro.rs:16:42
|
LL | pub fn bad_output(input: TokenStream) -> String {
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
| ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
|
= note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(proc_macro::TokenStream) -> std::string::String`

error: mismatched function-like proc macro signature
--> $DIR/signature-proc-macro.rs:22: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
error: function-like proc macro has incorrect signature
--> $DIR/signature-proc-macro.rs:22:30
|
LL | pub fn bad_everything(input: String) -> String {
| ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
| ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
|
= note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(std::string::String) -> std::string::String`

error: mismatched function-like proc macro signature
--> $DIR/signature-proc-macro.rs:29:33
error: function-like proc macro has incorrect signature
--> $DIR/signature-proc-macro.rs:28:36
|
LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
| ^^^^^^^^^^^ incorrect number of function parameters
|
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream`

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

6 changes: 1 addition & 5 deletions tests/ui/proc-macro/signature.rs
Original file line number Diff line number Diff line change
@@ -8,10 +8,6 @@ extern crate proc_macro;

#[proc_macro_derive(A)]
pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
//~^ 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
//~^ ERROR: derive proc macro has incorrect signature
loop {}
}
35 changes: 5 additions & 30 deletions tests/ui/proc-macro/signature.stderr
Original file line number Diff line number Diff line change
@@ -1,36 +1,11 @@
error: proc macro functions may not be `extern "C"`
error: derive proc macro has incorrect signature
--> $DIR/signature.rs:10:1
|
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
|
LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
|
= 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
= note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found signature `unsafe extern "C" fn(i32, u32) -> u32`

error: aborting due to 5 previous errors
error: aborting due to previous error