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
118 Ok(GenericParam {
119 ident,
120 id: ast::DUMMY_NODE_ID,
121 attrs: preceding_attrs,
122 bounds: Vec::new(),
123 kind: GenericParamKind::Const { ty, kw_span: const_span, default },
124 is_placeholder: false,
125 colon_span: None,
126 })
127 }
128
129 pub(crate) fn recover_const_param_with_mistyped_const(
130 &mut self,
131 preceding_attrs: AttrVec,
132 mistyped_const_ident: Ident,
133 ) -> PResult<'a, GenericParam> {
134 let ident = self.parse_ident()?;
135 self.expect(exp!(Colon))?;
136 let ty = self.parse_ty()?;
137
138 let default = if self.eat(exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
140
141 self.dcx()
142 .struct_span_err(
143 mistyped_const_ident.span,
144 format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
145 )
146 .with_span_suggestion_verbose(
147 mistyped_const_ident.span,
148 "use the `const` keyword",
149 kw::Const,
150 Applicability::MachineApplicable,
151 )
152 .emit();
153
154 Ok(GenericParam {
155 ident,
156 id: ast::DUMMY_NODE_ID,
157 attrs: preceding_attrs,
158 bounds: Vec::new(),
159 kind: GenericParamKind::Const { ty, kw_span: mistyped_const_ident.span, default },
160 is_placeholder: false,
161 colon_span: None,
162 })
163 }
164
165 pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
168 let mut params = ThinVec::new();
169 let mut done = false;
170 while !done {
171 let attrs = self.parse_outer_attributes()?;
172 let param = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
173 if this.eat_keyword_noexpect(kw::SelfUpper) {
174 this.dcx()
177 .emit_err(UnexpectedSelfInGenericParameters { span: this.prev_token.span });
178
179 let _ = this.eat(exp!(Comma));
181 }
182
183 let param = if this.check_lifetime() {
184 let lifetime = this.expect_lifetime();
185 let (colon_span, bounds) = if this.eat(exp!(Colon)) {
187 (Some(this.prev_token.span), this.parse_lt_param_bounds())
188 } else {
189 (None, Vec::new())
190 };
191
192 if this.check_noexpect(&token::Eq) && this.look_ahead(1, |t| t.is_lifetime()) {
193 let lo = this.token.span;
194 this.bump(); this.bump(); let span = lo.to(this.prev_token.span);
198 this.dcx().emit_err(UnexpectedDefaultValueForLifetimeInGenericParameters {
199 span,
200 });
201 }
202
203 Some(ast::GenericParam {
204 ident: lifetime.ident,
205 id: lifetime.id,
206 attrs,
207 bounds,
208 kind: ast::GenericParamKind::Lifetime,
209 is_placeholder: false,
210 colon_span,
211 })
212 } else if this.check_keyword(exp!(Const)) {
213 Some(this.parse_const_param(attrs)?)
215 } else if this.check_ident() {
216 Some(this.parse_ty_param(attrs)?)
218 } else if this.token.can_begin_type() {
219 let snapshot = this.create_snapshot_for_diagnostic();
221 let lo = this.token.span;
222 match this.parse_ty_where_predicate_kind() {
223 Ok(_) => {
224 this.dcx().emit_err(errors::BadAssocTypeBounds {
225 span: lo.to(this.prev_token.span),
226 });
227 }
229 Err(err) => {
230 err.cancel();
231 this.restore_snapshot(snapshot);
233 }
234 }
235 return Ok((None, Trailing::No, UsePreAttrPos::No));
236 } else {
237 if !attrs.is_empty() {
239 if !params.is_empty() {
240 this.dcx().emit_err(errors::AttrAfterGeneric { span: attrs[0].span });
241 } else {
242 this.dcx()
243 .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span });
244 }
245 }
246 return Ok((None, Trailing::No, UsePreAttrPos::No));
247 };
248
249 if !this.eat(exp!(Comma)) {
250 done = true;
251 }
252 Ok((param, Trailing::No, UsePreAttrPos::No))
254 })?;
255
256 if let Some(param) = param {
257 params.push(param);
258 } else {
259 break;
260 }
261 }
262 Ok(params)
263 }
264
265 pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
273 if self.eat_noexpect(&token::PathSep) {
276 self.dcx()
277 .emit_err(errors::InvalidPathSepInFnDefinition { span: self.prev_token.span });
278 }
279
280 let span_lo = self.token.span;
281 let (params, span) = if self.eat_lt() {
282 let params = self.parse_generic_params()?;
283 self.expect_gt_or_maybe_suggest_closing_generics(¶ms)?;
284 (params, span_lo.to(self.prev_token.span))
285 } else {
286 (ThinVec::new(), self.prev_token.span.shrink_to_hi())
287 };
288 Ok(ast::Generics {
289 params,
290 where_clause: WhereClause {
291 has_where_token: false,
292 predicates: ThinVec::new(),
293 span: self.prev_token.span.shrink_to_hi(),
294 },
295 span,
296 })
297 }
298
299 pub(super) fn parse_contract(
302 &mut self,
303 ) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> {
304 let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
305 self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
306 let precond = self.parse_expr()?;
307 Some(precond)
308 } else {
309 None
310 };
311 let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
312 self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
313 let postcond = self.parse_expr()?;
314 Some(postcond)
315 } else {
316 None
317 };
318 if requires.is_none() && ensures.is_none() {
319 Ok(None)
320 } else {
321 Ok(Some(rustc_ast::ptr::P(ast::FnContract { requires, ensures })))
322 }
323 }
324
325 pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
331 self.parse_where_clause_common(None).map(|(clause, _)| clause)
332 }
333
334 pub(super) fn parse_struct_where_clause(
335 &mut self,
336 struct_name: Ident,
337 body_insertion_point: Span,
338 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
339 self.parse_where_clause_common(Some((struct_name, body_insertion_point)))
340 }
341
342 fn parse_where_clause_common(
343 &mut self,
344 struct_: Option<(Ident, Span)>,
345 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
346 let mut where_clause = WhereClause {
347 has_where_token: false,
348 predicates: ThinVec::new(),
349 span: self.prev_token.span.shrink_to_hi(),
350 };
351 let mut tuple_struct_body = None;
352
353 if !self.eat_keyword(exp!(Where)) {
354 return Ok((where_clause, None));
355 }
356 where_clause.has_where_token = true;
357 let where_lo = self.prev_token.span;
358
359 if self.choose_generics_over_qpath(0) {
363 let generics = self.parse_generics()?;
364 self.dcx().emit_err(errors::WhereOnGenerics { span: generics.span });
365 }
366
367 loop {
368 let where_sp = where_lo.to(self.prev_token.span);
369 let attrs = self.parse_outer_attributes()?;
370 let pred_lo = self.token.span;
371 let predicate = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
372 for attr in &attrs {
373 self.psess.gated_spans.gate(sym::where_clause_attrs, attr.span);
374 }
375 let kind = if this.check_lifetime() && this.look_ahead(1, |t| !t.is_like_plus()) {
376 let lifetime = this.expect_lifetime();
377 this.expect(exp!(Colon))?;
379 let bounds = this.parse_lt_param_bounds();
380 Some(ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
381 lifetime,
382 bounds,
383 }))
384 } else if this.check_type() {
385 match this.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
386 struct_, pred_lo, where_sp,
387 )? {
388 PredicateKindOrStructBody::PredicateKind(kind) => Some(kind),
389 PredicateKindOrStructBody::StructBody(body) => {
390 tuple_struct_body = Some(body);
391 None
392 }
393 }
394 } else {
395 None
396 };
397 let predicate = kind.map(|kind| ast::WherePredicate {
398 attrs,
399 kind,
400 id: DUMMY_NODE_ID,
401 span: pred_lo.to(this.prev_token.span),
402 is_placeholder: false,
403 });
404 Ok((predicate, Trailing::No, UsePreAttrPos::No))
405 })?;
406 match predicate {
407 Some(predicate) => where_clause.predicates.push(predicate),
408 None => break,
409 }
410
411 let prev_token = self.prev_token.span;
412 let ate_comma = self.eat(exp!(Comma));
413
414 if self.eat_keyword_noexpect(kw::Where) {
415 self.dcx().emit_err(MultipleWhereClauses {
416 span: self.token.span,
417 previous: pred_lo,
418 between: prev_token.shrink_to_hi().to(self.prev_token.span),
419 });
420 } else if !ate_comma {
421 break;
422 }
423 }
424
425 where_clause.span = where_lo.to(self.prev_token.span);
426 Ok((where_clause, tuple_struct_body))
427 }
428
429 fn parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
430 &mut self,
431 struct_: Option<(Ident, Span)>,
432 pred_lo: Span,
433 where_sp: Span,
434 ) -> PResult<'a, PredicateKindOrStructBody> {
435 let mut snapshot = None;
436
437 if let Some(struct_) = struct_
438 && self.may_recover()
439 && self.token == token::OpenParen
440 {
441 snapshot = Some((struct_, self.create_snapshot_for_diagnostic()));
442 };
443
444 match self.parse_ty_where_predicate_kind() {
445 Ok(pred) => Ok(PredicateKindOrStructBody::PredicateKind(pred)),
446 Err(type_err) => {
447 let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else {
448 return Err(type_err);
449 };
450
451 match snapshot.parse_tuple_struct_body() {
453 Ok(body)
459 if matches!(snapshot.token.kind, token::Semi | token::Eof)
460 || snapshot.token.can_begin_item() =>
461 {
462 type_err.cancel();
463
464 let body_sp = pred_lo.to(snapshot.prev_token.span);
465 let map = self.psess.source_map();
466
467 self.dcx().emit_err(WhereClauseBeforeTupleStructBody {
468 span: where_sp,
469 name: struct_name.span,
470 body: body_sp,
471 sugg: map.span_to_snippet(body_sp).ok().map(|body| {
472 WhereClauseBeforeTupleStructBodySugg {
473 left: body_insertion_point.shrink_to_hi(),
474 snippet: body,
475 right: map.end_point(where_sp).to(body_sp),
476 }
477 }),
478 });
479
480 self.restore_snapshot(snapshot);
481 Ok(PredicateKindOrStructBody::StructBody(body))
482 }
483 Ok(_) => Err(type_err),
484 Err(body_err) => {
485 body_err.cancel();
486 Err(type_err)
487 }
488 }
489 }
490 }
491 }
492
493 fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKind> {
494 let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
502
503 let ty = self.parse_ty_for_where_clause()?;
506 if self.eat(exp!(Colon)) {
507 let bounds = self.parse_generic_bounds()?;
508 Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
509 bound_generic_params: lifetime_defs,
510 bounded_ty: ty,
511 bounds,
512 }))
513 } else if self.eat(exp!(Eq)) || self.eat(exp!(EqEq)) {
516 let rhs_ty = self.parse_ty()?;
517 Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty }))
518 } else {
519 self.maybe_recover_bounds_doubled_colon(&ty)?;
520 self.unexpected_any()
521 }
522 }
523
524 pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool {
525 self.look_ahead(start, |t| t == &token::Lt)
544 && (self.look_ahead(start + 1, |t| t == &token::Pound || t == &token::Gt)
545 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
546 && self.look_ahead(start + 2, |t| {
547 matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
548 || t.kind == token::Question
551 })
552 || self.is_keyword_ahead(start + 1, &[kw::Const]))
553 }
554}