Skip to content

Commit 385d07f

Browse files
committed
parser: move into generics.rs
1 parent d6d93b3 commit 385d07f

File tree

3 files changed

+278
-272
lines changed

3 files changed

+278
-272
lines changed

src/libsyntax/parse/parser.rs

+2-270
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ mod ty;
88
mod path;
99
pub use path::PathStyle;
1010
mod stmt;
11+
mod generics;
1112

1213
use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind};
13-
use crate::ast::{FnDecl, Ident, IsAsync, Lifetime, MacDelimiter, Mutability};
14-
use crate::ast::{GenericParam, GenericParamKind, WhereClause, TyKind, GenericBounds};
14+
use crate::ast::{FnDecl, Ident, IsAsync, Lifetime, MacDelimiter, Mutability, TyKind};
1515
use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar};
1616
use crate::ext::hygiene::SyntaxContext;
1717
use crate::source_map::{self, respan};
@@ -1205,249 +1205,6 @@ impl<'a> Parser<'a> {
12051205

12061206
}
12071207

1208-
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
1209-
///
1210-
/// ```
1211-
/// BOUND = LT_BOUND (e.g., `'a`)
1212-
/// ```
1213-
fn parse_lt_param_bounds(&mut self) -> GenericBounds {
1214-
let mut lifetimes = Vec::new();
1215-
while self.check_lifetime() {
1216-
lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
1217-
1218-
if !self.eat_plus() {
1219-
break
1220-
}
1221-
}
1222-
lifetimes
1223-
}
1224-
1225-
/// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
1226-
fn parse_ty_param(&mut self,
1227-
preceding_attrs: Vec<Attribute>)
1228-
-> PResult<'a, GenericParam> {
1229-
let ident = self.parse_ident()?;
1230-
1231-
// Parse optional colon and param bounds.
1232-
let bounds = if self.eat(&token::Colon) {
1233-
self.parse_generic_bounds(Some(self.prev_span))?
1234-
} else {
1235-
Vec::new()
1236-
};
1237-
1238-
let default = if self.eat(&token::Eq) {
1239-
Some(self.parse_ty()?)
1240-
} else {
1241-
None
1242-
};
1243-
1244-
Ok(GenericParam {
1245-
ident,
1246-
id: ast::DUMMY_NODE_ID,
1247-
attrs: preceding_attrs.into(),
1248-
bounds,
1249-
kind: GenericParamKind::Type {
1250-
default,
1251-
}
1252-
})
1253-
}
1254-
1255-
fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
1256-
self.expect_keyword(kw::Const)?;
1257-
let ident = self.parse_ident()?;
1258-
self.expect(&token::Colon)?;
1259-
let ty = self.parse_ty()?;
1260-
1261-
Ok(GenericParam {
1262-
ident,
1263-
id: ast::DUMMY_NODE_ID,
1264-
attrs: preceding_attrs.into(),
1265-
bounds: Vec::new(),
1266-
kind: GenericParamKind::Const {
1267-
ty,
1268-
}
1269-
})
1270-
}
1271-
1272-
/// Parses a (possibly empty) list of lifetime and type parameters, possibly including
1273-
/// a trailing comma and erroneous trailing attributes.
1274-
crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
1275-
let mut params = Vec::new();
1276-
loop {
1277-
let attrs = self.parse_outer_attributes()?;
1278-
if self.check_lifetime() {
1279-
let lifetime = self.expect_lifetime();
1280-
// Parse lifetime parameter.
1281-
let bounds = if self.eat(&token::Colon) {
1282-
self.parse_lt_param_bounds()
1283-
} else {
1284-
Vec::new()
1285-
};
1286-
params.push(ast::GenericParam {
1287-
ident: lifetime.ident,
1288-
id: lifetime.id,
1289-
attrs: attrs.into(),
1290-
bounds,
1291-
kind: ast::GenericParamKind::Lifetime,
1292-
});
1293-
} else if self.check_keyword(kw::Const) {
1294-
// Parse const parameter.
1295-
params.push(self.parse_const_param(attrs)?);
1296-
} else if self.check_ident() {
1297-
// Parse type parameter.
1298-
params.push(self.parse_ty_param(attrs)?);
1299-
} else {
1300-
// Check for trailing attributes and stop parsing.
1301-
if !attrs.is_empty() {
1302-
if !params.is_empty() {
1303-
self.struct_span_err(
1304-
attrs[0].span,
1305-
&format!("trailing attribute after generic parameter"),
1306-
)
1307-
.span_label(attrs[0].span, "attributes must go before parameters")
1308-
.emit();
1309-
} else {
1310-
self.struct_span_err(
1311-
attrs[0].span,
1312-
&format!("attribute without generic parameters"),
1313-
)
1314-
.span_label(
1315-
attrs[0].span,
1316-
"attributes are only permitted when preceding parameters",
1317-
)
1318-
.emit();
1319-
}
1320-
}
1321-
break
1322-
}
1323-
1324-
if !self.eat(&token::Comma) {
1325-
break
1326-
}
1327-
}
1328-
Ok(params)
1329-
}
1330-
1331-
/// Parses a set of optional generic type parameter declarations. Where
1332-
/// clauses are not parsed here, and must be added later via
1333-
/// `parse_where_clause()`.
1334-
///
1335-
/// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
1336-
/// | ( < lifetimes , typaramseq ( , )? > )
1337-
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
1338-
fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
1339-
let span_lo = self.token.span;
1340-
let (params, span) = if self.eat_lt() {
1341-
let params = self.parse_generic_params()?;
1342-
self.expect_gt()?;
1343-
(params, span_lo.to(self.prev_span))
1344-
} else {
1345-
(vec![], self.prev_span.between(self.token.span))
1346-
};
1347-
Ok(ast::Generics {
1348-
params,
1349-
where_clause: WhereClause {
1350-
predicates: Vec::new(),
1351-
span: DUMMY_SP,
1352-
},
1353-
span,
1354-
})
1355-
}
1356-
1357-
/// Parses an optional where-clause and places it in `generics`.
1358-
///
1359-
/// ```ignore (only-for-syntax-highlight)
1360-
/// where T : Trait<U, V> + 'b, 'a : 'b
1361-
/// ```
1362-
fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
1363-
let mut where_clause = WhereClause {
1364-
predicates: Vec::new(),
1365-
span: self.prev_span.to(self.prev_span),
1366-
};
1367-
1368-
if !self.eat_keyword(kw::Where) {
1369-
return Ok(where_clause);
1370-
}
1371-
let lo = self.prev_span;
1372-
1373-
// We are considering adding generics to the `where` keyword as an alternative higher-rank
1374-
// parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
1375-
// change we parse those generics now, but report an error.
1376-
if self.choose_generics_over_qpath() {
1377-
let generics = self.parse_generics()?;
1378-
self.struct_span_err(
1379-
generics.span,
1380-
"generic parameters on `where` clauses are reserved for future use",
1381-
)
1382-
.span_label(generics.span, "currently unsupported")
1383-
.emit();
1384-
}
1385-
1386-
loop {
1387-
let lo = self.token.span;
1388-
if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
1389-
let lifetime = self.expect_lifetime();
1390-
// Bounds starting with a colon are mandatory, but possibly empty.
1391-
self.expect(&token::Colon)?;
1392-
let bounds = self.parse_lt_param_bounds();
1393-
where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
1394-
ast::WhereRegionPredicate {
1395-
span: lo.to(self.prev_span),
1396-
lifetime,
1397-
bounds,
1398-
}
1399-
));
1400-
} else if self.check_type() {
1401-
// Parse optional `for<'a, 'b>`.
1402-
// This `for` is parsed greedily and applies to the whole predicate,
1403-
// the bounded type can have its own `for` applying only to it.
1404-
// Examples:
1405-
// * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
1406-
// * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
1407-
// * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
1408-
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
1409-
1410-
// Parse type with mandatory colon and (possibly empty) bounds,
1411-
// or with mandatory equality sign and the second type.
1412-
let ty = self.parse_ty()?;
1413-
if self.eat(&token::Colon) {
1414-
let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
1415-
where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
1416-
ast::WhereBoundPredicate {
1417-
span: lo.to(self.prev_span),
1418-
bound_generic_params: lifetime_defs,
1419-
bounded_ty: ty,
1420-
bounds,
1421-
}
1422-
));
1423-
// FIXME: Decide what should be used here, `=` or `==`.
1424-
// FIXME: We are just dropping the binders in lifetime_defs on the floor here.
1425-
} else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
1426-
let rhs_ty = self.parse_ty()?;
1427-
where_clause.predicates.push(ast::WherePredicate::EqPredicate(
1428-
ast::WhereEqPredicate {
1429-
span: lo.to(self.prev_span),
1430-
lhs_ty: ty,
1431-
rhs_ty,
1432-
id: ast::DUMMY_NODE_ID,
1433-
}
1434-
));
1435-
} else {
1436-
return self.unexpected();
1437-
}
1438-
} else {
1439-
break
1440-
}
1441-
1442-
if !self.eat(&token::Comma) {
1443-
break
1444-
}
1445-
}
1446-
1447-
where_clause.span = lo.to(self.prev_span);
1448-
Ok(where_clause)
1449-
}
1450-
14511208
fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
14521209
-> PResult<'a, (Vec<Arg> , bool)> {
14531210
let sp = self.token.span;
@@ -1671,31 +1428,6 @@ impl<'a> Parser<'a> {
16711428
}))
16721429
}
16731430

1674-
fn choose_generics_over_qpath(&self) -> bool {
1675-
// There's an ambiguity between generic parameters and qualified paths in impls.
1676-
// If we see `<` it may start both, so we have to inspect some following tokens.
1677-
// The following combinations can only start generics,
1678-
// but not qualified paths (with one exception):
1679-
// `<` `>` - empty generic parameters
1680-
// `<` `#` - generic parameters with attributes
1681-
// `<` (LIFETIME|IDENT) `>` - single generic parameter
1682-
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
1683-
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
1684-
// `<` (LIFETIME|IDENT) `=` - generic parameter with a default
1685-
// `<` const - generic const parameter
1686-
// The only truly ambiguous case is
1687-
// `<` IDENT `>` `::` IDENT ...
1688-
// we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
1689-
// because this is what almost always expected in practice, qualified paths in impls
1690-
// (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
1691-
self.token == token::Lt &&
1692-
(self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
1693-
self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
1694-
self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
1695-
t == &token::Colon || t == &token::Eq) ||
1696-
self.is_keyword_ahead(1, &[kw::Const]))
1697-
}
1698-
16991431
fn is_crate_vis(&self) -> bool {
17001432
self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
17011433
}

0 commit comments

Comments
 (0)