@@ -44,7 +44,7 @@ pub(super) enum DestructuredFloat {
4444 /// 1.
4545 TrailingDot ( Symbol , Span , Span ) ,
4646 /// 1.2 | 1.2e3
47- MiddleDot ( Symbol , Span , Span , Symbol , Span ) ,
47+ MiddleDot ( Symbol , Span , Symbol , Span ) ,
4848 /// Invalid
4949 Error ,
5050}
@@ -961,6 +961,7 @@ impl<'a> Parser<'a> {
961961 token:: Ident ( ..) => self . parse_dot_suffix ( base, lo) ,
962962 token:: Literal ( token:: Lit { kind : token:: Integer , symbol, suffix } ) => {
963963 let ident_span = self . token . span ;
964+ let symbol = self . validate_tuple_index ( symbol, ident_span) ;
964965 self . bump ( ) ;
965966 Ok ( self . mk_expr_tuple_field_access ( lo, ident_span, base, symbol, suffix) )
966967 }
@@ -986,13 +987,9 @@ impl<'a> Parser<'a> {
986987 self . mk_expr_tuple_field_access ( lo, ident_span, base, sym, None )
987988 }
988989 // 1.2 | 1.2e3
989- DestructuredFloat :: MiddleDot (
990- sym1,
991- ident1_span,
992- _dot_span,
993- sym2,
994- ident2_span,
995- ) => {
990+ // FIXME(fmease): (preexisting) For some reason for `x.0.0xyz` (i.e., suffixed)
991+ // highlight `0.0xyz` when we should just highlight `0xyz`.
992+ DestructuredFloat :: MiddleDot ( sym1, ident1_span, sym2, ident2_span) => {
996993 // `foo.1.2` (or `foo.1.2e3`): two complete dot accesses. We end up with
997994 // the `sym2` (`2` or `2e3`) token in `self.prev_token` and the following
998995 // token in `self.token`.
@@ -1055,30 +1052,68 @@ impl<'a> Parser<'a> {
10551052 // support pushing "future tokens" (would be also helpful to `break_and_eat`), or
10561053 // we should break everything including floats into more basic proc-macro style
10571054 // tokens in the lexer (probably preferable).
1055+ // FIXME(fmease): De-jank the impl.
10581056 pub ( super ) fn break_up_float ( & self , float : Symbol , span : Span ) -> DestructuredFloat {
10591057 #[ derive( Debug ) ]
10601058 enum FloatComponent {
1061- IdentLike ( String ) ,
1059+ IdentLike ( IdentLike ) ,
10621060 Punct ( char ) ,
10631061 }
10641062 use FloatComponent :: * ;
10651063
1064+ #[ derive( Debug , Default ) ]
1065+ struct IdentLike {
1066+ str : String ,
1067+ len : usize ,
1068+ poisoned : bool ,
1069+ }
1070+
10661071 let float_str = float. as_str ( ) ;
10671072 let mut components = Vec :: new ( ) ;
1068- let mut ident_like = String :: new ( ) ;
1073+ let mut ident_like = IdentLike :: default ( ) ;
1074+ let mut zero = false ;
1075+
10691076 for c in float_str. chars ( ) {
1070- if c == '_' || c. is_ascii_alphanumeric ( ) {
1071- ident_like. push ( c) ;
1072- } else if matches ! ( c, '.' | '+' | '-' ) {
1073- if !ident_like. is_empty ( ) {
1074- components. push ( IdentLike ( mem:: take ( & mut ident_like) ) ) ;
1077+ match c {
1078+ '0' ..='9' => {
1079+ ident_like. len += 1 ;
1080+ if zero {
1081+ ident_like. poisoned = true ;
1082+ }
1083+ zero = c == '0' && ident_like. str . is_empty ( ) ;
1084+ if !zero {
1085+ ident_like. str . push ( c) ;
1086+ }
10751087 }
1076- components. push ( Punct ( c) ) ;
1077- } else {
1078- panic ! ( "unexpected character in a float token: {c:?}" )
1088+ '_' | 'b' | 'o' | 'x' => {
1089+ ident_like. len += 1 ;
1090+ ident_like. poisoned = true ;
1091+ }
1092+ 'e' | 'E' => {
1093+ ident_like. len += 1 ;
1094+ ident_like. poisoned = true ;
1095+ if mem:: take ( & mut zero) {
1096+ ident_like. str . push ( '0' ) ;
1097+ }
1098+ ident_like. str . push ( c) ;
1099+ }
1100+ '.' | '+' | '-' => {
1101+ if mem:: take ( & mut zero) {
1102+ ident_like. str . push ( '0' ) ;
1103+ }
1104+ if !ident_like. str . is_empty ( ) {
1105+ components. push ( IdentLike ( mem:: take ( & mut ident_like) ) ) ;
1106+ }
1107+ components. push ( Punct ( c) ) ;
1108+ }
1109+ _ => panic ! ( "unexpected character in a float token: {c:?}" ) ,
10791110 }
10801111 }
1081- if !ident_like. is_empty ( ) {
1112+
1113+ if zero {
1114+ ident_like. str . push ( '0' ) ;
1115+ }
1116+ if !ident_like. str . is_empty ( ) {
10821117 components. push ( IdentLike ( ident_like) ) ;
10831118 }
10841119
@@ -1090,44 +1125,58 @@ impl<'a> Parser<'a> {
10901125
10911126 match & * components {
10921127 // 1e2
1093- [ IdentLike ( i) ] => {
1094- DestructuredFloat :: Single ( Symbol :: intern ( i) , span)
1095- }
1128+ [ IdentLike ( ident) ] => {
1129+ if ident. poisoned {
1130+ self . dcx ( ) . span_err ( span, "invalid tuple index" ) ;
1131+ }
1132+
1133+ DestructuredFloat :: Single ( Symbol :: intern ( & ident. str ) , span) } ,
10961134 // 1.
10971135 [ IdentLike ( left) , Punct ( '.' ) ] => {
10981136 let ( left_span, dot_span) = if can_take_span_apart ( ) {
1099- let left_span = span. with_hi ( span. lo ( ) + BytePos :: from_usize ( left. len ( ) ) ) ;
1137+ let left_span = span. with_hi ( span. lo ( ) + BytePos :: from_usize ( left. len ) ) ;
11001138 let dot_span = span. with_lo ( left_span. hi ( ) ) ;
11011139 ( left_span, dot_span)
11021140 } else {
11031141 ( span, span)
11041142 } ;
1105- let left = Symbol :: intern ( left) ;
1143+ if left. poisoned {
1144+ self . dcx ( ) . span_err ( left_span, "invalid tuple index" ) ;
1145+ }
1146+ let left = Symbol :: intern ( & left. str ) ;
11061147 DestructuredFloat :: TrailingDot ( left, left_span, dot_span)
11071148 }
11081149 // 1.2 | 1.2e3
11091150 [ IdentLike ( left) , Punct ( '.' ) , IdentLike ( right) ] => {
1110- let ( left_span, dot_span , right_span) = if can_take_span_apart ( ) {
1111- let left_span = span. with_hi ( span. lo ( ) + BytePos :: from_usize ( left. len ( ) ) ) ;
1151+ let ( left_span, right_span) = if can_take_span_apart ( ) {
1152+ let left_span = span. with_hi ( span. lo ( ) + BytePos :: from_usize ( left. len ) ) ;
11121153 let dot_span = span. with_lo ( left_span. hi ( ) ) . with_hi ( left_span. hi ( ) + BytePos ( 1 ) ) ;
11131154 let right_span = span. with_lo ( dot_span. hi ( ) ) ;
1114- ( left_span, dot_span , right_span)
1155+ ( left_span, right_span)
11151156 } else {
1116- ( span, span, span )
1157+ ( span, span)
11171158 } ;
1118- let left = Symbol :: intern ( left) ;
1119- let right = Symbol :: intern ( right) ;
1120- DestructuredFloat :: MiddleDot ( left, left_span, dot_span, right, right_span)
1159+ if left. poisoned {
1160+ self . dcx ( ) . span_err ( left_span, "invalid tuple index" ) ;
1161+ }
1162+ let left = Symbol :: intern ( & left. str ) ;
1163+ if right. poisoned {
1164+ self . dcx ( ) . span_err ( right_span, "invalid tuple index" ) ;
1165+ }
1166+ let right = Symbol :: intern ( & right. str ) ;
1167+ DestructuredFloat :: MiddleDot ( left, left_span, right, right_span)
11211168 }
11221169 // 1e+ | 1e- (recovered)
1123- [ IdentLike ( _ ) , Punct ( '+' | '-' ) ] |
1170+ [ IdentLike ( .. ) , Punct ( '+' | '-' ) ] |
11241171 // 1e+2 | 1e-2
1125- [ IdentLike ( _ ) , Punct ( '+' | '-' ) , IdentLike ( _ ) ] |
1172+ [ IdentLike ( .. ) , Punct ( '+' | '-' ) , IdentLike ( .. ) ] |
11261173 // 1.2e+ | 1.2e-
1127- [ IdentLike ( _ ) , Punct ( '.' ) , IdentLike ( _ ) , Punct ( '+' | '-' ) ] |
1174+ [ IdentLike ( .. ) , Punct ( '.' ) , IdentLike ( .. ) , Punct ( '+' | '-' ) ] |
11281175 // 1.2e+3 | 1.2e-3
1129- [ IdentLike ( _ ) , Punct ( '.' ) , IdentLike ( _ ) , Punct ( '+' | '-' ) , IdentLike ( _ ) ] => {
1176+ [ IdentLike ( .. ) , Punct ( '.' ) , IdentLike ( .. ) , Punct ( '+' | '-' ) , IdentLike ( .. ) ] => {
11301177 // See the FIXME about `TokenCursor` above.
1178+ // FIXME(fmease): We report 2 errors on `x.0e+1`.
1179+ // FIXME(fmease): (preexisting) Too many confusing errs in cases like `x.0x0.0`.
11311180 self . error_unexpected_after_dot ( ) ;
11321181 DestructuredFloat :: Error
11331182 }
@@ -1187,13 +1236,7 @@ impl<'a> Parser<'a> {
11871236 fields. insert ( start_idx, Ident :: new ( sym, sym_span) ) ;
11881237 }
11891238 // 1.2 | 1.2e3
1190- DestructuredFloat :: MiddleDot (
1191- symbol1,
1192- span1,
1193- _dot_span,
1194- symbol2,
1195- span2,
1196- ) => {
1239+ DestructuredFloat :: MiddleDot ( symbol1, span1, symbol2, span2) => {
11971240 trailing_dot = None ;
11981241 fields. insert ( start_idx, Ident :: new ( symbol2, span2) ) ;
11991242 fields. insert ( start_idx, Ident :: new ( symbol1, span1) ) ;
0 commit comments