@@ -41,6 +41,7 @@ use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};
4141
4242use std:: collections:: HashSet ;
4343
44+ use syntax:: tokenstream:: { TokenTree , TokenStream } ;
4445use syntax:: ast;
4546use syntax:: attr;
4647use syntax:: codemap:: Spanned ;
@@ -1784,3 +1785,70 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestFunctions {
17841785 } ;
17851786 }
17861787}
1788+
1789+ declare_lint ! {
1790+ pub ASYNC_IDENTS ,
1791+ Allow ,
1792+ "detects `async` being used as an identifier"
1793+ }
1794+
1795+ /// Checks for uses of `async` as an identifier
1796+ #[ derive( Clone ) ]
1797+ pub struct Async2018 ;
1798+
1799+ impl LintPass for Async2018 {
1800+ fn get_lints ( & self ) -> LintArray {
1801+ lint_array ! ( ASYNC_IDENTS )
1802+ }
1803+ }
1804+
1805+ impl Async2018 {
1806+ fn check_tokens ( & mut self , cx : & EarlyContext , tokens : TokenStream ) {
1807+ for tt in tokens. into_trees ( ) {
1808+ match tt {
1809+ TokenTree :: Token ( span, tok) => match tok. ident ( ) {
1810+ // only report non-raw idents
1811+ Some ( ( ident, false ) ) if ident. as_str ( ) == "async" => {
1812+ self . report ( cx, span. substitute_dummy ( ident. span ) )
1813+ } ,
1814+ _ => { } ,
1815+ }
1816+ TokenTree :: Delimited ( _, ref delim) => {
1817+ self . check_tokens ( cx, delim. tts . clone ( ) . into ( ) )
1818+ } ,
1819+ }
1820+ }
1821+ }
1822+ fn report ( & mut self , cx : & EarlyContext , span : Span ) {
1823+ // don't lint `r#async`
1824+ if cx. sess . parse_sess . raw_identifier_spans . borrow ( ) . contains ( & span) {
1825+ return ;
1826+ }
1827+ let mut lint = cx. struct_span_lint (
1828+ ASYNC_IDENTS ,
1829+ span,
1830+ "`async` is a keyword in the 2018 edition" ,
1831+ ) ;
1832+ lint. span_suggestion_with_applicability (
1833+ span,
1834+ "you can use a raw identifier to stay compatible" ,
1835+ "r#async" . to_string ( ) ,
1836+ Applicability :: MachineApplicable ,
1837+ ) ;
1838+ lint. emit ( )
1839+ }
1840+ }
1841+
1842+ impl EarlyLintPass for Async2018 {
1843+ fn check_mac_def ( & mut self , cx : & EarlyContext , mac_def : & ast:: MacroDef , _id : ast:: NodeId ) {
1844+ self . check_tokens ( cx, mac_def. stream ( ) ) ;
1845+ }
1846+ fn check_mac ( & mut self , cx : & EarlyContext , mac : & ast:: Mac ) {
1847+ self . check_tokens ( cx, mac. node . tts . clone ( ) . into ( ) ) ;
1848+ }
1849+ fn check_ident ( & mut self , cx : & EarlyContext , ident : ast:: Ident ) {
1850+ if ident. as_str ( ) == "async" {
1851+ self . report ( cx, ident. span ) ;
1852+ }
1853+ }
1854+ }
0 commit comments