@@ -16,6 +16,10 @@ use rustc_span::Span;
1616const VALID_FRAGMENT_NAMES_MSG : & str = "valid fragment specifiers are \
1717 `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
1818 `literal`, `path`, `meta`, `tt`, `item` and `vis`";
19+ const VALID_FRAGMENT_NAMES_MSG_2021 : & str = "valid fragment specifiers are \
20+ `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, \
21+ `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \
22+ `item` and `vis`";
1923
2024/// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. Specifically, this
2125/// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a
@@ -63,35 +67,49 @@ pub(super) fn parse(
6367 Some ( tokenstream:: TokenTree :: Token ( token, _) ) => match token. ident ( ) {
6468 Some ( ( fragment, _) ) => {
6569 let span = token. span . with_lo ( start_sp. lo ( ) ) ;
66-
70+ let edition = || {
71+ // FIXME(#85708) - once we properly decode a foreign
72+ // crate's `SyntaxContext::root`, then we can replace
73+ // this with just `span.edition()`. A
74+ // `SyntaxContext::root()` from the current crate will
75+ // have the edition of the current crate, and a
76+ // `SyntaxContext::root()` from a foreign crate will
77+ // have the edition of that crate (which we manually
78+ // retrieve via the `edition` parameter).
79+ if !span. from_expansion ( ) {
80+ edition
81+ } else {
82+ span. edition ( )
83+ }
84+ } ;
6785 let kind =
68- token:: NonterminalKind :: from_symbol ( fragment. name , || {
69- // FIXME(#85708) - once we properly decode a foreign
70- // crate's `SyntaxContext::root`, then we can replace
71- // this with just `span.edition()`. A
72- // `SyntaxContext::root()` from the current crate will
73- // have the edition of the current crate, and a
74- // `SyntaxContext::root()` from a foreign crate will
75- // have the edition of that crate (which we manually
76- // retrieve via the `edition` parameter).
77- if !span. from_expansion ( ) {
78- edition
79- } else {
80- span. edition ( )
81- }
82- } )
83- . unwrap_or_else (
84- || {
86+ token:: NonterminalKind :: from_symbol ( fragment. name , edition)
87+ . unwrap_or_else ( || {
88+ let help = match fragment. name {
89+ sym:: expr_2021 => {
90+ format ! (
91+ "fragment specifier `expr_2021` \
92+ requires Rust 2021 or later\n \
93+ {VALID_FRAGMENT_NAMES_MSG}"
94+ )
95+ }
96+ _ if edition ( ) . at_least_rust_2021 ( )
97+ && features
98+ . expr_fragment_specifier_2024 =>
99+ {
100+ VALID_FRAGMENT_NAMES_MSG_2021 . into ( )
101+ }
102+ _ => VALID_FRAGMENT_NAMES_MSG . into ( ) ,
103+ } ;
85104 sess. dcx ( ) . emit_err (
86105 errors:: InvalidFragmentSpecifier {
87106 span,
88107 fragment,
89- help : VALID_FRAGMENT_NAMES_MSG . into ( ) ,
108+ help,
90109 } ,
91110 ) ;
92111 token:: NonterminalKind :: Ident
93- } ,
94- ) ;
112+ } ) ;
95113 if kind == token:: NonterminalKind :: Expr2021
96114 && !features. expr_fragment_specifier_2024
97115 {
0 commit comments