1 use crate::errors::{ 2 self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters, 3 UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody, 4 WhereClauseBeforeTupleStructBodySugg, 5 }; 6 7 use super::{ForceCollect, Parser, TrailingToken}; 8 9 use ast::token::Delimiter; 10 use rustc_ast::token; 11 use rustc_ast::{ 12 self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, 13 }; 14 use rustc_errors::{Applicability, PResult}; 15 use rustc_span::symbol::{kw, Ident}; 16 use rustc_span::Span; 17 use thin_vec::ThinVec; 18 19 enum PredicateOrStructBody { 20 Predicate(ast::WherePredicate), 21 StructBody(ThinVec<ast::FieldDef>), 22 } 23 24 impl<'a> Parser<'a> { 25 /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. 26 /// 27 /// ```text 28 /// BOUND = LT_BOUND (e.g., `'a`) 29 /// ``` parse_lt_param_bounds(&mut self) -> GenericBounds30 fn parse_lt_param_bounds(&mut self) -> GenericBounds { 31 let mut lifetimes = Vec::new(); 32 while self.check_lifetime() { 33 lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime())); 34 35 if !self.eat_plus() { 36 break; 37 } 38 } 39 lifetimes 40 } 41 42 /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`. parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam>43 fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> { 44 let ident = self.parse_ident()?; 45 46 // We might have a typo'd `Const` that was parsed as a type parameter. 47 if self.may_recover() 48 && ident.name.as_str().to_ascii_lowercase() == kw::Const.as_str() 49 && self.check_ident() 50 // `Const` followed by IDENT 51 { 52 return Ok(self.recover_const_param_with_mistyped_const(preceding_attrs, ident)?); 53 } 54 55 // Parse optional colon and param bounds. 56 let mut colon_span = None; 57 let bounds = if self.eat(&token::Colon) { 58 colon_span = Some(self.prev_token.span); 59 // recover from `impl Trait` in type param bound 60 if self.token.is_keyword(kw::Impl) { 61 let impl_span = self.token.span; 62 let snapshot = self.create_snapshot_for_diagnostic(); 63 match self.parse_ty() { 64 Ok(p) => { 65 if let TyKind::ImplTrait(_, bounds) = &p.kind { 66 let span = impl_span.to(self.token.span.shrink_to_lo()); 67 let mut err = self.struct_span_err( 68 span, 69 "expected trait bound, found `impl Trait` type", 70 ); 71 err.span_label(span, "not a trait"); 72 if let [bound, ..] = &bounds[..] { 73 err.span_suggestion_verbose( 74 impl_span.until(bound.span()), 75 "use the trait bounds directly", 76 String::new(), 77 Applicability::MachineApplicable, 78 ); 79 } 80 err.emit(); 81 return Err(err); 82 } 83 } 84 Err(err) => { 85 err.cancel(); 86 } 87 } 88 self.restore_snapshot(snapshot); 89 } 90 self.parse_generic_bounds()? 91 } else { 92 Vec::new() 93 }; 94 95 let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; 96 Ok(GenericParam { 97 ident, 98 id: ast::DUMMY_NODE_ID, 99 attrs: preceding_attrs, 100 bounds, 101 kind: GenericParamKind::Type { default }, 102 is_placeholder: false, 103 colon_span, 104 }) 105 } 106 parse_const_param( &mut self, preceding_attrs: AttrVec, ) -> PResult<'a, GenericParam>107 pub(crate) fn parse_const_param( 108 &mut self, 109 preceding_attrs: AttrVec, 110 ) -> PResult<'a, GenericParam> { 111 let const_span = self.token.span; 112 113 self.expect_keyword(kw::Const)?; 114 let ident = self.parse_ident()?; 115 self.expect(&token::Colon)?; 116 let ty = self.parse_ty()?; 117 118 // Parse optional const generics default value. 119 let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; 120 121 Ok(GenericParam { 122 ident, 123 id: ast::DUMMY_NODE_ID, 124 attrs: preceding_attrs, 125 bounds: Vec::new(), 126 kind: GenericParamKind::Const { ty, kw_span: const_span, default }, 127 is_placeholder: false, 128 colon_span: None, 129 }) 130 } 131 recover_const_param_with_mistyped_const( &mut self, preceding_attrs: AttrVec, mistyped_const_ident: Ident, ) -> PResult<'a, GenericParam>132 pub(crate) fn recover_const_param_with_mistyped_const( 133 &mut self, 134 preceding_attrs: AttrVec, 135 mistyped_const_ident: Ident, 136 ) -> PResult<'a, GenericParam> { 137 let ident = self.parse_ident()?; 138 self.expect(&token::Colon)?; 139 let ty = self.parse_ty()?; 140 141 // Parse optional const generics default value. 142 let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; 143 144 let mut err = self.struct_span_err( 145 mistyped_const_ident.span, 146 format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()), 147 ); 148 err.span_suggestion_verbose( 149 mistyped_const_ident.span, 150 "use the `const` keyword", 151 kw::Const.as_str(), 152 Applicability::MachineApplicable, 153 ); 154 err.emit(); 155 156 Ok(GenericParam { 157 ident, 158 id: ast::DUMMY_NODE_ID, 159 attrs: preceding_attrs, 160 bounds: Vec::new(), 161 kind: GenericParamKind::Const { ty, kw_span: mistyped_const_ident.span, default }, 162 is_placeholder: false, 163 colon_span: None, 164 }) 165 } 166 167 /// Parses a (possibly empty) list of lifetime and type parameters, possibly including 168 /// a trailing comma and erroneous trailing attributes. parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>>169 pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> { 170 let mut params = ThinVec::new(); 171 let mut done = false; 172 while !done { 173 let attrs = self.parse_outer_attributes()?; 174 let param = 175 self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { 176 if this.eat_keyword_noexpect(kw::SelfUpper) { 177 // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing 178 // as if `Self` never existed. 179 this.sess.emit_err(UnexpectedSelfInGenericParameters { 180 span: this.prev_token.span, 181 }); 182 183 this.eat(&token::Comma); 184 } 185 186 let param = if this.check_lifetime() { 187 let lifetime = this.expect_lifetime(); 188 // Parse lifetime parameter. 189 let (colon_span, bounds) = if this.eat(&token::Colon) { 190 (Some(this.prev_token.span), this.parse_lt_param_bounds()) 191 } else { 192 (None, Vec::new()) 193 }; 194 195 if this.check_noexpect(&token::Eq) 196 && this.look_ahead(1, |t| t.is_lifetime()) 197 { 198 let lo = this.token.span; 199 // Parse `= 'lifetime`. 200 this.bump(); // `=` 201 this.bump(); // `'lifetime` 202 let span = lo.to(this.prev_token.span); 203 this.sess.emit_err( 204 UnexpectedDefaultValueForLifetimeInGenericParameters { span }, 205 ); 206 } 207 208 Some(ast::GenericParam { 209 ident: lifetime.ident, 210 id: lifetime.id, 211 attrs, 212 bounds, 213 kind: ast::GenericParamKind::Lifetime, 214 is_placeholder: false, 215 colon_span, 216 }) 217 } else if this.check_keyword(kw::Const) { 218 // Parse const parameter. 219 Some(this.parse_const_param(attrs)?) 220 } else if this.check_ident() { 221 // Parse type parameter. 222 Some(this.parse_ty_param(attrs)?) 223 } else if this.token.can_begin_type() { 224 // Trying to write an associated type bound? (#26271) 225 let snapshot = this.create_snapshot_for_diagnostic(); 226 match this.parse_ty_where_predicate() { 227 Ok(where_predicate) => { 228 this.sess.emit_err(errors::BadAssocTypeBounds { 229 span: where_predicate.span(), 230 }); 231 // FIXME - try to continue parsing other generics? 232 return Ok((None, TrailingToken::None)); 233 } 234 Err(err) => { 235 err.cancel(); 236 // FIXME - maybe we should overwrite 'self' outside of `collect_tokens`? 237 this.restore_snapshot(snapshot); 238 return Ok((None, TrailingToken::None)); 239 } 240 } 241 } else { 242 // Check for trailing attributes and stop parsing. 243 if !attrs.is_empty() { 244 if !params.is_empty() { 245 this.sess 246 .emit_err(errors::AttrAfterGeneric { span: attrs[0].span }); 247 } else { 248 this.sess 249 .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span }); 250 } 251 } 252 return Ok((None, TrailingToken::None)); 253 }; 254 255 if !this.eat(&token::Comma) { 256 done = true; 257 } 258 // We just ate the comma, so no need to use `TrailingToken` 259 Ok((param, TrailingToken::None)) 260 })?; 261 262 if let Some(param) = param { 263 params.push(param); 264 } else { 265 break; 266 } 267 } 268 Ok(params) 269 } 270 271 /// Parses a set of optional generic type parameter declarations. Where 272 /// clauses are not parsed here, and must be added later via 273 /// `parse_where_clause()`. 274 /// 275 /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > ) 276 /// | ( < lifetimes , typaramseq ( , )? > ) 277 /// where typaramseq = ( typaram ) | ( typaram , typaramseq ) parse_generics(&mut self) -> PResult<'a, ast::Generics>278 pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { 279 let span_lo = self.token.span; 280 let (params, span) = if self.eat_lt() { 281 let params = self.parse_generic_params()?; 282 self.expect_gt()?; 283 (params, span_lo.to(self.prev_token.span)) 284 } else { 285 (ThinVec::new(), self.prev_token.span.shrink_to_hi()) 286 }; 287 Ok(ast::Generics { 288 params, 289 where_clause: WhereClause { 290 has_where_token: false, 291 predicates: ThinVec::new(), 292 span: self.prev_token.span.shrink_to_hi(), 293 }, 294 span, 295 }) 296 } 297 298 /// Parses an optional where-clause. 299 /// 300 /// ```ignore (only-for-syntax-highlight) 301 /// where T : Trait<U, V> + 'b, 'a : 'b 302 /// ``` parse_where_clause(&mut self) -> PResult<'a, WhereClause>303 pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> { 304 self.parse_where_clause_common(None).map(|(clause, _)| clause) 305 } 306 parse_struct_where_clause( &mut self, struct_name: Ident, body_insertion_point: Span, ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)>307 pub(super) fn parse_struct_where_clause( 308 &mut self, 309 struct_name: Ident, 310 body_insertion_point: Span, 311 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> { 312 self.parse_where_clause_common(Some((struct_name, body_insertion_point))) 313 } 314 parse_where_clause_common( &mut self, struct_: Option<(Ident, Span)>, ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)>315 fn parse_where_clause_common( 316 &mut self, 317 struct_: Option<(Ident, Span)>, 318 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> { 319 let mut where_clause = WhereClause { 320 has_where_token: false, 321 predicates: ThinVec::new(), 322 span: self.prev_token.span.shrink_to_hi(), 323 }; 324 let mut tuple_struct_body = None; 325 326 if !self.eat_keyword(kw::Where) { 327 return Ok((where_clause, None)); 328 } 329 where_clause.has_where_token = true; 330 let where_lo = self.prev_token.span; 331 332 // We are considering adding generics to the `where` keyword as an alternative higher-rank 333 // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking 334 // change we parse those generics now, but report an error. 335 if self.choose_generics_over_qpath(0) { 336 let generics = self.parse_generics()?; 337 self.sess.emit_err(errors::WhereOnGenerics { span: generics.span }); 338 } 339 340 loop { 341 let where_sp = where_lo.to(self.prev_token.span); 342 let pred_lo = self.token.span; 343 if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { 344 let lifetime = self.expect_lifetime(); 345 // Bounds starting with a colon are mandatory, but possibly empty. 346 self.expect(&token::Colon)?; 347 let bounds = self.parse_lt_param_bounds(); 348 where_clause.predicates.push(ast::WherePredicate::RegionPredicate( 349 ast::WhereRegionPredicate { 350 span: pred_lo.to(self.prev_token.span), 351 lifetime, 352 bounds, 353 }, 354 )); 355 } else if self.check_type() { 356 match self.parse_ty_where_predicate_or_recover_tuple_struct_body( 357 struct_, pred_lo, where_sp, 358 )? { 359 PredicateOrStructBody::Predicate(pred) => where_clause.predicates.push(pred), 360 PredicateOrStructBody::StructBody(body) => { 361 tuple_struct_body = Some(body); 362 break; 363 } 364 } 365 } else { 366 break; 367 } 368 369 let prev_token = self.prev_token.span; 370 let ate_comma = self.eat(&token::Comma); 371 372 if self.eat_keyword_noexpect(kw::Where) { 373 self.sess.emit_err(MultipleWhereClauses { 374 span: self.token.span, 375 previous: pred_lo, 376 between: prev_token.shrink_to_hi().to(self.prev_token.span), 377 }); 378 } else if !ate_comma { 379 break; 380 } 381 } 382 383 where_clause.span = where_lo.to(self.prev_token.span); 384 Ok((where_clause, tuple_struct_body)) 385 } 386 parse_ty_where_predicate_or_recover_tuple_struct_body( &mut self, struct_: Option<(Ident, Span)>, pred_lo: Span, where_sp: Span, ) -> PResult<'a, PredicateOrStructBody>387 fn parse_ty_where_predicate_or_recover_tuple_struct_body( 388 &mut self, 389 struct_: Option<(Ident, Span)>, 390 pred_lo: Span, 391 where_sp: Span, 392 ) -> PResult<'a, PredicateOrStructBody> { 393 let mut snapshot = None; 394 395 if let Some(struct_) = struct_ 396 && self.may_recover() 397 && self.token.kind == token::OpenDelim(Delimiter::Parenthesis) 398 { 399 snapshot = Some((struct_, self.create_snapshot_for_diagnostic())); 400 }; 401 402 match self.parse_ty_where_predicate() { 403 Ok(pred) => Ok(PredicateOrStructBody::Predicate(pred)), 404 Err(type_err) => { 405 let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else { 406 return Err(type_err); 407 }; 408 409 // Check if we might have encountered an out of place tuple struct body. 410 match snapshot.parse_tuple_struct_body() { 411 // Since we don't know the exact reason why we failed to parse the 412 // predicate (we might have stumbled upon something bogus like `(T): ?`), 413 // employ a simple heuristic to weed out some pathological cases: 414 // Look for a semicolon (strong indicator) or anything that might mark 415 // the end of the item (weak indicator) following the body. 416 Ok(body) 417 if matches!(snapshot.token.kind, token::Semi | token::Eof) 418 || snapshot.token.can_begin_item() => 419 { 420 type_err.cancel(); 421 422 let body_sp = pred_lo.to(snapshot.prev_token.span); 423 let map = self.sess.source_map(); 424 425 self.sess.emit_err(WhereClauseBeforeTupleStructBody { 426 span: where_sp, 427 name: struct_name.span, 428 body: body_sp, 429 sugg: map.span_to_snippet(body_sp).ok().map(|body| { 430 WhereClauseBeforeTupleStructBodySugg { 431 left: body_insertion_point.shrink_to_hi(), 432 snippet: body, 433 right: map.end_point(where_sp).to(body_sp), 434 } 435 }), 436 }); 437 438 self.restore_snapshot(snapshot); 439 Ok(PredicateOrStructBody::StructBody(body)) 440 } 441 Ok(_) => Err(type_err), 442 Err(body_err) => { 443 body_err.cancel(); 444 Err(type_err) 445 } 446 } 447 } 448 } 449 } 450 parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate>451 fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> { 452 let lo = self.token.span; 453 // Parse optional `for<'a, 'b>`. 454 // This `for` is parsed greedily and applies to the whole predicate, 455 // the bounded type can have its own `for` applying only to it. 456 // Examples: 457 // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>` 458 // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>` 459 // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>` 460 let lifetime_defs = self.parse_late_bound_lifetime_defs()?; 461 462 // Parse type with mandatory colon and (possibly empty) bounds, 463 // or with mandatory equality sign and the second type. 464 let ty = self.parse_ty_for_where_clause()?; 465 if self.eat(&token::Colon) { 466 let bounds = self.parse_generic_bounds()?; 467 Ok(ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { 468 span: lo.to(self.prev_token.span), 469 bound_generic_params: lifetime_defs, 470 bounded_ty: ty, 471 bounds, 472 })) 473 // FIXME: Decide what should be used here, `=` or `==`. 474 // FIXME: We are just dropping the binders in lifetime_defs on the floor here. 475 } else if self.eat(&token::Eq) || self.eat(&token::EqEq) { 476 let rhs_ty = self.parse_ty()?; 477 Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { 478 span: lo.to(self.prev_token.span), 479 lhs_ty: ty, 480 rhs_ty, 481 })) 482 } else { 483 self.maybe_recover_bounds_doubled_colon(&ty)?; 484 self.unexpected() 485 } 486 } 487 choose_generics_over_qpath(&self, start: usize) -> bool488 pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool { 489 // There's an ambiguity between generic parameters and qualified paths in impls. 490 // If we see `<` it may start both, so we have to inspect some following tokens. 491 // The following combinations can only start generics, 492 // but not qualified paths (with one exception): 493 // `<` `>` - empty generic parameters 494 // `<` `#` - generic parameters with attributes 495 // `<` (LIFETIME|IDENT) `>` - single generic parameter 496 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list 497 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds 498 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default 499 // `<` const - generic const parameter 500 // `<` IDENT `?` - RECOVERY for `impl<T ?Bound` missing a `:`, meant to 501 // avoid the `T?` to `Option<T>` recovery for types. 502 // The only truly ambiguous case is 503 // `<` IDENT `>` `::` IDENT ... 504 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`) 505 // because this is what almost always expected in practice, qualified paths in impls 506 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment. 507 self.look_ahead(start, |t| t == &token::Lt) 508 && (self.look_ahead(start + 1, |t| t == &token::Pound || t == &token::Gt) 509 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident()) 510 && self.look_ahead(start + 2, |t| { 511 matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq) 512 // Recovery-only branch -- this could be removed, 513 // since it only affects diagnostics currently. 514 || matches!(t.kind, token::Question) 515 }) 516 || self.is_keyword_ahead(start + 1, &[kw::Const])) 517 } 518 } 519