@@ -118,23 +118,22 @@ enum BlockMode {
118118/// `token::Interpolated` tokens. 
119119macro_rules!  maybe_whole_expr { 
120120 ( $p: expr)  => { 
121-  if  let  token:: Interpolated ( nt)  = $p. token. clone( )  { 
122-  match  * nt { 
123-  token:: NtExpr ( ref e)  | token:: NtLiteral ( ref e)  => { 
121+  if  let  token:: Interpolated ( nt)  = & $p. token { 
122+  match  & * * nt { 
123+  token:: NtExpr ( e)  | token:: NtLiteral ( e)  => { 
124+  let  e = e. clone( ) ; 
124125 $p. bump( ) ; 
125-  return  Ok ( ( * e ) . clone ( ) ) ; 
126+  return  Ok ( e ) ; 
126127 } 
127-  token:: NtPath ( ref path)  => { 
128+  token:: NtPath ( path)  => { 
129+  let  path = path. clone( ) ; 
128130 $p. bump( ) ; 
129-  let  span = $p. span; 
130-  let  kind = ExprKind :: Path ( None ,  ( * path) . clone( ) ) ; 
131-  return  Ok ( $p. mk_expr( span,  kind,  ThinVec :: new( ) ) ) ; 
131+  return  Ok ( $p. mk_expr( $p. span,  ExprKind :: Path ( None ,  path) ,  ThinVec :: new( ) ) ) ; 
132132 } 
133-  token:: NtBlock ( ref block)  => { 
133+  token:: NtBlock ( block)  => { 
134+  let  block = block. clone( ) ; 
134135 $p. bump( ) ; 
135-  let  span = $p. span; 
136-  let  kind = ExprKind :: Block ( ( * block) . clone( ) ,  None ) ; 
137-  return  Ok ( $p. mk_expr( span,  kind,  ThinVec :: new( ) ) ) ; 
136+  return  Ok ( $p. mk_expr( $p. span,  ExprKind :: Block ( block,  None ) ,  ThinVec :: new( ) ) ) ; 
138137 } 
139138 _ => { } , 
140139 } ; 
@@ -145,15 +144,31 @@ macro_rules! maybe_whole_expr {
145144/// As maybe_whole_expr, but for things other than expressions 
146145macro_rules!  maybe_whole { 
147146 ( $p: expr,  $constructor: ident,  |$x: ident| $e: expr)  => { 
148-  if  let  token:: Interpolated ( nt)  = $p. token. clone( )  { 
149-  if  let  token:: $constructor( $x)  = ( * nt) . clone( )  { 
147+  if  let  token:: Interpolated ( nt)  = & $p. token { 
148+  if  let  token:: $constructor( x)  = & * * nt { 
149+  let  $x = x. clone( ) ; 
150150 $p. bump( ) ; 
151151 return  Ok ( $e) ; 
152152 } 
153153 } 
154154 } ; 
155155} 
156156
157+ /// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`. 
158+ macro_rules!  maybe_recover_from_interpolated_ty_qpath { 
159+  ( $self:  expr,  $allow_qpath_recovery:  expr)  => { 
160+  if  $allow_qpath_recovery && $self. look_ahead( 1 ,  |t| t == & token:: ModSep )  { 
161+  if  let  token:: Interpolated ( nt)  = & $self. token { 
162+  if  let  token:: NtTy ( ty)  = & * * nt { 
163+  let  ty = ty. clone( ) ; 
164+  $self. bump( ) ; 
165+  return  $self. maybe_recover_from_bad_qpath_stage_2( $self. prev_span,  ty) ; 
166+  } 
167+  } 
168+  } 
169+  } 
170+ } 
171+ 
157172fn  maybe_append ( mut  lhs :  Vec < Attribute > ,  mut  rhs :  Option < Vec < Attribute > > )  -> Vec < Attribute >  { 
158173 if  let  Some ( ref  mut  rhs)  = rhs { 
159174 lhs. append ( rhs) ; 
@@ -172,48 +187,38 @@ enum PrevTokenKind {
172187 Other , 
173188} 
174189
175- trait  RecoverQPath :  Sized  { 
190+ trait  RecoverQPath :  Sized  +  ' static   { 
176191 const  PATH_STYLE :  PathStyle  = PathStyle :: Expr ; 
177192 fn  to_ty ( & self )  -> Option < P < Ty > > ; 
178-  fn  to_recovered ( & self ,  qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self ; 
179-  fn  to_string ( & self )  -> String ; 
193+  fn  recovered ( qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self ; 
180194} 
181195
182196impl  RecoverQPath  for  Ty  { 
183197 const  PATH_STYLE :  PathStyle  = PathStyle :: Type ; 
184198 fn  to_ty ( & self )  -> Option < P < Ty > >  { 
185199 Some ( P ( self . clone ( ) ) ) 
186200 } 
187-  fn  to_recovered ( & self ,  qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self  { 
188-  Self  {  span :  path. span ,  node :  TyKind :: Path ( qself,  path) ,  id :  self . id  } 
189-  } 
190-  fn  to_string ( & self )  -> String  { 
191-  pprust:: ty_to_string ( self ) 
201+  fn  recovered ( qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self  { 
202+  Self  {  span :  path. span ,  node :  TyKind :: Path ( qself,  path) ,  id :  ast:: DUMMY_NODE_ID  } 
192203 } 
193204} 
194205
195206impl  RecoverQPath  for  Pat  { 
196207 fn  to_ty ( & self )  -> Option < P < Ty > >  { 
197208 self . to_ty ( ) 
198209 } 
199-  fn  to_recovered ( & self ,  qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self  { 
200-  Self  {  span :  path. span ,  node :  PatKind :: Path ( qself,  path) ,  id :  self . id  } 
201-  } 
202-  fn  to_string ( & self )  -> String  { 
203-  pprust:: pat_to_string ( self ) 
210+  fn  recovered ( qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self  { 
211+  Self  {  span :  path. span ,  node :  PatKind :: Path ( qself,  path) ,  id :  ast:: DUMMY_NODE_ID  } 
204212 } 
205213} 
206214
207215impl  RecoverQPath  for  Expr  { 
208216 fn  to_ty ( & self )  -> Option < P < Ty > >  { 
209217 self . to_ty ( ) 
210218 } 
211-  fn  to_recovered ( & self ,   qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self  { 
219+  fn  recovered ( qself :  Option < QSelf > ,  path :  ast:: Path )  -> Self  { 
212220 Self  {  span :  path. span ,  node :  ExprKind :: Path ( qself,  path) , 
213-  id :  self . id ,  attrs :  self . attrs . clone ( )  } 
214-  } 
215-  fn  to_string ( & self )  -> String  { 
216-  pprust:: expr_to_string ( self ) 
221+  attrs :  ThinVec :: new ( ) ,  id :  ast:: DUMMY_NODE_ID  } 
217222 } 
218223} 
219224
@@ -1649,6 +1654,7 @@ impl<'a> Parser<'a> {
16491654
16501655 fn  parse_ty_common ( & mut  self ,  allow_plus :  bool ,  allow_qpath_recovery :  bool , 
16511656 allow_c_variadic :  bool )  -> PResult < ' a ,  P < Ty > >  { 
1657+  maybe_recover_from_interpolated_ty_qpath ! ( self ,  allow_qpath_recovery) ; 
16521658 maybe_whole ! ( self ,  NtTy ,  |x| x) ; 
16531659
16541660 let  lo = self . span ; 
@@ -1800,14 +1806,12 @@ impl<'a> Parser<'a> {
18001806 } ; 
18011807
18021808 let  span = lo. to ( self . prev_span ) ; 
1803-  let  ty = Ty  {  node,  span,  id :  ast:: DUMMY_NODE_ID  } ; 
1809+  let  ty = P ( Ty  {  node,  span,  id :  ast:: DUMMY_NODE_ID  } ) ; 
18041810
18051811 // Try to recover from use of `+` with incorrect priority. 
18061812 self . maybe_report_ambiguous_plus ( allow_plus,  impl_dyn_multi,  & ty) ; 
18071813 self . maybe_recover_from_bad_type_plus ( allow_plus,  & ty) ?; 
1808-  let  ty = self . maybe_recover_from_bad_qpath ( ty,  allow_qpath_recovery) ?; 
1809- 
1810-  Ok ( P ( ty) ) 
1814+  self . maybe_recover_from_bad_qpath ( ty,  allow_qpath_recovery) 
18111815 } 
18121816
18131817 fn  parse_remaining_bounds ( & mut  self ,  generic_params :  Vec < GenericParam > ,  path :  ast:: Path , 
@@ -1878,36 +1882,40 @@ impl<'a> Parser<'a> {
18781882 Ok ( ( ) ) 
18791883 } 
18801884
1881-  // Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`. 
1882-  fn  maybe_recover_from_bad_qpath < T :  RecoverQPath > ( & mut  self ,  base :  T ,  allow_recovery :  bool ) 
1883-  -> PResult < ' a ,  T >  { 
1885+  /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`. 
1886+ /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem` 
1887+ /// tail, and combine them into a `<Ty>::AssocItem` expression/pattern/type. 
1888+ fn  maybe_recover_from_bad_qpath < T :  RecoverQPath > ( & mut  self ,  base :  P < T > ,  allow_recovery :  bool ) 
1889+  -> PResult < ' a ,  P < T > >  { 
18841890 // Do not add `::` to expected tokens. 
1885-  if  !allow_recovery || self . token  != token:: ModSep  { 
1886-  return  Ok ( base) ; 
1891+  if  allow_recovery && self . token  == token:: ModSep  { 
1892+  if  let  Some ( ty)  = base. to_ty ( )  { 
1893+  return  self . maybe_recover_from_bad_qpath_stage_2 ( ty. span ,  ty) ; 
1894+  } 
18871895 } 
1888-  let  ty = match  base. to_ty ( )  { 
1889-  Some ( ty)  => ty, 
1890-  None  => return  Ok ( base) , 
1891-  } ; 
1896+  Ok ( base) 
1897+  } 
18921898
1893-  self . bump ( ) ;  // `::` 
1894-  let  mut  segments = Vec :: new ( ) ; 
1895-  self . parse_path_segments ( & mut  segments,  T :: PATH_STYLE ,  true ) ?; 
1899+  /// Given an already parsed `Ty` parse the `::AssocItem` tail and 
1900+ /// combine them into a `<Ty>::AssocItem` expression/pattern/type. 
1901+ fn  maybe_recover_from_bad_qpath_stage_2 < T :  RecoverQPath > ( & mut  self ,  ty_span :  Span ,  ty :  P < Ty > ) 
1902+  -> PResult < ' a ,  P < T > >  { 
1903+  self . expect ( & token:: ModSep ) ?; 
18961904
1897-  let  span = ty. span . to ( self . prev_span ) ; 
1898-  let  path_span = span. to ( span) ;  // use an empty path since `position` == 0 
1899-  let  recovered = base. to_recovered ( 
1900-  Some ( QSelf  {  ty,  path_span,  position :  0  } ) , 
1901-  ast:: Path  {  segments,  span } , 
1902-  ) ; 
1905+  let  mut  path = ast:: Path  {  segments :  Vec :: new ( ) ,  span :  syntax_pos:: DUMMY_SP  } ; 
1906+  self . parse_path_segments ( & mut  path. segments ,  T :: PATH_STYLE ,  true ) ?; 
1907+  path. span  = ty_span. to ( self . prev_span ) ; 
19031908
1909+  let  ty_str = self . sess . source_map ( ) . span_to_snippet ( ty_span) 
1910+  . unwrap_or_else ( |_| pprust:: ty_to_string ( & ty) ) ; 
19041911 self . diagnostic ( ) 
1905-  . struct_span_err ( span,  "missing angle brackets in associated item path" ) 
1912+  . struct_span_err ( path . span ,  "missing angle brackets in associated item path" ) 
19061913 . span_suggestion (  // this is a best-effort recovery 
1907-  span,  "try" ,  recovered . to_string ( ) ,  Applicability :: MaybeIncorrect 
1914+  path . span ,  "try" ,  format ! ( "<{}>::{}" ,  ty_str ,  path ) ,  Applicability :: MaybeIncorrect 
19081915 ) . emit ( ) ; 
19091916
1910-  Ok ( recovered) 
1917+  let  path_span = ty_span. shrink_to_hi ( ) ;  // use an empty path since `position` == 0 
1918+  Ok ( P ( T :: recovered ( Some ( QSelf  {  ty,  path_span,  position :  0  } ) ,  path) ) ) 
19111919 } 
19121920
19131921 fn  parse_borrowed_pointee ( & mut  self )  -> PResult < ' a ,  TyKind >  { 
@@ -2572,15 +2580,6 @@ impl<'a> Parser<'a> {
25722580 ExprKind :: AssignOp ( binop,  lhs,  rhs) 
25732581 } 
25742582
2575-  pub  fn  mk_mac_expr ( & mut  self ,  span :  Span ,  m :  Mac_ ,  attrs :  ThinVec < Attribute > )  -> P < Expr >  { 
2576-  P ( Expr  { 
2577-  id :  ast:: DUMMY_NODE_ID , 
2578-  node :  ExprKind :: Mac ( source_map:: Spanned  { node :  m,  span :  span} ) , 
2579-  span, 
2580-  attrs, 
2581-  } ) 
2582-  } 
2583- 
25842583 fn  expect_delimited_token_tree ( & mut  self )  -> PResult < ' a ,  ( MacDelimiter ,  TokenStream ) >  { 
25852584 let  delim = match  self . token  { 
25862585 token:: OpenDelim ( delim)  => delim, 
@@ -2610,6 +2609,7 @@ impl<'a> Parser<'a> {
26102609/// N.B., this does not parse outer attributes, and is private because it only works 
26112610/// correctly if called from `parse_dot_or_call_expr()`. 
26122611fn  parse_bottom_expr ( & mut  self )  -> PResult < ' a ,  P < Expr > >  { 
2612+  maybe_recover_from_interpolated_ty_qpath ! ( self ,  true ) ; 
26132613 maybe_whole_expr ! ( self ) ; 
26142614
26152615 // Outer attributes are already parsed and will be 
@@ -2824,29 +2824,23 @@ impl<'a> Parser<'a> {
28242824 db. note ( "variable declaration using `let` is a statement" ) ; 
28252825 return  Err ( db) ; 
28262826 }  else  if  self . token . is_path_start ( )  { 
2827-  let  pth  = self . parse_path ( PathStyle :: Expr ) ?; 
2827+  let  path  = self . parse_path ( PathStyle :: Expr ) ?; 
28282828
28292829 // `!`, as an operator, is prefix, so we know this isn't that 
28302830 if  self . eat ( & token:: Not )  { 
28312831 // MACRO INVOCATION expression 
28322832 let  ( delim,  tts)  = self . expect_delimited_token_tree ( ) ?; 
2833-  let  hi = self . prev_span ; 
2834-  let  node = Mac_  {  path :  pth,  tts,  delim } ; 
2835-  return  Ok ( self . mk_mac_expr ( lo. to ( hi) ,  node,  attrs) ) 
2836-  } 
2837-  if  self . check ( & token:: OpenDelim ( token:: Brace ) )  { 
2833+  hi = self . prev_span ; 
2834+  ex = ExprKind :: Mac ( respan ( lo. to ( hi) ,  Mac_  {  path,  tts,  delim } ) ) ; 
2835+  }  else  if  self . check ( & token:: OpenDelim ( token:: Brace ) )  &&
2836+  !self . restrictions . contains ( Restrictions :: NO_STRUCT_LITERAL )  { 
28382837 // This is a struct literal, unless we're prohibited 
28392838 // from parsing struct literals here. 
2840-  let  prohibited = self . restrictions . contains ( 
2841-  Restrictions :: NO_STRUCT_LITERAL 
2842-  ) ; 
2843-  if  !prohibited { 
2844-  return  self . parse_struct_expr ( lo,  pth,  attrs) ; 
2845-  } 
2839+  return  self . parse_struct_expr ( lo,  path,  attrs) ; 
2840+  }  else  { 
2841+  hi = path. span ; 
2842+  ex = ExprKind :: Path ( None ,  path) ; 
28462843 } 
2847- 
2848-  hi = pth. span ; 
2849-  ex = ExprKind :: Path ( None ,  pth) ; 
28502844 }  else  { 
28512845 if  !self . unclosed_delims . is_empty ( )  && self . check ( & token:: Semi )  { 
28522846 // Don't complain about bare semicolons after unclosed braces 
@@ -2881,10 +2875,8 @@ impl<'a> Parser<'a> {
28812875 } 
28822876 } 
28832877
2884-  let  expr = Expr  {  node :  ex,  span :  lo. to ( hi) ,  id :  ast:: DUMMY_NODE_ID ,  attrs } ; 
2885-  let  expr = self . maybe_recover_from_bad_qpath ( expr,  true ) ?; 
2886- 
2887-  return  Ok ( P ( expr) ) ; 
2878+  let  expr = self . mk_expr ( lo. to ( hi) ,  ex,  attrs) ; 
2879+  self . maybe_recover_from_bad_qpath ( expr,  true ) 
28882880 } 
28892881
28902882 fn  parse_struct_expr ( & mut  self ,  lo :  Span ,  pth :  ast:: Path ,  mut  attrs :  ThinVec < Attribute > ) 
@@ -4584,6 +4576,7 @@ impl<'a> Parser<'a> {
45844576 allow_range_pat :  bool , 
45854577 expected :  Option < & ' static  str > , 
45864578 )  -> PResult < ' a ,  P < Pat > >  { 
4579+  maybe_recover_from_interpolated_ty_qpath ! ( self ,  true ) ; 
45874580 maybe_whole ! ( self ,  NtPat ,  |x| x) ; 
45884581
45894582 let  lo = self . span ; 
@@ -4759,7 +4752,7 @@ impl<'a> Parser<'a> {
47594752 } 
47604753 } 
47614754
4762-  let  pat = Pat  {  node :  pat,  span :  lo. to ( self . prev_span ) ,  id :  ast:: DUMMY_NODE_ID  } ; 
4755+  let  pat = P ( Pat  {  node :  pat,  span :  lo. to ( self . prev_span ) ,  id :  ast:: DUMMY_NODE_ID  } ) ; 
47634756 let  pat = self . maybe_recover_from_bad_qpath ( pat,  true ) ?; 
47644757
47654758 if  !allow_range_pat { 
@@ -4785,7 +4778,7 @@ impl<'a> Parser<'a> {
47854778 } 
47864779 } 
47874780
4788-  Ok ( P ( pat) ) 
4781+  Ok ( pat) 
47894782 } 
47904783
47914784 /// Parses `ident` or `ident @ pat`. 
@@ -5249,7 +5242,8 @@ impl<'a> Parser<'a> {
52495242 self . warn_missing_semicolon ( ) ; 
52505243 StmtKind :: Mac ( P ( ( mac,  style,  attrs. into ( ) ) ) ) 
52515244 }  else  { 
5252-  let  e = self . mk_mac_expr ( lo. to ( hi) ,  mac. node ,  ThinVec :: new ( ) ) ; 
5245+  let  e = self . mk_expr ( mac. span ,  ExprKind :: Mac ( mac) ,  ThinVec :: new ( ) ) ; 
5246+  let  e = self . maybe_recover_from_bad_qpath ( e,  true ) ?; 
52535247 let  e = self . parse_dot_or_call_expr_with ( e,  lo,  attrs. into ( ) ) ?; 
52545248 let  e = self . parse_assoc_expr_with ( 0 ,  LhsExpr :: AlreadyParsed ( e) ) ?; 
52555249 StmtKind :: Expr ( e) 
0 commit comments