diff options
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/generics.rs | 62 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 17 |
3 files changed, 60 insertions, 41 deletions
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 5aebe716b0a..76ecb77d750 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -1,6 +1,7 @@ use ast::token::Delimiter; use rustc_ast::{ - self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, token, + self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind, + WhereClause, token, }; use rustc_errors::{Applicability, PResult}; use rustc_span::Span; @@ -14,8 +15,8 @@ use crate::errors::{ WhereClauseBeforeTupleStructBodySugg, }; -enum PredicateOrStructBody { - Predicate(ast::WherePredicate), +enum PredicateKindOrStructBody { + PredicateKind(ast::WherePredicateKind), StructBody(ThinVec<ast::FieldDef>), } @@ -218,10 +219,11 @@ impl<'a> Parser<'a> { } else if this.token.can_begin_type() { // Trying to write an associated type bound? (#26271) let snapshot = this.create_snapshot_for_diagnostic(); - match this.parse_ty_where_predicate() { - Ok(where_predicate) => { + let lo = this.token.span; + match this.parse_ty_where_predicate_kind() { + Ok(_) => { this.dcx().emit_err(errors::BadAssocTypeBounds { - span: where_predicate.span(), + span: lo.to(this.prev_token.span), }); // FIXME - try to continue parsing other generics? } @@ -340,31 +342,33 @@ impl<'a> Parser<'a> { loop { let where_sp = where_lo.to(self.prev_token.span); let pred_lo = self.token.span; - if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { + let kind = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { let lifetime = self.expect_lifetime(); // Bounds starting with a colon are mandatory, but possibly empty. self.expect(&token::Colon)?; let bounds = self.parse_lt_param_bounds(); - where_clause.predicates.push(ast::WherePredicate::RegionPredicate( - ast::WhereRegionPredicate { - span: pred_lo.to(self.prev_token.span), - lifetime, - bounds, - }, - )); + ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate { + lifetime, + bounds, + }) } else if self.check_type() { - match self.parse_ty_where_predicate_or_recover_tuple_struct_body( + match self.parse_ty_where_predicate_kind_or_recover_tuple_struct_body( struct_, pred_lo, where_sp, )? { - PredicateOrStructBody::Predicate(pred) => where_clause.predicates.push(pred), - PredicateOrStructBody::StructBody(body) => { + PredicateKindOrStructBody::PredicateKind(kind) => kind, + PredicateKindOrStructBody::StructBody(body) => { tuple_struct_body = Some(body); break; } } } else { break; - } + }; + where_clause.predicates.push(ast::WherePredicate { + kind, + id: DUMMY_NODE_ID, + span: pred_lo.to(self.prev_token.span), + }); let prev_token = self.prev_token.span; let ate_comma = self.eat(&token::Comma); @@ -384,12 +388,12 @@ impl<'a> Parser<'a> { Ok((where_clause, tuple_struct_body)) } - fn parse_ty_where_predicate_or_recover_tuple_struct_body( + fn parse_ty_where_predicate_kind_or_recover_tuple_struct_body( &mut self, struct_: Option<(Ident, Span)>, pred_lo: Span, where_sp: Span, - ) -> PResult<'a, PredicateOrStructBody> { + ) -> PResult<'a, PredicateKindOrStructBody> { let mut snapshot = None; if let Some(struct_) = struct_ @@ -399,8 +403,8 @@ impl<'a> Parser<'a> { snapshot = Some((struct_, self.create_snapshot_for_diagnostic())); }; - match self.parse_ty_where_predicate() { - Ok(pred) => Ok(PredicateOrStructBody::Predicate(pred)), + match self.parse_ty_where_predicate_kind() { + Ok(pred) => Ok(PredicateKindOrStructBody::PredicateKind(pred)), Err(type_err) => { let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else { return Err(type_err); @@ -436,7 +440,7 @@ impl<'a> Parser<'a> { }); self.restore_snapshot(snapshot); - Ok(PredicateOrStructBody::StructBody(body)) + Ok(PredicateKindOrStructBody::StructBody(body)) } Ok(_) => Err(type_err), Err(body_err) => { @@ -448,8 +452,7 @@ impl<'a> Parser<'a> { } } - fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> { - let lo = self.token.span; + fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKind> { // Parse optional `for<'a, 'b>`. // This `for` is parsed greedily and applies to the whole predicate, // the bounded type can have its own `for` applying only to it. @@ -464,8 +467,7 @@ impl<'a> Parser<'a> { let ty = self.parse_ty_for_where_clause()?; if self.eat(&token::Colon) { let bounds = self.parse_generic_bounds()?; - Ok(ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - span: lo.to(self.prev_token.span), + Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { bound_generic_params: lifetime_defs, bounded_ty: ty, bounds, @@ -474,11 +476,7 @@ impl<'a> Parser<'a> { // FIXME: We are just dropping the binders in lifetime_defs on the floor here. } else if self.eat(&token::Eq) || self.eat(&token::EqEq) { let rhs_ty = self.parse_ty()?; - Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - span: lo.to(self.prev_token.span), - lhs_ty: ty, - rhs_ty, - })) + Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty })) } else { self.maybe_recover_bounds_doubled_colon(&ty)?; self.unexpected_any() diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index fddbf5896ad..26e81b7676b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1791,6 +1791,17 @@ impl<'a> Parser<'a> { Ok((fields, recovered)) } + fn parse_unsafe_field(&mut self) -> Safety { + // not using parse_safety as that also accepts `safe`. + if self.eat_keyword(kw::Unsafe) { + let span = self.prev_token.span; + self.psess.gated_spans.gate(sym::unsafe_fields, span); + Safety::Unsafe(span) + } else { + Safety::Default + } + } + pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> { // This is the case where we find `struct Foo<T>(T) where T: Copy;` // Unit like structs are handled in parse_item_struct function @@ -1814,6 +1825,8 @@ impl<'a> Parser<'a> { return Err(err); } }; + // Unsafe fields are not supported in tuple structs, as doing so would result in a + // parsing ambiguity for `struct X(unsafe fn())`. let ty = match p.parse_ty() { Ok(ty) => ty, Err(err) => { @@ -1828,6 +1841,7 @@ impl<'a> Parser<'a> { FieldDef { span: lo.to(ty.span), vis, + safety: Safety::Default, ident: None, id: DUMMY_NODE_ID, ty, @@ -1850,7 +1864,8 @@ impl<'a> Parser<'a> { self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; - this.parse_single_struct_field(adt_ty, lo, vis, attrs) + let safety = this.parse_unsafe_field(); + this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs) .map(|field| (field, Trailing::No, UsePreAttrPos::No)) }) } @@ -1861,10 +1876,11 @@ impl<'a> Parser<'a> { adt_ty: &str, lo: Span, vis: Visibility, + safety: Safety, attrs: AttrVec, ) -> PResult<'a, FieldDef> { let mut seen_comma: bool = false; - let a_var = self.parse_name_and_ty(adt_ty, lo, vis, attrs)?; + let a_var = self.parse_name_and_ty(adt_ty, lo, vis, safety, attrs)?; if self.token == token::Comma { seen_comma = true; } @@ -1992,6 +2008,7 @@ impl<'a> Parser<'a> { adt_ty: &str, lo: Span, vis: Visibility, + safety: Safety, attrs: AttrVec, ) -> PResult<'a, FieldDef> { let name = self.parse_field_ident(adt_ty, lo)?; @@ -2017,6 +2034,7 @@ impl<'a> Parser<'a> { span: lo.to(self.prev_token.span), ident: Some(name), vis, + safety, id: DUMMY_NODE_ID, ty, attrs, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index c4326427f67..004b5b34813 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,11 +1,12 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token}; +use rustc_ast::util::parser::AssocOp; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, ExprPrecedence, - LocalKind, MacCall, Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, - RangeSyntax, Stmt, StmtKind, + self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, + Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, + StmtKind, }; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey}; @@ -458,7 +459,7 @@ impl<'a> Parser<'a> { .create_err(UnexpectedExpressionInPattern { span, is_bound, - expr_precedence: expr.precedence().order(), + expr_precedence: expr.precedence(), }) .stash(span, StashKey::ExprInPat) .unwrap(), @@ -545,7 +546,8 @@ impl<'a> Parser<'a> { let expr = match &err.args["expr_precedence"] { DiagArgValue::Number(expr_precedence) => { if *expr_precedence - <= ExprPrecedence::Binary(BinOpKind::Eq).order() as i32 + <= AssocOp::from_ast_binop(BinOpKind::Eq).precedence() + as i32 { format!("({expr})") } else { @@ -568,8 +570,9 @@ impl<'a> Parser<'a> { } Some(guard) => { // Are parentheses required around the old guard? - let wrap_guard = guard.precedence().order() - <= ExprPrecedence::Binary(BinOpKind::And).order(); + let wrap_guard = guard.precedence() + <= AssocOp::from_ast_binop(BinOpKind::And).precedence() + as i8; err.subdiagnostic( UnexpectedExpressionInPatternSugg::UpdateGuard { |
