ast and parser
This commit is contained in:
parent
e0ef0fc392
commit
823dbb38e4
5 changed files with 94 additions and 28 deletions
|
@ -1845,6 +1845,7 @@ impl UintTy {
|
||||||
pub struct AssocTyConstraint {
|
pub struct AssocTyConstraint {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
|
pub gen_args: Option<GenericArgs>,
|
||||||
pub kind: AssocTyConstraintKind,
|
pub kind: AssocTyConstraintKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
|
@ -441,11 +441,14 @@ pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_ty_constraint<T: MutVisitor>(
|
pub fn noop_visit_ty_constraint<T: MutVisitor>(
|
||||||
AssocTyConstraint { id, ident, kind, span }: &mut AssocTyConstraint,
|
AssocTyConstraint { id, ident, gen_args, kind, span }: &mut AssocTyConstraint,
|
||||||
vis: &mut T,
|
vis: &mut T,
|
||||||
) {
|
) {
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
vis.visit_ident(ident);
|
vis.visit_ident(ident);
|
||||||
|
if let Some(ref mut gen_args) = gen_args {
|
||||||
|
vis.visit_generic_args(gen_args);
|
||||||
|
}
|
||||||
match kind {
|
match kind {
|
||||||
AssocTyConstraintKind::Equality { ref mut ty } => {
|
AssocTyConstraintKind::Equality { ref mut ty } => {
|
||||||
vis.visit_ty(ty);
|
vis.visit_ty(ty);
|
||||||
|
|
|
@ -485,6 +485,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(
|
||||||
constraint: &'a AssocTyConstraint,
|
constraint: &'a AssocTyConstraint,
|
||||||
) {
|
) {
|
||||||
visitor.visit_ident(constraint.ident);
|
visitor.visit_ident(constraint.ident);
|
||||||
|
if let Some(ref gen_args) = constraint.gen_args {
|
||||||
|
visitor.visit_generic_args(gen_args.span(), gen_args);
|
||||||
|
}
|
||||||
match constraint.kind {
|
match constraint.kind {
|
||||||
AssocTyConstraintKind::Equality { ref ty } => {
|
AssocTyConstraintKind::Equality { ref ty } => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
|
|
|
@ -1372,16 +1372,18 @@ fn deny_equality_constraints(
|
||||||
if param.ident == *ident {
|
if param.ident == *ident {
|
||||||
let param = ident;
|
let param = ident;
|
||||||
match &full_path.segments[qself.position..] {
|
match &full_path.segments[qself.position..] {
|
||||||
[PathSegment { ident, .. }] => {
|
[PathSegment { ident, args, .. }] => {
|
||||||
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
||||||
let mut assoc_path = full_path.clone();
|
let mut assoc_path = full_path.clone();
|
||||||
// Remove `Bar` from `Foo::Bar`.
|
// Remove `Bar` from `Foo::Bar`.
|
||||||
assoc_path.segments.pop();
|
assoc_path.segments.pop();
|
||||||
let len = assoc_path.segments.len() - 1;
|
let len = assoc_path.segments.len() - 1;
|
||||||
|
let gen_args = args.as_ref().map(|p| (**p).clone());
|
||||||
// Build `<Bar = RhsTy>`.
|
// Build `<Bar = RhsTy>`.
|
||||||
let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
|
let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
|
||||||
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
||||||
ident: *ident,
|
ident: *ident,
|
||||||
|
gen_args,
|
||||||
kind: AssocTyConstraintKind::Equality {
|
kind: AssocTyConstraintKind::Equality {
|
||||||
ty: predicate.rhs_ty.clone(),
|
ty: predicate.rhs_ty.clone(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,10 +3,9 @@ use super::{Parser, TokenType};
|
||||||
use crate::maybe_whole;
|
use crate::maybe_whole;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Token};
|
use rustc_ast::token::{self, Token};
|
||||||
use rustc_ast::{
|
use rustc_ast::{self as ast, AngleBracketedArg, AngleBracketedArgs, ParenthesizedArgs};
|
||||||
self as ast, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs,
|
|
||||||
};
|
|
||||||
use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
|
use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
|
||||||
|
use rustc_ast::{GenericArg, GenericArgs};
|
||||||
use rustc_ast::{Path, PathSegment, QSelf};
|
use rustc_ast::{Path, PathSegment, QSelf};
|
||||||
use rustc_errors::{pluralize, Applicability, PResult};
|
use rustc_errors::{pluralize, Applicability, PResult};
|
||||||
use rustc_span::source_map::{BytePos, Span};
|
use rustc_span::source_map::{BytePos, Span};
|
||||||
|
@ -414,32 +413,40 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses a single argument in the angle arguments `<...>` of a path segment.
|
/// Parses a single argument in the angle arguments `<...>` of a path segment.
|
||||||
fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
|
fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
|
||||||
if self.check_ident() && self.look_ahead(1, |t| matches!(t.kind, token::Eq | token::Colon))
|
let lo = self.token.span;
|
||||||
{
|
let arg = self.parse_generic_arg()?;
|
||||||
// Parse associated type constraint.
|
match arg {
|
||||||
let lo = self.token.span;
|
Some(arg) => {
|
||||||
let ident = self.parse_ident()?;
|
if self.check(&token::Colon) | self.check(&token::Eq) {
|
||||||
let kind = if self.eat(&token::Eq) {
|
let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?;
|
||||||
let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
|
let kind = if self.eat(&token::Colon) {
|
||||||
AssocTyConstraintKind::Equality { ty }
|
// Parse associated type constraint bound.
|
||||||
} else if self.eat(&token::Colon) {
|
|
||||||
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
|
|
||||||
AssocTyConstraintKind::Bound { bounds }
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
|
|
||||||
let span = lo.to(self.prev_token.span);
|
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
|
||||||
|
AssocTyConstraintKind::Bound { bounds }
|
||||||
|
} else if self.eat(&token::Eq) {
|
||||||
|
// Parse associated type equality constraint
|
||||||
|
|
||||||
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
|
let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
|
||||||
if let AssocTyConstraintKind::Bound { .. } = kind {
|
AssocTyConstraintKind::Equality { ty }
|
||||||
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
let span = lo.to(self.prev_token.span);
|
||||||
|
|
||||||
|
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
|
||||||
|
if let AssocTyConstraintKind::Bound { .. } = kind {
|
||||||
|
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
|
||||||
|
}
|
||||||
|
let constraint =
|
||||||
|
AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
|
||||||
|
Ok(Some(AngleBracketedArg::Constraint(constraint)))
|
||||||
|
} else {
|
||||||
|
Ok(Some(AngleBracketedArg::Arg(arg)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_ => Ok(None),
|
||||||
let constraint = AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, kind, span };
|
|
||||||
Ok(Some(AngleBracketedArg::Constraint(constraint)))
|
|
||||||
} else {
|
|
||||||
Ok(self.parse_generic_arg()?.map(AngleBracketedArg::Arg))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,4 +541,54 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
Ok(Some(arg))
|
Ok(Some(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_ident_from_generic_arg(
|
||||||
|
&self,
|
||||||
|
gen_arg: GenericArg,
|
||||||
|
lo: Span,
|
||||||
|
) -> PResult<'a, (Ident, Option<GenericArgs>)> {
|
||||||
|
let gen_arg_span = gen_arg.span();
|
||||||
|
match gen_arg {
|
||||||
|
GenericArg::Type(t) => match t.into_inner().kind {
|
||||||
|
ast::TyKind::Path(qself, mut path) => {
|
||||||
|
if let Some(qself) = qself {
|
||||||
|
let mut err = self.struct_span_err(
|
||||||
|
gen_arg_span,
|
||||||
|
"qualified paths cannot be used in associated type constraints",
|
||||||
|
);
|
||||||
|
err.span_label(
|
||||||
|
qself.path_span,
|
||||||
|
"not allowed in associated type constraints",
|
||||||
|
);
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
if path.segments.len() == 1 {
|
||||||
|
let path_seg = path.segments.remove(0);
|
||||||
|
let ident = path_seg.ident;
|
||||||
|
let gen_args = path_seg.args.map(|args| args.into_inner());
|
||||||
|
return Ok((ident, gen_args));
|
||||||
|
}
|
||||||
|
let err = self.struct_span_err(
|
||||||
|
path.span,
|
||||||
|
"paths with multiple segments cannot be used in associated type constraints",
|
||||||
|
);
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let span = lo.to(self.prev_token.span);
|
||||||
|
let err = self.struct_span_err(
|
||||||
|
span,
|
||||||
|
"only path types can be used in associated type constraints",
|
||||||
|
);
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
let span = lo.to(self.prev_token.span);
|
||||||
|
let err = self
|
||||||
|
.struct_span_err(span, "only types can be used in associated type constraints");
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue