Skip to content

Commit 823dbb3

Browse files
b-naberb-naber
b-naber
authored and
b-naber
committed
ast and parser
1 parent e0ef0fc commit 823dbb3

File tree

5 files changed

+94
-28
lines changed

5 files changed

+94
-28
lines changed

compiler/rustc_ast/src/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1845,6 +1845,7 @@ impl UintTy {
18451845
pub struct AssocTyConstraint {
18461846
pub id: NodeId,
18471847
pub ident: Ident,
1848+
pub gen_args: Option<GenericArgs>,
18481849
pub kind: AssocTyConstraintKind,
18491850
pub span: Span,
18501851
}

compiler/rustc_ast/src/mut_visit.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -441,11 +441,14 @@ pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[
441441
}
442442

443443
pub fn noop_visit_ty_constraint<T: MutVisitor>(
444-
AssocTyConstraint { id, ident, kind, span }: &mut AssocTyConstraint,
444+
AssocTyConstraint { id, ident, gen_args, kind, span }: &mut AssocTyConstraint,
445445
vis: &mut T,
446446
) {
447447
vis.visit_id(id);
448448
vis.visit_ident(ident);
449+
if let Some(ref mut gen_args) = gen_args {
450+
vis.visit_generic_args(gen_args);
451+
}
449452
match kind {
450453
AssocTyConstraintKind::Equality { ref mut ty } => {
451454
vis.visit_ty(ty);

compiler/rustc_ast/src/visit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(
485485
constraint: &'a AssocTyConstraint,
486486
) {
487487
visitor.visit_ident(constraint.ident);
488+
if let Some(ref gen_args) = constraint.gen_args {
489+
visitor.visit_generic_args(gen_args.span(), gen_args);
490+
}
488491
match constraint.kind {
489492
AssocTyConstraintKind::Equality { ref ty } => {
490493
visitor.visit_ty(ty);

compiler/rustc_ast_passes/src/ast_validation.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1372,16 +1372,18 @@ fn deny_equality_constraints(
13721372
if param.ident == *ident {
13731373
let param = ident;
13741374
match &full_path.segments[qself.position..] {
1375-
[PathSegment { ident, .. }] => {
1375+
[PathSegment { ident, args, .. }] => {
13761376
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
13771377
let mut assoc_path = full_path.clone();
13781378
// Remove `Bar` from `Foo::Bar`.
13791379
assoc_path.segments.pop();
13801380
let len = assoc_path.segments.len() - 1;
1381+
let gen_args = args.as_ref().map(|p| (**p).clone());
13811382
// Build `<Bar = RhsTy>`.
13821383
let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
13831384
id: rustc_ast::node_id::DUMMY_NODE_ID,
13841385
ident: *ident,
1386+
gen_args,
13851387
kind: AssocTyConstraintKind::Equality {
13861388
ty: predicate.rhs_ty.clone(),
13871389
},

compiler/rustc_parse/src/parser/path.rs

+83-26
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ use super::{Parser, TokenType};
33
use crate::maybe_whole;
44
use rustc_ast::ptr::P;
55
use rustc_ast::token::{self, Token};
6-
use rustc_ast::{
7-
self as ast, AngleBracketedArg, AngleBracketedArgs, GenericArg, ParenthesizedArgs,
8-
};
6+
use rustc_ast::{self as ast, AngleBracketedArg, AngleBracketedArgs, ParenthesizedArgs};
97
use rustc_ast::{AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode};
8+
use rustc_ast::{GenericArg, GenericArgs};
109
use rustc_ast::{Path, PathSegment, QSelf};
1110
use rustc_errors::{pluralize, Applicability, PResult};
1211
use rustc_span::source_map::{BytePos, Span};
@@ -414,32 +413,40 @@ impl<'a> Parser<'a> {
414413

415414
/// Parses a single argument in the angle arguments `<...>` of a path segment.
416415
fn parse_angle_arg(&mut self) -> PResult<'a, Option<AngleBracketedArg>> {
417-
if self.check_ident() && self.look_ahead(1, |t| matches!(t.kind, token::Eq | token::Colon))
418-
{
419-
// Parse associated type constraint.
420-
let lo = self.token.span;
421-
let ident = self.parse_ident()?;
422-
let kind = if self.eat(&token::Eq) {
423-
let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
424-
AssocTyConstraintKind::Equality { ty }
425-
} else if self.eat(&token::Colon) {
426-
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
427-
AssocTyConstraintKind::Bound { bounds }
428-
} else {
429-
unreachable!();
430-
};
416+
let lo = self.token.span;
417+
let arg = self.parse_generic_arg()?;
418+
match arg {
419+
Some(arg) => {
420+
if self.check(&token::Colon) | self.check(&token::Eq) {
421+
let (ident, gen_args) = self.get_ident_from_generic_arg(arg, lo)?;
422+
let kind = if self.eat(&token::Colon) {
423+
// Parse associated type constraint bound.
424+
425+
let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
426+
AssocTyConstraintKind::Bound { bounds }
427+
} else if self.eat(&token::Eq) {
428+
// Parse associated type equality constraint
429+
430+
let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?;
431+
AssocTyConstraintKind::Equality { ty }
432+
} else {
433+
unreachable!();
434+
};
431435

432-
let span = lo.to(self.prev_token.span);
436+
let span = lo.to(self.prev_token.span);
433437

434-
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
435-
if let AssocTyConstraintKind::Bound { .. } = kind {
436-
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
438+
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
439+
if let AssocTyConstraintKind::Bound { .. } = kind {
440+
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
441+
}
442+
let constraint =
443+
AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
444+
Ok(Some(AngleBracketedArg::Constraint(constraint)))
445+
} else {
446+
Ok(Some(AngleBracketedArg::Arg(arg)))
447+
}
437448
}
438-
439-
let constraint = AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, kind, span };
440-
Ok(Some(AngleBracketedArg::Constraint(constraint)))
441-
} else {
442-
Ok(self.parse_generic_arg()?.map(AngleBracketedArg::Arg))
449+
_ => Ok(None),
443450
}
444451
}
445452

@@ -534,4 +541,54 @@ impl<'a> Parser<'a> {
534541
};
535542
Ok(Some(arg))
536543
}
544+
545+
fn get_ident_from_generic_arg(
546+
&self,
547+
gen_arg: GenericArg,
548+
lo: Span,
549+
) -> PResult<'a, (Ident, Option<GenericArgs>)> {
550+
let gen_arg_span = gen_arg.span();
551+
match gen_arg {
552+
GenericArg::Type(t) => match t.into_inner().kind {
553+
ast::TyKind::Path(qself, mut path) => {
554+
if let Some(qself) = qself {
555+
let mut err = self.struct_span_err(
556+
gen_arg_span,
557+
"qualified paths cannot be used in associated type constraints",
558+
);
559+
err.span_label(
560+
qself.path_span,
561+
"not allowed in associated type constraints",
562+
);
563+
return Err(err);
564+
}
565+
if path.segments.len() == 1 {
566+
let path_seg = path.segments.remove(0);
567+
let ident = path_seg.ident;
568+
let gen_args = path_seg.args.map(|args| args.into_inner());
569+
return Ok((ident, gen_args));
570+
}
571+
let err = self.struct_span_err(
572+
path.span,
573+
"paths with multiple segments cannot be used in associated type constraints",
574+
);
575+
return Err(err);
576+
}
577+
_ => {
578+
let span = lo.to(self.prev_token.span);
579+
let err = self.struct_span_err(
580+
span,
581+
"only path types can be used in associated type constraints",
582+
);
583+
return Err(err);
584+
}
585+
},
586+
_ => {
587+
let span = lo.to(self.prev_token.span);
588+
let err = self
589+
.struct_span_err(span, "only types can be used in associated type constraints");
590+
return Err(err);
591+
}
592+
}
593+
}
537594
}

0 commit comments

Comments
 (0)