1use rustc_ast::{
2 self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind,
3 WhereClause, token,
4};
5use rustc_errors::{Applicability, PResult};
6use rustc_span::{Ident, Span, kw, sym};
7use thin_vec::ThinVec;
8
9use super::{ForceCollect, Parser, Trailing, UsePreAttrPos};
10use crate::errors::{
11 self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
12 UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
13 WhereClauseBeforeTupleStructBodySugg,
14};
15use crate::exp;
16
17enum PredicateKindOrStructBody {
18 PredicateKind(ast::WherePredicateKind),
19 StructBody(ThinVec<ast::FieldDef>),
20}
21
22impl<'a> Parser<'a> {
23 fn parse_lt_param_bounds(&mut self) -> GenericBounds {
29 let mut lifetimes = Vec::new();
30 while self.check_lifetime() {
31 lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
32
33 if !self.eat_plus() {
34 break;
35 }
36 }
37 lifetimes
38 }
39
40 fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> {
42 let ident = self.parse_ident()?;
43
44 if self.may_recover()
46 && ident.name.as_str().to_ascii_lowercase() == kw::Const.as_str()
47 && self.check_ident()
48 {
50 return self.recover_const_param_with_mistyped_const(preceding_attrs, ident);
51 }
52
53 let mut colon_span = None;
55 let bounds = if self.eat(exp!(Colon)) {
56 colon_span = Some(self.prev_token.span);
57 if self.token.is_keyword(kw::Impl) {
59 let impl_span = self.token.span;
60 let snapshot = self.create_snapshot_for_diagnostic();
61 match self.parse_ty() {
62 Ok(p) => {
63 if let TyKind::ImplTrait(_, bounds) = &p.kind {
64 let span = impl_span.to(self.token.span.shrink_to_lo());
65 let mut err = self.dcx().struct_span_err(
66 span,
67 "expected trait bound, found `impl Trait` type",
68 );
69 err.span_label(span, "not a trait");
70 if let [bound, ..] = &bounds[..] {
71 err.span_suggestion_verbose(
72 impl_span.until(bound.span()),
73 "use the trait bounds directly",
74 String::new(),
75 Applicability::MachineApplicable,
76 );
77 }
78 return Err(err);
79 }
80 }
81 Err(err) => {
82 err.cancel();
83 }
84 }
85 self.restore_snapshot(snapshot);
86 }
87 self.parse_generic_bounds()?
88 } else {
89 Vec::new()
90 };
91
92 let default = if self.eat(exp!(Eq)) { Some(self.parse_ty()?) } else { None };
93 Ok(GenericParam {
94 ident,
95 id: ast::DUMMY_NODE_ID,
96 attrs: preceding_attrs,
97 bounds,
98 kind: GenericParamKind::Type { default },
99 is_placeholder: false,
100 colon_span,
101 })
102 }
103
104 pub(crate) fn parse_const_param(
105 &mut self,
106 preceding_attrs: AttrVec,
107 ) -> PResult<'a, GenericParam> {
108 let const_span = self.token.span;
109
110 self.expect_keyword(exp!(Const))?;
111 let ident = self.parse_ident()?;
112 self.expect(exp!(Colon))?;
113 let ty = self.parse_ty()?;
114
115 let default = if self.eat(exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
117 let span = if let Some(ref default) = default {
118 const_span.to(default.value.span)
119 } else {
120 const_span.to(ty.span)
121 };
122
123 Ok(GenericParam {
124 ident,
125 id: ast::DUMMY_NODE_ID,
126 attrs: preceding_attrs,
127 bounds: Vec::new(),
128 kind: GenericParamKind::Const { ty, span, default },
129 is_placeholder: false,
130 colon_span: None,
131 })
132 }
133
134 pub(crate) fn recover_const_param_with_mistyped_const(
135 &mut self,
136 preceding_attrs: AttrVec,
137 mistyped_const_ident: Ident,
138 ) -> PResult<'a, GenericParam> {
139 let ident = self.parse_ident()?;
140 self.expect(exp!(Colon))?;
141 let ty = self.parse_ty()?;
142
143 let default = if self.eat(exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
145 let span = if let Some(ref default) = default {
146 mistyped_const_ident.span.to(default.value.span)
147 } else {
148 mistyped_const_ident.span.to(ty.span)
149 };
150
151 self.dcx()
152 .struct_span_err(
153 mistyped_const_ident.span,
154 format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
155 )
156 .with_span_suggestion_verbose(
157 mistyped_const_ident.span,
158 "use the `const` keyword",
159 kw::Const,
160 Applicability::MachineApplicable,
161 )
162 .emit();
163
164 Ok(GenericParam {
165 ident,
166 id: ast::DUMMY_NODE_ID,
167 attrs: preceding_attrs,
168 bounds: Vec::new(),
169 kind: GenericParamKind::Const { ty, span, default },
170 is_placeholder: false,
171 colon_span: None,
172 })
173 }
174
175 pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
181 let mut params = ThinVec::new();
182 let mut done = false;
183 while !done {
184 let attrs = self.parse_outer_attributes()?;
185 let param = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
186 if this.eat_keyword_noexpect(kw::SelfUpper) {
187 this.dcx()
190 .emit_err(UnexpectedSelfInGenericParameters { span: this.prev_token.span });
191
192 let _ = this.eat(exp!(Comma));
194 }
195
196 let param = if this.check_lifetime() {
197 let lifetime = this.expect_lifetime();
198 let (colon_span, bounds) = if this.eat(exp!(Colon)) {
200 (Some(this.prev_token.span), this.parse_lt_param_bounds())
201 } else {
202 (None, Vec::new())
203 };
204
205 if this.check_noexpect(&token::Eq) && this.look_ahead(1, |t| t.is_lifetime()) {
206 let lo = this.token.span;
207 this.bump(); this.bump(); let span = lo.to(this.prev_token.span);
211 this.dcx().emit_err(UnexpectedDefaultValueForLifetimeInGenericParameters {
212 span,
213 });
214 }
215
216 Some(ast::GenericParam {
217 ident: lifetime.ident,
218 id: lifetime.id,
219 attrs,
220 bounds,
221 kind: ast::GenericParamKind::Lifetime,
222 is_placeholder: false,
223 colon_span,
224 })
225 } else if this.check_keyword(exp!(Const)) {
226 Some(this.parse_const_param(attrs)?)
228 } else if this.check_ident() {
229 Some(this.parse_ty_param(attrs)?)
231 } else if this.token.can_begin_type() {
232 let snapshot = this.create_snapshot_for_diagnostic();
234 let lo = this.token.span;
235 match this.parse_ty_where_predicate_kind() {
236 Ok(_) => {
237 this.dcx().emit_err(errors::BadAssocTypeBounds {
238 span: lo.to(this.prev_token.span),
239 });
240 }
242 Err(err) => {
243 err.cancel();
244 this.restore_snapshot(snapshot);
246 }
247 }
248 return Ok((None, Trailing::No, UsePreAttrPos::No));
249 } else {
250 if !attrs.is_empty() {
252 if !params.is_empty() {
253 this.dcx().emit_err(errors::AttrAfterGeneric { span: attrs[0].span });
254 } else {
255 this.dcx()
256 .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span });
257 }
258 }
259 return Ok((None, Trailing::No, UsePreAttrPos::No));
260 };
261
262 if !this.eat(exp!(Comma)) {
263 done = true;
264 }
265 Ok((param, Trailing::No, UsePreAttrPos::No))
267 })?;
268
269 if let Some(param) = param {
270 params.push(param);
271 } else {
272 break;
273 }
274 }
275 Ok(params)
276 }
277
278 pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
286 if self.eat_noexpect(&token::PathSep) {
289 self.dcx()
290 .emit_err(errors::InvalidPathSepInFnDefinition { span: self.prev_token.span });
291 }
292
293 let span_lo = self.token.span;
294 let (params, span) = if self.eat_lt() {
295 let params = self.parse_generic_params()?;
296 self.expect_gt_or_maybe_suggest_closing_generics(¶ms)?;
297 (params, span_lo.to(self.prev_token.span))
298 } else {
299 (ThinVec::new(), self.prev_token.span.shrink_to_hi())
300 };
301 Ok(ast::Generics {
302 params,
303 where_clause: WhereClause {
304 has_where_token: false,
305 predicates: ThinVec::new(),
306 span: self.prev_token.span.shrink_to_hi(),
307 },
308 span,
309 })
310 }
311
312 pub(super) fn parse_contract(&mut self) -> PResult<'a, Option<Box<ast::FnContract>>> {
315 let (declarations, requires) = self.parse_contract_requires()?;
316 let ensures = self.parse_contract_ensures()?;
317
318 if requires.is_none() && ensures.is_none() {
319 Ok(None)
320 } else {
321 Ok(Some(Box::new(ast::FnContract { declarations, requires, ensures })))
322 }
323 }
324
325 fn parse_contract_requires(
326 &mut self,
327 ) -> PResult<'a, (ThinVec<rustc_ast::Stmt>, Option<Box<rustc_ast::Expr>>)> {
328 Ok(if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
329 self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
330 let mut decls_and_precond = self.parse_block()?;
331
332 let precond = match decls_and_precond.stmts.pop() {
333 Some(precond) => match precond.kind {
334 rustc_ast::StmtKind::Expr(expr) => expr,
335 _ => self.mk_unit_expr(decls_and_precond.span),
338 },
339 None => self.mk_unit_expr(decls_and_precond.span),
340 };
341 let precond = self.mk_closure_expr(precond.span, precond);
342 let decls = decls_and_precond.stmts;
343 (decls, Some(precond))
344 } else {
345 (Default::default(), None)
346 })
347 }
348
349 fn parse_contract_ensures(&mut self) -> PResult<'a, Option<Box<rustc_ast::Expr>>> {
350 Ok(if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
351 self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
352 let postcond = self.parse_expr()?;
353 Some(postcond)
354 } else {
355 None
356 })
357 }
358
359 pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
365 self.parse_where_clause_common(None).map(|(clause, _)| clause)
366 }
367
368 pub(super) fn parse_struct_where_clause(
369 &mut self,
370 struct_name: Ident,
371 body_insertion_point: Span,
372 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
373 self.parse_where_clause_common(Some((struct_name, body_insertion_point)))
374 }
375
376 fn parse_where_clause_common(
377 &mut self,
378 struct_: Option<(Ident, Span)>,
379 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
380 let mut where_clause = WhereClause {
381 has_where_token: false,
382 predicates: ThinVec::new(),
383 span: self.prev_token.span.shrink_to_hi(),
384 };
385 let mut tuple_struct_body = None;
386
387 if !self.eat_keyword(exp!(Where)) {
388 return Ok((where_clause, None));
389 }
390
391 if self.eat_noexpect(&token::Colon) {
392 let colon_span = self.prev_token.span;
393 self.dcx()
394 .struct_span_err(colon_span, "unexpected colon after `where`")
395 .with_span_suggestion_short(
396 colon_span,
397 "remove the colon",
398 "",
399 Applicability::MachineApplicable,
400 )
401 .emit();
402 }
403
404 where_clause.has_where_token = true;
405 let where_lo = self.prev_token.span;
406
407 if self.choose_generics_over_qpath(0) {
411 let generics = self.parse_generics()?;
412 self.dcx().emit_err(errors::WhereOnGenerics { span: generics.span });
413 }
414
415 loop {
416 let where_sp = where_lo.to(self.prev_token.span);
417 let attrs = self.parse_outer_attributes()?;
418 let pred_lo = self.token.span;
419 let predicate = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
420 for attr in &attrs {
421 self.psess.gated_spans.gate(sym::where_clause_attrs, attr.span);
422 }
423 let kind = if this.check_lifetime() && this.look_ahead(1, |t| !t.is_like_plus()) {
424 let lifetime = this.expect_lifetime();
425 this.expect(exp!(Colon))?;
427 let bounds = this.parse_lt_param_bounds();
428 Some(ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
429 lifetime,
430 bounds,
431 }))
432 } else if this.check_type() {
433 match this.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
434 struct_, pred_lo, where_sp,
435 )? {
436 PredicateKindOrStructBody::PredicateKind(kind) => Some(kind),
437 PredicateKindOrStructBody::StructBody(body) => {
438 tuple_struct_body = Some(body);
439 None
440 }
441 }
442 } else {
443 None
444 };
445 let predicate = kind.map(|kind| ast::WherePredicate {
446 attrs,
447 kind,
448 id: DUMMY_NODE_ID,
449 span: pred_lo.to(this.prev_token.span),
450 is_placeholder: false,
451 });
452 Ok((predicate, Trailing::No, UsePreAttrPos::No))
453 })?;
454 match predicate {
455 Some(predicate) => where_clause.predicates.push(predicate),
456 None => break,
457 }
458
459 let prev_token = self.prev_token.span;
460 let ate_comma = self.eat(exp!(Comma));
461
462 if self.eat_keyword_noexpect(kw::Where) {
463 self.dcx().emit_err(MultipleWhereClauses {
464 span: self.token.span,
465 previous: pred_lo,
466 between: prev_token.shrink_to_hi().to(self.prev_token.span),
467 });
468 } else if !ate_comma {
469 break;
470 }
471 }
472
473 where_clause.span = where_lo.to(self.prev_token.span);
474 Ok((where_clause, tuple_struct_body))
475 }
476
477 fn parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
478 &mut self,
479 struct_: Option<(Ident, Span)>,
480 pred_lo: Span,
481 where_sp: Span,
482 ) -> PResult<'a, PredicateKindOrStructBody> {
483 let mut snapshot = None;
484
485 if let Some(struct_) = struct_
486 && self.may_recover()
487 && self.token == token::OpenParen
488 {
489 snapshot = Some((struct_, self.create_snapshot_for_diagnostic()));
490 };
491
492 match self.parse_ty_where_predicate_kind() {
493 Ok(pred) => Ok(PredicateKindOrStructBody::PredicateKind(pred)),
494 Err(type_err) => {
495 let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else {
496 return Err(type_err);
497 };
498
499 match snapshot.parse_tuple_struct_body() {
501 Ok(body)
507 if matches!(snapshot.token.kind, token::Semi | token::Eof)
508 || snapshot.token.can_begin_item() =>
509 {
510 type_err.cancel();
511
512 let body_sp = pred_lo.to(snapshot.prev_token.span);
513 let map = self.psess.source_map();
514
515 self.dcx().emit_err(WhereClauseBeforeTupleStructBody {
516 span: where_sp,
517 name: struct_name.span,
518 body: body_sp,
519 sugg: map.span_to_snippet(body_sp).ok().map(|body| {
520 WhereClauseBeforeTupleStructBodySugg {
521 left: body_insertion_point.shrink_to_hi(),
522 snippet: body,
523 right: map.end_point(where_sp).to(body_sp),
524 }
525 }),
526 });
527
528 self.restore_snapshot(snapshot);
529 Ok(PredicateKindOrStructBody::StructBody(body))
530 }
531 Ok(_) => Err(type_err),
532 Err(body_err) => {
533 body_err.cancel();
534 Err(type_err)
535 }
536 }
537 }
538 }
539 }
540
541 fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKind> {
542 let (bound_vars, _) = self.parse_higher_ranked_binder()?;
550
551 let ty = self.parse_ty_for_where_clause()?;
554 if self.eat(exp!(Colon)) {
555 let bounds = self.parse_generic_bounds()?;
556 Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
557 bound_generic_params: bound_vars,
558 bounded_ty: ty,
559 bounds,
560 }))
561 } else if self.eat(exp!(Eq)) || self.eat(exp!(EqEq)) {
564 let rhs_ty = self.parse_ty()?;
565 Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty }))
566 } else {
567 self.maybe_recover_bounds_doubled_colon(&ty)?;
568 self.unexpected_any()
569 }
570 }
571
572 pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool {
573 self.look_ahead(start, |t| t == &token::Lt)
592 && (self.look_ahead(start + 1, |t| t == &token::Pound || t == &token::Gt)
593 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
594 && self.look_ahead(start + 2, |t| {
595 matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
596 || t.kind == token::Question
599 })
600 || self.is_keyword_ahead(start + 1, &[kw::Const]))
601 }
602}