1use ast::token::Delimiter;
2use rustc_ast::{
3 self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind,
4 WhereClause, token,
5};
6use rustc_errors::{Applicability, PResult};
7use rustc_span::{Ident, Span, kw, sym};
8use thin_vec::ThinVec;
9
10use super::{ForceCollect, Parser, Trailing, UsePreAttrPos};
11use crate::errors::{
12 self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
13 UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
14 WhereClauseBeforeTupleStructBodySugg,
15};
16use crate::exp;
17
18enum PredicateKindOrStructBody {
19 PredicateKind(ast::WherePredicateKind),
20 StructBody(ThinVec<ast::FieldDef>),
21}
22
23impl<'a> Parser<'a> {
24 fn parse_lt_param_bounds(&mut self) -> GenericBounds {
30 let mut lifetimes = Vec::new();
31 while self.check_lifetime() {
32 lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
33
34 if !self.eat_plus() {
35 break;
36 }
37 }
38 lifetimes
39 }
40
41 fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> {
43 let ident = self.parse_ident()?;
44
45 if self.may_recover()
47 && ident.name.as_str().to_ascii_lowercase() == kw::Const.as_str()
48 && self.check_ident()
49 {
51 return self.recover_const_param_with_mistyped_const(preceding_attrs, ident);
52 }
53
54 let mut colon_span = None;
56 let bounds = if self.eat(exp!(Colon)) {
57 colon_span = Some(self.prev_token.span);
58 if self.token.is_keyword(kw::Impl) {
60 let impl_span = self.token.span;
61 let snapshot = self.create_snapshot_for_diagnostic();
62 match self.parse_ty() {
63 Ok(p) => {
64 if let TyKind::ImplTrait(_, bounds) = &p.kind {
65 let span = impl_span.to(self.token.span.shrink_to_lo());
66 let mut err = self.dcx().struct_span_err(
67 span,
68 "expected trait bound, found `impl Trait` type",
69 );
70 err.span_label(span, "not a trait");
71 if let [bound, ..] = &bounds[..] {
72 err.span_suggestion_verbose(
73 impl_span.until(bound.span()),
74 "use the trait bounds directly",
75 String::new(),
76 Applicability::MachineApplicable,
77 );
78 }
79 return Err(err);
80 }
81 }
82 Err(err) => {
83 err.cancel();
84 }
85 }
86 self.restore_snapshot(snapshot);
87 }
88 self.parse_generic_bounds()?
89 } else {
90 Vec::new()
91 };
92
93 let default = if self.eat(exp!(Eq)) { Some(self.parse_ty()?) } else { None };
94 Ok(GenericParam {
95 ident,
96 id: ast::DUMMY_NODE_ID,
97 attrs: preceding_attrs,
98 bounds,
99 kind: GenericParamKind::Type { default },
100 is_placeholder: false,
101 colon_span,
102 })
103 }
104
105 pub(crate) fn parse_const_param(
106 &mut self,
107 preceding_attrs: AttrVec,
108 ) -> PResult<'a, GenericParam> {
109 let const_span = self.token.span;
110
111 self.expect_keyword(exp!(Const))?;
112 let ident = self.parse_ident()?;
113 self.expect(exp!(Colon))?;
114 let ty = self.parse_ty()?;
115
116 let default = if self.eat(exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
118
119 Ok(GenericParam {
120 ident,
121 id: ast::DUMMY_NODE_ID,
122 attrs: preceding_attrs,
123 bounds: Vec::new(),
124 kind: GenericParamKind::Const { ty, kw_span: const_span, default },
125 is_placeholder: false,
126 colon_span: None,
127 })
128 }
129
130 pub(crate) fn recover_const_param_with_mistyped_const(
131 &mut self,
132 preceding_attrs: AttrVec,
133 mistyped_const_ident: Ident,
134 ) -> PResult<'a, GenericParam> {
135 let ident = self.parse_ident()?;
136 self.expect(exp!(Colon))?;
137 let ty = self.parse_ty()?;
138
139 let default = if self.eat(exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
141
142 self.dcx()
143 .struct_span_err(
144 mistyped_const_ident.span,
145 format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
146 )
147 .with_span_suggestion_verbose(
148 mistyped_const_ident.span,
149 "use the `const` keyword",
150 kw::Const,
151 Applicability::MachineApplicable,
152 )
153 .emit();
154
155 Ok(GenericParam {
156 ident,
157 id: ast::DUMMY_NODE_ID,
158 attrs: preceding_attrs,
159 bounds: Vec::new(),
160 kind: GenericParamKind::Const { ty, kw_span: mistyped_const_ident.span, default },
161 is_placeholder: false,
162 colon_span: None,
163 })
164 }
165
166 pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
169 let mut params = ThinVec::new();
170 let mut done = false;
171 while !done {
172 let attrs = self.parse_outer_attributes()?;
173 let param = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
174 if this.eat_keyword_noexpect(kw::SelfUpper) {
175 this.dcx()
178 .emit_err(UnexpectedSelfInGenericParameters { span: this.prev_token.span });
179
180 let _ = this.eat(exp!(Comma));
182 }
183
184 let param = if this.check_lifetime() {
185 let lifetime = this.expect_lifetime();
186 let (colon_span, bounds) = if this.eat(exp!(Colon)) {
188 (Some(this.prev_token.span), this.parse_lt_param_bounds())
189 } else {
190 (None, Vec::new())
191 };
192
193 if this.check_noexpect(&token::Eq) && this.look_ahead(1, |t| t.is_lifetime()) {
194 let lo = this.token.span;
195 this.bump(); this.bump(); let span = lo.to(this.prev_token.span);
199 this.dcx().emit_err(UnexpectedDefaultValueForLifetimeInGenericParameters {
200 span,
201 });
202 }
203
204 Some(ast::GenericParam {
205 ident: lifetime.ident,
206 id: lifetime.id,
207 attrs,
208 bounds,
209 kind: ast::GenericParamKind::Lifetime,
210 is_placeholder: false,
211 colon_span,
212 })
213 } else if this.check_keyword(exp!(Const)) {
214 Some(this.parse_const_param(attrs)?)
216 } else if this.check_ident() {
217 Some(this.parse_ty_param(attrs)?)
219 } else if this.token.can_begin_type() {
220 let snapshot = this.create_snapshot_for_diagnostic();
222 let lo = this.token.span;
223 match this.parse_ty_where_predicate_kind() {
224 Ok(_) => {
225 this.dcx().emit_err(errors::BadAssocTypeBounds {
226 span: lo.to(this.prev_token.span),
227 });
228 }
230 Err(err) => {
231 err.cancel();
232 this.restore_snapshot(snapshot);
234 }
235 }
236 return Ok((None, Trailing::No, UsePreAttrPos::No));
237 } else {
238 if !attrs.is_empty() {
240 if !params.is_empty() {
241 this.dcx().emit_err(errors::AttrAfterGeneric { span: attrs[0].span });
242 } else {
243 this.dcx()
244 .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span });
245 }
246 }
247 return Ok((None, Trailing::No, UsePreAttrPos::No));
248 };
249
250 if !this.eat(exp!(Comma)) {
251 done = true;
252 }
253 Ok((param, Trailing::No, UsePreAttrPos::No))
255 })?;
256
257 if let Some(param) = param {
258 params.push(param);
259 } else {
260 break;
261 }
262 }
263 Ok(params)
264 }
265
266 pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
274 if self.eat_noexpect(&token::PathSep) {
277 self.dcx()
278 .emit_err(errors::InvalidPathSepInFnDefinition { span: self.prev_token.span });
279 }
280
281 let span_lo = self.token.span;
282 let (params, span) = if self.eat_lt() {
283 let params = self.parse_generic_params()?;
284 self.expect_gt_or_maybe_suggest_closing_generics(¶ms)?;
285 (params, span_lo.to(self.prev_token.span))
286 } else {
287 (ThinVec::new(), self.prev_token.span.shrink_to_hi())
288 };
289 Ok(ast::Generics {
290 params,
291 where_clause: WhereClause {
292 has_where_token: false,
293 predicates: ThinVec::new(),
294 span: self.prev_token.span.shrink_to_hi(),
295 },
296 span,
297 })
298 }
299
300 pub(super) fn parse_contract(
303 &mut self,
304 ) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> {
305 let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
306 self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
307 let precond = self.parse_expr()?;
308 Some(precond)
309 } else {
310 None
311 };
312 let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
313 self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
314 let postcond = self.parse_expr()?;
315 Some(postcond)
316 } else {
317 None
318 };
319 if requires.is_none() && ensures.is_none() {
320 Ok(None)
321 } else {
322 Ok(Some(rustc_ast::ptr::P(ast::FnContract { requires, ensures })))
323 }
324 }
325
326 pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
332 self.parse_where_clause_common(None).map(|(clause, _)| clause)
333 }
334
335 pub(super) fn parse_struct_where_clause(
336 &mut self,
337 struct_name: Ident,
338 body_insertion_point: Span,
339 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
340 self.parse_where_clause_common(Some((struct_name, body_insertion_point)))
341 }
342
343 fn parse_where_clause_common(
344 &mut self,
345 struct_: Option<(Ident, Span)>,
346 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
347 let mut where_clause = WhereClause {
348 has_where_token: false,
349 predicates: ThinVec::new(),
350 span: self.prev_token.span.shrink_to_hi(),
351 };
352 let mut tuple_struct_body = None;
353
354 if !self.eat_keyword(exp!(Where)) {
355 return Ok((where_clause, None));
356 }
357 where_clause.has_where_token = true;
358 let where_lo = self.prev_token.span;
359
360 if self.choose_generics_over_qpath(0) {
364 let generics = self.parse_generics()?;
365 self.dcx().emit_err(errors::WhereOnGenerics { span: generics.span });
366 }
367
368 loop {
369 let where_sp = where_lo.to(self.prev_token.span);
370 let attrs = self.parse_outer_attributes()?;
371 let pred_lo = self.token.span;
372 let predicate = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
373 for attr in &attrs {
374 self.psess.gated_spans.gate(sym::where_clause_attrs, attr.span);
375 }
376 let kind = if this.check_lifetime() && this.look_ahead(1, |t| !t.is_like_plus()) {
377 let lifetime = this.expect_lifetime();
378 this.expect(exp!(Colon))?;
380 let bounds = this.parse_lt_param_bounds();
381 Some(ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
382 lifetime,
383 bounds,
384 }))
385 } else if this.check_type() {
386 match this.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
387 struct_, pred_lo, where_sp,
388 )? {
389 PredicateKindOrStructBody::PredicateKind(kind) => Some(kind),
390 PredicateKindOrStructBody::StructBody(body) => {
391 tuple_struct_body = Some(body);
392 None
393 }
394 }
395 } else {
396 None
397 };
398 let predicate = kind.map(|kind| ast::WherePredicate {
399 attrs,
400 kind,
401 id: DUMMY_NODE_ID,
402 span: pred_lo.to(this.prev_token.span),
403 is_placeholder: false,
404 });
405 Ok((predicate, Trailing::No, UsePreAttrPos::No))
406 })?;
407 match predicate {
408 Some(predicate) => where_clause.predicates.push(predicate),
409 None => break,
410 }
411
412 let prev_token = self.prev_token.span;
413 let ate_comma = self.eat(exp!(Comma));
414
415 if self.eat_keyword_noexpect(kw::Where) {
416 self.dcx().emit_err(MultipleWhereClauses {
417 span: self.token.span,
418 previous: pred_lo,
419 between: prev_token.shrink_to_hi().to(self.prev_token.span),
420 });
421 } else if !ate_comma {
422 break;
423 }
424 }
425
426 where_clause.span = where_lo.to(self.prev_token.span);
427 Ok((where_clause, tuple_struct_body))
428 }
429
430 fn parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
431 &mut self,
432 struct_: Option<(Ident, Span)>,
433 pred_lo: Span,
434 where_sp: Span,
435 ) -> PResult<'a, PredicateKindOrStructBody> {
436 let mut snapshot = None;
437
438 if let Some(struct_) = struct_
439 && self.may_recover()
440 && self.token == token::OpenDelim(Delimiter::Parenthesis)
441 {
442 snapshot = Some((struct_, self.create_snapshot_for_diagnostic()));
443 };
444
445 match self.parse_ty_where_predicate_kind() {
446 Ok(pred) => Ok(PredicateKindOrStructBody::PredicateKind(pred)),
447 Err(type_err) => {
448 let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else {
449 return Err(type_err);
450 };
451
452 match snapshot.parse_tuple_struct_body() {
454 Ok(body)
460 if matches!(snapshot.token.kind, token::Semi | token::Eof)
461 || snapshot.token.can_begin_item() =>
462 {
463 type_err.cancel();
464
465 let body_sp = pred_lo.to(snapshot.prev_token.span);
466 let map = self.psess.source_map();
467
468 self.dcx().emit_err(WhereClauseBeforeTupleStructBody {
469 span: where_sp,
470 name: struct_name.span,
471 body: body_sp,
472 sugg: map.span_to_snippet(body_sp).ok().map(|body| {
473 WhereClauseBeforeTupleStructBodySugg {
474 left: body_insertion_point.shrink_to_hi(),
475 snippet: body,
476 right: map.end_point(where_sp).to(body_sp),
477 }
478 }),
479 });
480
481 self.restore_snapshot(snapshot);
482 Ok(PredicateKindOrStructBody::StructBody(body))
483 }
484 Ok(_) => Err(type_err),
485 Err(body_err) => {
486 body_err.cancel();
487 Err(type_err)
488 }
489 }
490 }
491 }
492 }
493
494 fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKind> {
495 let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
503
504 let ty = self.parse_ty_for_where_clause()?;
507 if self.eat(exp!(Colon)) {
508 let bounds = self.parse_generic_bounds()?;
509 Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
510 bound_generic_params: lifetime_defs,
511 bounded_ty: ty,
512 bounds,
513 }))
514 } else if self.eat(exp!(Eq)) || self.eat(exp!(EqEq)) {
517 let rhs_ty = self.parse_ty()?;
518 Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty }))
519 } else {
520 self.maybe_recover_bounds_doubled_colon(&ty)?;
521 self.unexpected_any()
522 }
523 }
524
525 pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool {
526 self.look_ahead(start, |t| t == &token::Lt)
545 && (self.look_ahead(start + 1, |t| t == &token::Pound || t == &token::Gt)
546 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
547 && self.look_ahead(start + 2, |t| {
548 matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
549 || matches!(t.kind, token::Question)
552 })
553 || self.is_keyword_ahead(start + 1, &[kw::Const]))
554 }
555}