mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
ast and parser
This commit is contained in:
parent
e0ef0fc392
commit
823dbb38e4
@ -1845,6 +1845,7 @@ impl UintTy {
|
||||
pub struct AssocTyConstraint {
|
||||
pub id: NodeId,
|
||||
pub ident: Ident,
|
||||
pub gen_args: Option<GenericArgs>,
|
||||
pub kind: AssocTyConstraintKind,
|
||||
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>(
|
||||
AssocTyConstraint { id, ident, kind, span }: &mut AssocTyConstraint,
|
||||
AssocTyConstraint { id, ident, gen_args, kind, span }: &mut AssocTyConstraint,
|
||||
vis: &mut T,
|
||||
) {
|
||||
vis.visit_id(id);
|
||||
vis.visit_ident(ident);
|
||||
if let Some(ref mut gen_args) = gen_args {
|
||||
vis.visit_generic_args(gen_args);
|
||||
}
|
||||
match kind {
|
||||
AssocTyConstraintKind::Equality { ref mut ty } => {
|
||||
vis.visit_ty(ty);
|
||||
|
@ -485,6 +485,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(
|
||||
constraint: &'a AssocTyConstraint,
|
||||
) {
|
||||
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 {
|
||||
AssocTyConstraintKind::Equality { ref ty } => {
|
||||
visitor.visit_ty(ty);
|
||||
|
@ -1372,16 +1372,18 @@ fn deny_equality_constraints(
|
||||
if param.ident == *ident {
|
||||
let param = ident;
|
||||
match &full_path.segments[qself.position..] {
|
||||
[PathSegment { ident, .. }] => {
|
||||
[PathSegment { ident, args, .. }] => {
|
||||
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
||||
let mut assoc_path = full_path.clone();
|
||||
// Remove `Bar` from `Foo::Bar`.
|
||||
assoc_path.segments.pop();
|
||||
let len = assoc_path.segments.len() - 1;
|
||||
let gen_args = args.as_ref().map(|p| (**p).clone());
|
||||
// Build `<Bar = RhsTy>`.
|
||||
let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
|
||||
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
||||
ident: *ident,
|
||||
gen_args,
|
||||
kind: AssocTyConstraintKind::Equality {
|
||||
ty: predicate.rhs_ty.clone(),
|
||||
},
|
||||
|
@ -3,10 +3,9 @@ use super::{Parser, TokenType};
|
||||
use crate::maybe_whole;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Token};
|
||||
use rustc_ast::{
|
||||
self as ast, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs,
|
||||
};
|
||||
use rustc_ast::{self as ast, AngleBracketedArg, AngleBracketedArgs, ParenthesizedArgs};
|
||||
use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
|
||||
use rustc_ast::{GenericArg, GenericArgs};
|
||||
use rustc_ast::{Path, PathSegment, QSelf};
|
||||
use rustc_errors::{pluralize, Applicability, PResult};
|
||||
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.
|
||||
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))
|
||||
{
|
||||
// Parse associated type constraint.
|
||||
let lo = self.token.span;
|
||||
let ident = self.parse_ident()?;
|
||||
let kind = if self.eat(&token::Eq) {
|
||||
let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
|
||||
AssocTyConstraintKind::Equality { ty }
|
||||
} else if self.eat(&token::Colon) {
|
||||
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
|
||||
AssocTyConstraintKind::Bound { bounds }
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
let lo = self.token.span;
|
||||
let arg = self.parse_generic_arg()?;
|
||||
match arg {
|
||||
Some(arg) => {
|
||||
if self.check(&token::Colon) | self.check(&token::Eq) {
|
||||
let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?;
|
||||
let kind = if self.eat(&token::Colon) {
|
||||
// Parse associated type constraint bound.
|
||||
|
||||
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>`.
|
||||
if let AssocTyConstraintKind::Bound { .. } = kind {
|
||||
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
|
||||
let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
|
||||
AssocTyConstraintKind::Equality { ty }
|
||||
} 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)))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -534,4 +541,54 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
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…
Reference in New Issue
Block a user