@@ -23,6 +23,7 @@ use rustc_hir::{
2323use rustc_hir:: { MethodKind , Target , Unsafety } ;
2424use rustc_middle:: hir:: nested_filter;
2525use rustc_middle:: middle:: resolve_lifetime:: ObjectLifetimeDefault ;
26+ use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams } ;
2627use rustc_middle:: ty:: query:: Providers ;
2728use rustc_middle:: ty:: { ParamEnv , TyCtxt } ;
2829use rustc_session:: lint:: builtin:: {
@@ -84,6 +85,8 @@ impl IntoDiagnosticArg for ProcMacroKind {
8485
8586struct CheckAttrVisitor < ' tcx > {
8687 tcx : TyCtxt < ' tcx > ,
88+
89+ // Whether or not this visitor should abort after finding errors
8790 abort : Cell < bool > ,
8891}
8992
@@ -2084,6 +2087,9 @@ impl CheckAttrVisitor<'_> {
20842087 ) ;
20852088 }
20862089
2090+ /// A best effort attempt to create an error for a mismatching proc macro signature.
2091+ ///
2092+ /// If this best effort goes wrong, it will just emit a worse error later (see #102923)
20872093 fn check_proc_macro ( & self , hir_id : HirId , target : Target , kind : ProcMacroKind ) {
20882094 let expected_input_count = match kind {
20892095 ProcMacroKind :: Attribute => 2 ,
@@ -2103,23 +2109,30 @@ impl CheckAttrVisitor<'_> {
21032109 let id = hir_id. expect_owner ( ) ;
21042110 let hir_sig = tcx. hir ( ) . fn_sig_by_hir_id ( hir_id) . unwrap ( ) ;
21052111
2106- let sig = tcx. fn_sig ( id) ;
2112+ let sig = tcx. liberate_late_bound_regions ( id. to_def_id ( ) , tcx. fn_sig ( id) ) ;
2113+ let sig = tcx. normalize_erasing_regions ( ParamEnv :: empty ( ) , sig) ;
2114+
2115+ // We don't currently require that the function signature is equal to
2116+ // `fn(TokenStream) -> TokenStream`, but instead monomorphizes to
2117+ // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments.
2118+ //
2119+ // Properly checking this means pulling in additional `rustc` crates, so we don't.
2120+ let drcx = DeepRejectCtxt { treat_obligation_params : TreatParams :: AsInfer } ;
21072121
2108- if sig. abi ( ) != Abi :: Rust {
2109- tcx. sess
2110- . emit_err ( ProcMacroInvalidAbi { span : hir_sig. span , abi : sig. abi ( ) . name ( ) } ) ;
2122+ if sig. abi != Abi :: Rust {
2123+ tcx. sess . emit_err ( ProcMacroInvalidAbi { span : hir_sig. span , abi : sig. abi . name ( ) } ) ;
21112124 self . abort . set ( true ) ;
21122125 }
21132126
2114- if sig. unsafety ( ) == Unsafety :: Unsafe {
2127+ if sig. unsafety == Unsafety :: Unsafe {
21152128 tcx. sess . emit_err ( ProcMacroUnsafe { span : hir_sig. span } ) ;
21162129 self . abort . set ( true ) ;
21172130 }
21182131
2119- let output = sig. output ( ) . skip_binder ( ) ;
2132+ let output = sig. output ( ) ;
21202133
21212134 // Typecheck the output
2122- if tcx . normalize_erasing_regions ( ParamEnv :: empty ( ) , output ) != tokenstream {
2135+ if !drcx . types_may_unify ( output , tokenstream) {
21232136 tcx. sess . emit_err ( ProcMacroTypeError {
21242137 span : hir_sig. decl . output . span ( ) ,
21252138 found : output,
@@ -2129,11 +2142,22 @@ impl CheckAttrVisitor<'_> {
21292142 self . abort . set ( true ) ;
21302143 }
21312144
2132- // Typecheck "expected_input_count" inputs, emitting
2133- // `ProcMacroMissingArguments` if there are not enough.
2134- if let Some ( args) = sig. inputs ( ) . skip_binder ( ) . get ( 0 ..expected_input_count) {
2135- for ( arg, input) in args. iter ( ) . zip ( hir_sig. decl . inputs ) {
2136- if tcx. normalize_erasing_regions ( ParamEnv :: empty ( ) , * arg) != tokenstream {
2145+ if sig. inputs ( ) . len ( ) < expected_input_count {
2146+ tcx. sess . emit_err ( ProcMacroMissingArguments {
2147+ expected_input_count,
2148+ span : hir_sig. span ,
2149+ kind,
2150+ expected_signature,
2151+ } ) ;
2152+ self . abort . set ( true ) ;
2153+ }
2154+
2155+ // Check that the inputs are correct, if there are enough.
2156+ if sig. inputs ( ) . len ( ) >= expected_input_count {
2157+ for ( arg, input) in
2158+ sig. inputs ( ) . iter ( ) . zip ( hir_sig. decl . inputs ) . take ( expected_input_count)
2159+ {
2160+ if !drcx. types_may_unify ( * arg, tokenstream) {
21372161 tcx. sess . emit_err ( ProcMacroTypeError {
21382162 span : input. span ,
21392163 found : * arg,
@@ -2143,14 +2167,6 @@ impl CheckAttrVisitor<'_> {
21432167 self . abort . set ( true ) ;
21442168 }
21452169 }
2146- } else {
2147- tcx. sess . emit_err ( ProcMacroMissingArguments {
2148- expected_input_count,
2149- span : hir_sig. span ,
2150- kind,
2151- expected_signature,
2152- } ) ;
2153- self . abort . set ( true ) ;
21542170 }
21552171
21562172 // Check that there are not too many arguments
0 commit comments