diff options
| author | bors <bors@rust-lang.org> | 2019-06-06 03:56:22 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-06-06 03:56:22 +0000 |
| commit | 740668dbd99dbf1726bbb0cca6cd0943ea2f7e27 (patch) | |
| tree | 7fcf783b5f92803e8ca4985eaa24097e76b6192c /src/libsyntax | |
| parent | 1bec46c9a5399d5e95c05e3428c3abd264780705 (diff) | |
| parent | ee890331f6e33afe12ef250eb6388db2aab7cbbf (diff) | |
| download | rust-740668dbd99dbf1726bbb0cca6cd0943ea2f7e27.tar.gz rust-740668dbd99dbf1726bbb0cca6cd0943ea2f7e27.zip | |
Auto merge of #57428 - alexreg:associated_type_bounds, r=nikomatsakis,Centril
Implementation of RFC 2289 (associated_type_bounds) This PR implements the [`asociated_type_bounds` feature](https://github.com/rust-lang/rfcs/blob/master/text/2289-associated-type-bounds.md). Associated type bounds are implemented in: - function/method arguments and return types - structs, enums, unions - associated items in traits - type aliases - type parameter defaults - trait objects - let bindings CC @nikomatsakis @centril
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 32 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 49 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 42 | ||||
| -rw-r--r-- | src/libsyntax/mut_visit.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 110 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/ptr.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/util/node_count.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 23 |
9 files changed, 186 insertions, 123 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index b8a10d90c3c..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 { @@ -213,7 +213,7 @@ pub struct ParenthesizedArgs { /// Overall span pub span: Span, - /// `(A,B)` + /// `(A, B)` pub inputs: Vec<P<Ty>>, /// `C` @@ -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, @@ -1840,7 +1854,7 @@ impl Arg { } } -/// Header (not the body) of a function declaration. +/// A header (not the body) of a function declaration. /// /// E.g., `fn foo(bar: baz)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 47c79f8466a..2a03e49996b 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -10,7 +10,7 @@ use rustc_target::spec::abi::Abi; use syntax_pos::{Pos, Span}; pub trait AstBuilder { - // paths + // Paths fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path; fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path; fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path; @@ -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 @@ -69,7 +69,7 @@ pub trait AstBuilder { bounds: ast::GenericBounds) -> ast::GenericParam; - // statements + // Statements fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt; fn stmt_semi(&self, expr: P<ast::Expr>) -> ast::Stmt; fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: P<ast::Expr>) -> ast::Stmt; @@ -83,11 +83,11 @@ pub trait AstBuilder { fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt; fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt; - // blocks + // Blocks fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block>; fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block>; - // expressions + // Expressions fn expr(&self, span: Span, node: ast::ExprKind) -> P<ast::Expr>; fn expr_path(&self, path: ast::Path) -> P<ast::Expr>; fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr>; @@ -194,12 +194,12 @@ pub trait AstBuilder { fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>, ident: ast::Ident) -> P<ast::Expr>; - // items + // Items fn item(&self, span: Span, name: Ident, attrs: Vec<ast::Attribute> , node: ast::ItemKind) -> P<ast::Item>; fn arg(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::Arg; - // FIXME unused self + // FIXME: unused `self` fn fn_decl(&self, inputs: Vec<ast::Arg> , output: ast::FunctionRetTy) -> P<ast::FnDecl>; fn item_fn_poly(&self, @@ -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 }; @@ -552,7 +552,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } } - // Generate `let _: Type;`, usually used for type assertions. + // Generates `let _: Type;`, which is usually used for type assertions. fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt { let local = P(ast::Local { pat: self.pat_wild(span), @@ -606,7 +606,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(path.span, ast::ExprKind::Path(None, path)) } - /// Constructs a QPath expression. + /// Constructs a `QPath` expression. fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr> { self.expr(span, ast::ExprKind::Path(Some(qself), path)) } @@ -736,7 +736,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(sp, ast::ExprKind::Cast(expr, ty)) } - fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> { let some = self.std_path(&[sym::option, sym::Option, sym::Some]); self.expr_call_global(sp, some, vec![expr]) @@ -748,12 +747,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_path(none) } - fn expr_break(&self, sp: Span) -> P<ast::Expr> { self.expr(sp, ast::ExprKind::Break(None, None)) } - fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> { self.expr(sp, ast::ExprKind::Tup(exprs)) } @@ -797,22 +794,22 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let binding_pat = self.pat_ident(sp, binding_variable); let binding_expr = self.expr_ident(sp, binding_variable); - // Ok(__try_var) pattern + // `Ok(__try_var)` pattern let ok_pat = self.pat_tuple_struct(sp, ok_path, vec![binding_pat.clone()]); - // Err(__try_var) (pattern and expression resp.) + // `Err(__try_var)` (pattern and expression respectively) let err_pat = self.pat_tuple_struct(sp, err_path.clone(), vec![binding_pat]); let err_inner_expr = self.expr_call(sp, self.expr_path(err_path), vec![binding_expr.clone()]); - // return Err(__try_var) + // `return Err(__try_var)` let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr))); - // Ok(__try_var) => __try_var + // `Ok(__try_var) => __try_var` let ok_arm = self.arm(sp, vec![ok_pat], binding_expr); - // Err(__try_var) => return Err(__try_var) + // `Err(__try_var) => return Err(__try_var)` let err_arm = self.arm(sp, vec![err_pat], err_expr); - // match head { Ok() => ..., Err() => ... } + // `match head { Ok() => ..., Err() => ... }` self.expr_match(sp, head, vec![ok_arm, err_arm]) } @@ -972,7 +969,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } } - // FIXME unused self + // FIXME: unused `self` fn fn_decl(&self, inputs: Vec<ast::Arg>, output: ast::FunctionRetTy) -> P<ast::FnDecl> { P(ast::FnDecl { inputs, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b2646efe3e4..4a95b6f69a1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -15,7 +15,10 @@ use AttributeType::*; use AttributeGate::*; -use crate::ast::{self, NodeId, GenericParam, GenericParamKind, PatKind, RangeEnd}; +use crate::ast::{ + self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, + PatKind, RangeEnd, +}; use crate::attr; use crate::early_buffered_lints::BufferedEarlyLintId; use crate::source_map::Spanned; @@ -554,6 +557,9 @@ declare_features! ( // Allows using C-variadics. (active, c_variadic, "1.34.0", Some(44930), None), + // Allows the user of associated type bounds. + (active, associated_type_bounds, "1.34.0", Some(52662), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -1917,7 +1923,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.builtin_attributes.get(&ident.name).map(|a| *a) }); - // check for gated attributes + // Check for gated attributes. self.context.check_attribute(attr, attr_info, false); if attr.check_name(sym::doc) { @@ -2115,7 +2121,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) { if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { if let ast::TyKind::Never = output_ty.node { - // Do nothing + // Do nothing. } else { self.visit_ty(output_ty) } @@ -2171,7 +2177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } _ => {} } - visit::walk_expr(self, e); + visit::walk_expr(self, e) } fn visit_arm(&mut self, arm: &'a ast::Arm) { @@ -2220,15 +2226,27 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); } - visit::walk_fn(self, fn_kind, fn_decl, span); + visit::walk_fn(self, fn_kind, fn_decl, span) } fn visit_generic_param(&mut self, param: &'a GenericParam) { - if let GenericParamKind::Const { .. } = param.kind { - gate_feature_post!(&self, const_generics, param.ident.span, - "const generics are unstable"); + match param.kind { + GenericParamKind::Const { .. } => + gate_feature_post!(&self, const_generics, param.ident.span, + "const generics are unstable"), + _ => {} + } + visit::walk_generic_param(self, param) + } + + fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { + match constraint.kind { + AssocTyConstraintKind::Bound { .. } => + gate_feature_post!(&self, associated_type_bounds, constraint.span, + "associated type bounds are unstable"), + _ => {} } - visit::walk_generic_param(self, param); + visit::walk_assoc_ty_constraint(self, constraint) } fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) { @@ -2266,7 +2284,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } _ => {} } - visit::walk_trait_item(self, ti); + visit::walk_trait_item(self, ti) } fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) { @@ -2298,7 +2316,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } _ => {} } - visit::walk_impl_item(self, ii); + visit::walk_impl_item(self, ii) } fn visit_vis(&mut self, vis: &'a ast::Visibility) { @@ -2306,7 +2324,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, crate_visibility_modifier, vis.span, "`crate` visibility modifier is experimental"); } - visit::walk_vis(self, vis); + visit::walk_vis(self, vis) } } 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 39fcd29e1b0..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}; @@ -191,24 +191,24 @@ enum PrevTokenKind { Other, } -/* ident is handled by common.rs */ +// NOTE: `Ident`s are handled by `common.rs`. #[derive(Clone)] pub struct Parser<'a> { pub sess: &'a ParseSess, - /// the current token: + /// The current token. pub token: token::Token, - /// the span of the current token: + /// The span of the current token. pub span: Span, - /// the span of the previous token: meta_var_span: Option<Span>, + /// The span of the previous token. pub prev_span: Span, - /// the previous token kind + /// The kind of the previous troken. prev_token_kind: PrevTokenKind, restrictions: Restrictions, - /// Used to determine the path to externally loaded source files + /// Used to determine the path to externally loaded source files. crate directory: Directory<'a>, - /// Whether to parse sub-modules in other files. + /// `true` to parse sub-modules in other files. pub recurse_into_file_modules: bool, /// Name of the root module this parser originated from. If `None`, then the /// name is not known. This does not change while the parser is descending @@ -217,7 +217,7 @@ pub struct Parser<'a> { crate expected_tokens: Vec<TokenType>, crate token_cursor: TokenCursor, desugar_doc_comments: bool, - /// Whether we should configure out of line modules as we parse. + /// `true` we should configure out of line modules as we parse. pub cfg_mods: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error @@ -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(); // `(` @@ -2680,8 +2680,7 @@ impl<'a> Parser<'a> { } } - // parse a stream of tokens into a list of TokenTree's, - // up to EOF. + /// Parses a stream of tokens into a list of `TokenTree`s, up to EOF. pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec<TokenTree>> { let mut tts = Vec::new(); while self.token != token::Eof { @@ -5077,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 @@ -5212,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; @@ -5224,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 { @@ -5262,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 } @@ -5279,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", @@ -5293,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`. @@ -5344,9 +5353,10 @@ impl<'a> Parser<'a> { // Parse optional `for<'a, 'b>`. // This `for` is parsed greedily and applies to the whole predicate, // the bounded type can have its own `for` applying only to it. - // Example 1: for<'a> Trait1<'a>: Trait2<'a /*ok*/> - // Example 2: (for<'a> Trait1<'a>): Trait2<'a /*not ok*/> - // Example 3: for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /*ok*/, 'b /*not ok*/> + // Examples: + // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>` + // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>` + // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>` let lifetime_defs = self.parse_late_bound_lifetime_defs()?; // Parse type with mandatory colon and (possibly empty) bounds, @@ -5478,17 +5488,17 @@ impl<'a> Parser<'a> { this.look_ahead(n + 1, |t| t != &token::ModSep) }; - // Parse optional self parameter of a method. - // Only a limited set of initial token sequences is considered self parameters, anything + // Parse optional `self` parameter of a method. + // Only a limited set of initial token sequences is considered `self` parameters; anything // else is parsed as a normal function parameter list, so some lookahead is required. let eself_lo = self.span; let (eself, eself_ident, eself_hi) = match self.token { token::BinOp(token::And) => { - // &self - // &mut self - // &'lt self - // &'lt mut self - // ¬_self + // `&self` + // `&mut self` + // `&'lt self` + // `&'lt mut self` + // `¬_self` (if isolated_self(self, 1) { self.bump(); SelfKind::Region(None, Mutability::Immutable) @@ -5514,10 +5524,10 @@ impl<'a> Parser<'a> { }, expect_ident(self), self.prev_span) } token::BinOp(token::Star) => { - // *self - // *const self - // *mut self - // *not_self + // `*self` + // `*const self` + // `*mut self` + // `*not_self` // Emit special error for `self` cases. let msg = "cannot pass `self` by raw pointer"; (if isolated_self(self, 1) { @@ -5540,8 +5550,8 @@ impl<'a> Parser<'a> { } token::Ident(..) => { if isolated_self(self, 0) { - // self - // self: TYPE + // `self` + // `self: TYPE` let eself_ident = expect_ident(self); let eself_hi = self.prev_span; (if self.eat(&token::Colon) { @@ -5552,8 +5562,8 @@ impl<'a> Parser<'a> { }, eself_ident, eself_hi) } else if self.token.is_keyword(kw::Mut) && isolated_self(self, 1) { - // mut self - // mut self: TYPE + // `mut self` + // `mut self: TYPE` self.bump(); let eself_ident = expect_ident(self); let eself_hi = self.prev_span; @@ -5580,7 +5590,7 @@ impl<'a> Parser<'a> { { self.expect(&token::OpenDelim(token::Paren))?; - // Parse optional self argument + // Parse optional self argument. let self_arg = self.parse_self_arg()?; // Parse the rest of the function parameter list. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b81dc53ef68..57c01e9e3ef 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1715,7 +1715,7 @@ impl<'a> State<'a> { match els { Some(_else) => { match _else.node { - // "another else-if" + // Another `else if` block. ast::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; @@ -1725,7 +1725,7 @@ impl<'a> State<'a> { self.print_block(then)?; self.print_else(e.as_ref().map(|e| &**e)) } - // "another else-if-let" + // Another `else if let` block. ast::ExprKind::IfLet(ref pats, ref expr, ref then, ref e) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; @@ -1738,14 +1738,14 @@ impl<'a> State<'a> { self.print_block(then)?; self.print_else(e.as_ref().map(|e| &**e)) } - // "final else" + // Final `else` block. ast::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1)?; self.ibox(0)?; self.s.word(" else ")?; self.print_block(b) } - // BLEAH, constraints would be great here + // Constraints would be great here! _ => { panic!("print_if saw if with weird alternative"); } @@ -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/ptr.rs b/src/libsyntax/ptr.rs index 9afcb7c4621..d577243fb3d 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -57,7 +57,8 @@ impl<T: 'static> P<T> { { f(*self.ptr) } - /// Equivalent to and_then(|x| x) + + /// Equivalent to `and_then(|x| x)`. pub fn into_inner(self) -> T { *self.ptr } 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 eb516b5c7c6..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) { @@ -499,7 +506,7 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi walk_list!(visitor, visit_attribute, param.attrs.iter()); walk_list!(visitor, visit_param_bound, ¶m.bounds); match param.kind { - GenericParamKind::Lifetime => {} + GenericParamKind::Lifetime => (), GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default), GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty), } |
