diff options
| author | Alexander Regueiro <alexreg@me.com> | 2019-02-28 22:43:53 +0000 |
|---|---|---|
| committer | Alexander Regueiro <alexreg@me.com> | 2019-06-05 21:09:26 +0100 |
| commit | 3816958f18ea6c8990d64d03da839e5a180b0b9b (patch) | |
| tree | 1bf9dca622038936fb05d803c5cd441b7e95885e /src/libsyntax | |
| parent | dce27cba78ebda2c5adfe149d33af5a88a28d08d (diff) | |
| download | rust-3816958f18ea6c8990d64d03da839e5a180b0b9b.tar.gz rust-3816958f18ea6c8990d64d03da839e5a180b0b9b.zip | |
Implemented for function bounds, type bounds, and named existential types.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 28 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/mut_visit.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 52 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/util/node_count.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 21 |
7 files changed, 103 insertions, 56 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 31e89804800..598232f9f8f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -190,9 +190,9 @@ pub struct AngleBracketedArgs { pub span: Span, /// The arguments for this path segment. pub args: Vec<GenericArg>, - /// Bindings (equality constraints) on associated types, if present. - /// E.g., `Foo<A = Bar>`. - pub bindings: Vec<TypeBinding>, + /// Constraints on associated types, if any. + /// E.g., `Foo<A = Bar, B: Baz>`. + pub constraints: Vec<AssocTyConstraint>, } impl Into<Option<P<GenericArgs>>> for AngleBracketedArgs { @@ -225,7 +225,7 @@ impl ParenthesizedArgs { AngleBracketedArgs { span: self.span, args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(), - bindings: vec![], + constraints: vec![], } } } @@ -1611,15 +1611,29 @@ impl fmt::Display for UintTy { } } -// Bind a type to an associated type: `A = Foo`. +/// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or +/// `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`). #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct TypeBinding { +pub struct AssocTyConstraint { pub id: NodeId, pub ident: Ident, - pub ty: P<Ty>, + pub kind: AssocTyConstraintKind, pub span: Span, } +/// The kinds of an `AssocTyConstraint`. +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum AssocTyConstraintKind { + /// E.g., `A = Bar` in `Foo<A = Bar>`. + Equality { + ty: P<Ty>, + }, + /// E.g. `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`. + Bound { + bounds: GenericBounds, + }, +} + #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Ty { pub id: NodeId, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 435a3d7b6a2..2a03e49996b 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -18,7 +18,7 @@ pub trait AstBuilder { global: bool, idents: Vec<ast::Ident>, args: Vec<ast::GenericArg>, - bindings: Vec<ast::TypeBinding>) + constraints: Vec<ast::AssocTyConstraint>) -> ast::Path; fn qpath(&self, self_type: P<ast::Ty>, @@ -29,7 +29,7 @@ pub trait AstBuilder { trait_path: ast::Path, ident: ast::Ident, args: Vec<ast::GenericArg>, - bindings: Vec<ast::TypeBinding>) + constraints: Vec<ast::AssocTyConstraint>) -> (ast::QSelf, ast::Path); // types and consts @@ -302,7 +302,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { global: bool, mut idents: Vec<ast::Ident> , args: Vec<ast::GenericArg>, - bindings: Vec<ast::TypeBinding> ) + constraints: Vec<ast::AssocTyConstraint> ) -> ast::Path { assert!(!idents.is_empty()); let add_root = global && !idents[0].is_path_segment_keyword(); @@ -314,8 +314,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { segments.extend(idents.into_iter().map(|ident| { ast::PathSegment::from_ident(ident.with_span_pos(span)) })); - let args = if !args.is_empty() || !bindings.is_empty() { - ast::AngleBracketedArgs { args, bindings, span }.into() + let args = if !args.is_empty() || !constraints.is_empty() { + ast::AngleBracketedArgs { args, constraints, span }.into() } else { None }; @@ -346,11 +346,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { trait_path: ast::Path, ident: ast::Ident, args: Vec<ast::GenericArg>, - bindings: Vec<ast::TypeBinding>) + constraints: Vec<ast::AssocTyConstraint>) -> (ast::QSelf, ast::Path) { let mut path = trait_path; - let args = if !args.is_empty() || !bindings.is_empty() { - ast::AngleBracketedArgs { args, bindings, span: ident.span }.into() + let args = if !args.is_empty() || !constraints.is_empty() { + ast::AngleBracketedArgs { args, constraints, span: ident.span }.into() } else { None }; diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 75751309899..fb1a7a680ba 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -163,8 +163,8 @@ pub trait MutVisitor: Sized { noop_visit_lifetime(l, self); } - fn visit_ty_binding(&mut self, t: &mut TypeBinding) { - noop_visit_ty_binding(t, self); + fn visit_ty_constraint(&mut self, t: &mut AssocTyConstraint) { + noop_visit_ty_constraint(t, self); } fn visit_mod(&mut self, m: &mut Mod) { @@ -400,11 +400,20 @@ pub fn noop_visit_guard<T: MutVisitor>(g: &mut Guard, vis: &mut T) { } } -pub fn noop_visit_ty_binding<T: MutVisitor>(TypeBinding { id, ident, ty, span }: &mut TypeBinding, - vis: &mut T) { +pub fn noop_visit_ty_constraint<T: MutVisitor>( + AssocTyConstraint { id, ident, kind, span }: &mut AssocTyConstraint, + vis: &mut T +) { vis.visit_id(id); vis.visit_ident(ident); - vis.visit_ty(ty); + match kind { + AssocTyConstraintKind::Equality { ref mut ty } => { + vis.visit_ty(ty); + } + AssocTyConstraintKind::Bound { ref mut bounds } => { + visit_bounds(bounds, vis); + } + } vis.visit_span(span); } @@ -499,9 +508,9 @@ pub fn noop_visit_generic_arg<T: MutVisitor>(arg: &mut GenericArg, vis: &mut T) pub fn noop_visit_angle_bracketed_parameter_data<T: MutVisitor>(data: &mut AngleBracketedArgs, vis: &mut T) { - let AngleBracketedArgs { args, bindings, span } = data; + let AngleBracketedArgs { args, constraints, span } = data; visit_vec(args, |arg| vis.visit_generic_arg(arg)); - visit_vec(bindings, |binding| vis.visit_ty_binding(binding)); + visit_vec(constraints, |constraint| vis.visit_ty_constraint(constraint)); vis.visit_span(span); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index abfce660c80..790013f6eb1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -27,7 +27,7 @@ use crate::ast::{VariantData, StructField}; use crate::ast::StrStyle; use crate::ast::SelfKind; use crate::ast::{TraitItem, TraitRef, TraitObjectSyntax}; -use crate::ast::{Ty, TyKind, TypeBinding, GenericBounds}; +use crate::ast::{Ty, TyKind, AssocTyConstraint, AssocTyConstraintKind, GenericBounds}; use crate::ast::{Visibility, VisibilityKind, WhereClause, CrateSugar}; use crate::ast::{UseTree, UseTreeKind}; use crate::ast::{BinOpKind, UnOp}; @@ -1791,11 +1791,11 @@ impl<'a> Parser<'a> { let lo = self.span; let args = if self.eat_lt() { // `<'a, T, A = U>` - let (args, bindings) = + let (args, constraints) = self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?; self.expect_gt()?; let span = lo.to(self.prev_span); - AngleBracketedArgs { args, bindings, span }.into() + AngleBracketedArgs { args, constraints, span }.into() } else { // `(T, U) -> R` self.bump(); // `(` @@ -5076,7 +5076,7 @@ impl<'a> Parser<'a> { &mut self, style: PathStyle, lo: Span, - ) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> { + ) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> { // We need to detect whether there are extra leading left angle brackets and produce an // appropriate error and suggestion. This cannot be implemented by looking ahead at // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens @@ -5211,11 +5211,11 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings, /// possibly including trailing comma. - fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> { + fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> { let mut args = Vec::new(); - let mut bindings = Vec::new(); - let mut misplaced_assoc_ty_bindings: Vec<Span> = Vec::new(); - let mut assoc_ty_bindings: Vec<Span> = Vec::new(); + let mut constraints = Vec::new(); + let mut misplaced_assoc_ty_constraints: Vec<Span> = Vec::new(); + let mut assoc_ty_constraints: Vec<Span> = Vec::new(); let args_lo = self.span; @@ -5223,21 +5223,31 @@ impl<'a> Parser<'a> { if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { // Parse lifetime argument. args.push(GenericArg::Lifetime(self.expect_lifetime())); - misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings); - } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) { - // Parse associated type binding. + misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints); + } else if self.check_ident() && self.look_ahead(1, + |t| t == &token::Eq || t == &token::Colon) { + // Parse associated type constraint. let lo = self.span; let ident = self.parse_ident()?; - self.bump(); - let ty = self.parse_ty()?; + let kind = if self.eat(&token::Eq) { + AssocTyConstraintKind::Equality { + ty: self.parse_ty()?, + } + } else if self.eat(&token::Colon) { + AssocTyConstraintKind::Bound { + bounds: self.parse_generic_bounds(Some(self.prev_span))?, + } + } else { + unreachable!(); + }; let span = lo.to(self.prev_span); - bindings.push(TypeBinding { + constraints.push(AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, - ty, + kind, span, }); - assoc_ty_bindings.push(span); + assoc_ty_constraints.push(span); } else if self.check_const_arg() { // Parse const argument. let expr = if let token::OpenDelim(token::Brace) = self.token { @@ -5261,11 +5271,11 @@ impl<'a> Parser<'a> { value: expr, }; args.push(GenericArg::Const(value)); - misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings); + misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints); } else if self.check_type() { // Parse type argument. args.push(GenericArg::Type(self.parse_ty()?)); - misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings); + misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints); } else { break } @@ -5278,12 +5288,12 @@ impl<'a> Parser<'a> { // FIXME: we would like to report this in ast_validation instead, but we currently do not // preserve ordering of generic parameters with respect to associated type binding, so we // lose that information after parsing. - if misplaced_assoc_ty_bindings.len() > 0 { + if misplaced_assoc_ty_constraints.len() > 0 { let mut err = self.struct_span_err( args_lo.to(self.prev_span), "associated type bindings must be declared after generic parameters", ); - for span in misplaced_assoc_ty_bindings { + for span in misplaced_assoc_ty_constraints { err.span_label( span, "this associated type binding should be moved after the generic parameters", @@ -5292,7 +5302,7 @@ impl<'a> Parser<'a> { err.emit(); } - Ok((args, bindings)) + Ok((args, constraints)) } /// Parses an optional where-clause and places it in `generics`. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 44e1f5398d3..57c01e9e3ef 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2450,14 +2450,21 @@ impl<'a> State<'a> { let mut comma = data.args.len() != 0; - for binding in data.bindings.iter() { + for constraint in data.constraints.iter() { if comma { self.word_space(",")? } - self.print_ident(binding.ident)?; + self.print_ident(constraint.ident)?; self.s.space()?; - self.word_space("=")?; - self.print_type(&binding.ty)?; + match constraint.kind { + ast::AssocTyConstraintKind::Equality { ref ty } => { + self.word_space("=")?; + self.print_type(ty)?; + } + ast::AssocTyConstraintKind::Bound { ref bounds } => { + self.print_type_bounds(":", &*bounds)?; + } + } comma = true; } diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index 521edac8f5f..f17eb3b3943 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -131,9 +131,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_generic_args(self, path_span, generic_args) } - fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) { + fn visit_assoc_ty_constraint(&mut self, constraint: &AssocTyConstraint) { self.count += 1; - walk_assoc_type_binding(self, type_binding) + walk_assoc_ty_constraint(self, constraint) } fn visit_attribute(&mut self, _attr: &Attribute) { self.count += 1; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index ba57055b8e0..334709b1521 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -139,8 +139,8 @@ pub trait Visitor<'ast>: Sized { GenericArg::Const(ct) => self.visit_anon_const(ct), } } - fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) { - walk_assoc_type_binding(self, type_binding) + fn visit_assoc_ty_constraint(&mut self, constraint: &'ast AssocTyConstraint) { + walk_assoc_ty_constraint(self, constraint) } fn visit_attribute(&mut self, attr: &'ast Attribute) { walk_attribute(self, attr) @@ -404,7 +404,7 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V, match *generic_args { GenericArgs::AngleBracketed(ref data) => { walk_list!(visitor, visit_generic_arg, &data.args); - walk_list!(visitor, visit_assoc_type_binding, &data.bindings); + walk_list!(visitor, visit_assoc_ty_constraint, &data.constraints); } GenericArgs::Parenthesized(ref data) => { walk_list!(visitor, visit_ty, &data.inputs); @@ -413,10 +413,17 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V, } } -pub fn walk_assoc_type_binding<'a, V: Visitor<'a>>(visitor: &mut V, - type_binding: &'a TypeBinding) { - visitor.visit_ident(type_binding.ident); - visitor.visit_ty(&type_binding.ty); +pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(visitor: &mut V, + constraint: &'a AssocTyConstraint) { + visitor.visit_ident(constraint.ident); + match constraint.kind { + AssocTyConstraintKind::Equality { ref ty } => { + visitor.visit_ty(ty); + } + AssocTyConstraintKind::Bound { ref bounds } => { + walk_list!(visitor, visit_param_bound, bounds); + } + } } pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { |
