diff options
| author | Konrad Borowski <konrad@borowski.pw> | 2018-12-23 16:47:11 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-23 16:47:11 +0100 |
| commit | 8ac5380ea0204dbdcbc8108d259928b67d5f8ebb (patch) | |
| tree | 174d912756fc2678af50d46ff457f7504750a975 /src/libsyntax | |
| parent | b4a306c1e648c84f289c63e984941b7faad10af1 (diff) | |
| parent | ddab10a692aab2e2984b5c826ed9d78a57e94851 (diff) | |
| download | rust-8ac5380ea0204dbdcbc8108d259928b67d5f8ebb.tar.gz rust-8ac5380ea0204dbdcbc8108d259928b67d5f8ebb.zip | |
Merge branch 'master' into copied
Diffstat (limited to 'src/libsyntax')
38 files changed, 1058 insertions, 1228 deletions
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index 519cc7aa92c..fba2623e005 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -17,4 +17,4 @@ syntax_pos = { path = "../libsyntax_pos" } rustc_errors = { path = "../librustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.5", features = ["union"] } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 227017a9073..0792b2dc49c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -68,12 +68,12 @@ impl fmt::Debug for Lifetime { /// It's represented as a sequence of identifiers, /// along with a bunch of supporting information. /// -/// E.g. `std::cmp::PartialEq` +/// E.g., `std::cmp::PartialEq`. #[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Path { pub span: Span, /// The segments in the path: the things separated by `::`. - /// Global paths begin with `keywords::CrateRoot`. + /// Global paths begin with `keywords::PathRoot`. pub segments: Vec<PathSegment>, } @@ -96,8 +96,8 @@ impl fmt::Display for Path { } impl Path { - // convert a span and an identifier to the corresponding - // 1-segment path + // Convert a span and an identifier to the corresponding + // one-segment path. pub fn from_ident(ident: Ident) -> Path { Path { segments: vec![PathSegment::from_ident(ident)], @@ -105,25 +105,14 @@ impl Path { } } - // Make a "crate root" segment for this path unless it already has it - // or starts with something like `self`/`super`/`$crate`/etc. - pub fn make_root(&self) -> Option<PathSegment> { - if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) { - if ident.is_path_segment_keyword() { - return None; - } - } - Some(PathSegment::crate_root(self.span.shrink_to_lo())) - } - pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == keywords::CrateRoot.name() + !self.segments.is_empty() && self.segments[0].ident.name == keywords::PathRoot.name() } } /// A segment of a path: an identifier, an optional lifetime, and a set of types. /// -/// E.g. `std`, `String` or `Box<T>` +/// E.g., `std`, `String` or `Box<T>`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct PathSegment { /// The identifier portion of this path segment. @@ -144,14 +133,14 @@ impl PathSegment { pub fn from_ident(ident: Ident) -> Self { PathSegment { ident, id: DUMMY_NODE_ID, args: None } } - pub fn crate_root(span: Span) -> Self { - PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span)) + pub fn path_root(span: Span) -> Self { + PathSegment::from_ident(Ident::new(keywords::PathRoot.name(), span)) } } /// Arguments of a path segment. /// -/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)` +/// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericArgs { /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` @@ -293,7 +282,7 @@ pub type GenericBounds = Vec<GenericBound>; #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericParamKind { - /// A lifetime definition, e.g. `'a: 'b+'c+'d`. + /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime, Type { default: Option<P<Ty>>, @@ -345,11 +334,11 @@ pub struct WhereClause { /// A single predicate in a `where` clause #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum WherePredicate { - /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c` + /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), - /// A lifetime predicate, e.g. `'a: 'b+'c` + /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate), - /// An equality predicate (unsupported) + /// An equality predicate (unsupported). EqPredicate(WhereEqPredicate), } @@ -365,7 +354,7 @@ impl WherePredicate { /// A type bound. /// -/// E.g. `for<'c> Foo: Send+Clone+'c` +/// E.g., `for<'c> Foo: Send + Clone + 'c`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereBoundPredicate { pub span: Span, @@ -379,7 +368,7 @@ pub struct WhereBoundPredicate { /// A lifetime predicate. /// -/// E.g. `'a: 'b+'c` +/// E.g., `'a: 'b + 'c`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereRegionPredicate { pub span: Span, @@ -389,7 +378,7 @@ pub struct WhereRegionPredicate { /// An equality predicate (unsupported). /// -/// E.g. `T=int` +/// E.g., `T = int`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct WhereEqPredicate { pub id: NodeId, @@ -398,8 +387,8 @@ pub struct WhereEqPredicate { pub rhs_ty: P<Ty>, } -/// The set of MetaItems that define the compilation environment of the crate, -/// used to drive conditional compilation +/// The set of `MetaItem`s that define the compilation environment of the crate, +/// used to drive conditional compilation. pub type CrateConfig = FxHashSet<(Name, Option<Symbol>)>; #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -414,20 +403,20 @@ pub type NestedMetaItem = Spanned<NestedMetaItemKind>; /// Possible values inside of compile-time attribute lists. /// -/// E.g. the '..' in `#[name(..)]`. +/// E.g., the '..' in `#[name(..)]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum NestedMetaItemKind { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), /// A literal. /// - /// E.g. "foo", 64, true + /// E.g., `"foo"`, `64`, `true`. Literal(Lit), } /// A spanned compile-time attribute item. /// -/// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]` +/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct MetaItem { pub ident: Path, @@ -437,26 +426,26 @@ pub struct MetaItem { /// A compile-time attribute item. /// -/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]` +/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum MetaItemKind { /// Word meta item. /// - /// E.g. `test` as in `#[test]` + /// E.g., `test` as in `#[test]`. Word, /// List meta item. /// - /// E.g. `derive(..)` as in `#[derive(..)]` + /// E.g., `derive(..)` as in `#[derive(..)]`. List(Vec<NestedMetaItem>), /// Name value meta item. /// - /// E.g. `feature = "foo"` as in `#[feature = "foo"]` + /// E.g., `feature = "foo"` as in `#[feature = "foo"]`. NameValue(Lit), } /// A Block (`{ .. }`). /// -/// E.g. `{ .. }` as in `fn foo() { .. }` +/// E.g., `{ .. }` as in `fn foo() { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Block { /// Statements in a block @@ -579,7 +568,7 @@ pub enum RangeSyntax { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum PatKind { - /// Represents a wildcard pattern (`_`) + /// Represents a wildcard pattern (`_`). Wild, /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`), @@ -588,13 +577,13 @@ pub enum PatKind { /// during name resolution. Ident(BindingMode, Ident, Option<P<Pat>>), - /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. + /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. Struct(Path, Vec<Spanned<FieldPat>>, bool), - /// A tuple struct/variant pattern `Variant(x, y, .., z)`. + /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. - /// 0 <= position <= subpats.len() + /// `0 <= position <= subpats.len()`. TupleStruct(Path, Vec<P<Pat>>, Option<usize>), /// A possibly qualified path pattern. @@ -603,24 +592,24 @@ pub enum PatKind { /// only legally refer to associated constants. Path(Option<QSelf>, Path), - /// A tuple pattern `(a, b)`. + /// A tuple pattern (`(a, b)`). /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. - /// 0 <= position <= subpats.len() + /// `0 <= position <= subpats.len()`. Tuple(Vec<P<Pat>>, Option<usize>), - /// A `box` pattern + /// A `box` pattern. Box(P<Pat>), - /// A reference pattern, e.g. `&mut (a, b)` + /// A reference pattern (e.g., `&mut (a, b)`). Ref(P<Pat>, Mutability), - /// A literal + /// A literal. Lit(P<Expr>), - /// A range pattern, e.g. `1...2`, `1..=2` or `1..2` + /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). Range(P<Expr>, P<Expr>, Spanned<RangeEnd>), /// `[a, b, ..i, y, z]` is represented as: /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>), - /// Parentheses in patterns used for grouping, i.e. `(PAT)`. + /// Parentheses in patterns used for grouping (i.e., `(PAT)`). Paren(P<Pat>), - /// A macro pattern; pre-expansion + /// A macro pattern; pre-expansion. Mac(Mac), } @@ -818,23 +807,23 @@ pub enum StmtKind { #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum MacStmtStyle { - /// The macro statement had a trailing semicolon, e.g. `foo! { ... };` - /// `foo!(...);`, `foo![...];` + /// The macro statement had a trailing semicolon (e.g., `foo! { ... };` + /// `foo!(...);`, `foo![...];`). Semicolon, - /// The macro statement had braces; e.g. foo! { ... } + /// The macro statement had braces (e.g., `foo! { ... }`). Braces, - /// The macro statement had parentheses or brackets and no semicolon; e.g. - /// `foo!(...)`. All of these will end up being converted into macro + /// The macro statement had parentheses or brackets and no semicolon (e.g., + /// `foo!(...)`). All of these will end up being converted into macro /// expressions. NoBraces, } -/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;` +/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Local { pub pat: P<Pat>, pub ty: Option<P<Ty>>, - /// Initializer expression to set the value, if any + /// Initializer expression to set the value, if any. pub init: Option<P<Expr>>, pub id: NodeId, pub span: Span, @@ -843,7 +832,7 @@ pub struct Local { /// An arm of a 'match'. /// -/// E.g. `0..=10 => { println!("match!") }` as in +/// E.g., `0..=10 => { println!("match!") }` as in /// /// ``` /// match 123 { @@ -889,8 +878,8 @@ pub enum UnsafeSource { /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. -/// These are usually found nested inside types (e.g. array lengths) -/// or expressions (e.g. repeat counts), and also used to define +/// These are usually found nested inside types (e.g., array lengths) +/// or expressions (e.g., repeat counts), and also used to define /// explicit discriminant values for enum variants. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct AnonConst { @@ -912,7 +901,7 @@ pub struct Expr { static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 88); impl Expr { - /// Whether this expression would be valid somewhere that expects a value, for example, an `if` + /// Whether this expression would be valid somewhere that expects a value; for example, an `if` /// condition. pub fn returns(&self) -> bool { if let ExprKind::Block(ref block, _) = self.node { @@ -1060,24 +1049,24 @@ pub enum ExprKind { /// /// The `PathSegment` represents the method name and its generic arguments /// (within the angle brackets). - /// The first element of the vector of `Expr`s is the expression that evaluates + /// The first element of the vector of an `Expr` is the expression that evaluates /// to the object on which the method is being called on (the receiver), /// and the remaining elements are the rest of the arguments. /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. MethodCall(PathSegment, Vec<P<Expr>>), - /// A tuple (`(a, b, c ,d)`) + /// A tuple (e.g., `(a, b, c, d)`). Tup(Vec<P<Expr>>), - /// A binary operation (For example: `a + b`, `a * b`) + /// A binary operation (e.g., `a + b`, `a * b`). Binary(BinOp, P<Expr>, P<Expr>), - /// A unary operation (For example: `!x`, `*x`) + /// A unary operation (e.g., `!x`, `*x`). Unary(UnOp, P<Expr>), - /// A literal (For example: `1`, `"foo"`) + /// A literal (e.g., `1`, `"foo"`). Lit(Lit), - /// A cast (`foo as f64`) + /// A cast (e.g., `foo as f64`). Cast(P<Expr>, P<Ty>), Type(P<Expr>, P<Ty>), - /// An `if` block, with an optional else block + /// An `if` block, with an optional `else` block. /// /// `if expr { block } else { expr }` If(P<Expr>, P<Block>, Option<P<Expr>>), @@ -1091,31 +1080,31 @@ pub enum ExprKind { /// /// `'label: while expr { block }` While(P<Expr>, P<Block>, Option<Label>), - /// A while-let loop, with an optional label + /// A `while let` loop, with an optional label. /// /// `'label: while let pat = expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. WhileLet(Vec<P<Pat>>, P<Expr>, P<Block>, Option<Label>), - /// A for loop, with an optional label + /// A `for` loop, with an optional label. /// /// `'label: for pat in expr { block }` /// /// This is desugared to a combination of `loop` and `match` expressions. ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Label>), - /// Conditionless loop (can be exited with break, continue, or return) + /// Conditionless loop (can be exited with `break`, `continue`, or `return`). /// /// `'label: loop { block }` Loop(P<Block>, Option<Label>), /// A `match` block. Match(P<Expr>, Vec<Arm>), - /// A closure (for example, `move |a, b, c| a + b + c`) + /// A closure (e.g., `move |a, b, c| a + b + c`). /// - /// The final span is the span of the argument block `|...|` + /// The final span is the span of the argument block `|...|`. Closure(CaptureBy, IsAsync, Movability, P<FnDecl>, P<Expr>, Span), - /// A block (`'label: { ... }`) + /// A block (`'label: { ... }`). Block(P<Block>, Option<Label>), - /// An async block (`async move { ... }`) + /// An async block (`async move { ... }`). /// /// The `NodeId` is the `NodeId` for the closure that results from /// desugaring an async block, just like the NodeId field in the @@ -1124,70 +1113,69 @@ pub enum ExprKind { /// created during lowering cannot be made the parent of any other /// preexisting defs. Async(CaptureBy, NodeId, P<Block>), - /// A try block (`try { ... }`) + /// A try block (`try { ... }`). TryBlock(P<Block>), - /// An assignment (`a = foo()`) + /// An assignment (`a = foo()`). Assign(P<Expr>, P<Expr>), - /// An assignment with an operator + /// An assignment with an operator. /// - /// For example, `a += 1`. + /// E.g., `a += 1`. AssignOp(BinOp, P<Expr>, P<Expr>), - /// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct field + /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field. Field(P<Expr>, Ident), - /// An indexing operation (`foo[2]`) + /// An indexing operation (e.g., `foo[2]`). Index(P<Expr>, P<Expr>), - /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`) + /// A range (e.g., `1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`). Range(Option<P<Expr>>, Option<P<Expr>>, RangeLimits), /// Variable reference, possibly containing `::` and/or type - /// parameters, e.g. foo::bar::<baz>. + /// parameters (e.g., `foo::bar::<baz>`). /// - /// Optionally "qualified", - /// E.g. `<Vec<T> as SomeTrait>::SomeType`. + /// Optionally "qualified" (e.g., `<Vec<T> as SomeTrait>::SomeType`). Path(Option<QSelf>, Path), - /// A referencing operation (`&a` or `&mut a`) + /// A referencing operation (`&a` or `&mut a`). AddrOf(Mutability, P<Expr>), - /// A `break`, with an optional label to break, and an optional expression + /// A `break`, with an optional label to break, and an optional expression. Break(Option<Label>, Option<P<Expr>>), - /// A `continue`, with an optional label + /// A `continue`, with an optional label. Continue(Option<Label>), - /// A `return`, with an optional value to be returned + /// A `return`, with an optional value to be returned. Ret(Option<P<Expr>>), - /// Output of the `asm!()` macro + /// Output of the `asm!()` macro. InlineAsm(P<InlineAsm>), - /// A macro invocation; pre-expansion + /// A macro invocation; pre-expansion. Mac(Mac), /// A struct literal expression. /// - /// For example, `Foo {x: 1, y: 2}`, or - /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`. + /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. base}`, + /// where `base` is the `Option<Expr>`. Struct(Path, Vec<Field>, Option<P<Expr>>), /// An array literal constructed from one repeated element. /// - /// For example, `[1; 5]`. The expression is the element to be + /// E.g., `[1; 5]`. The expression is the element to be /// repeated; the constant is the number of times to repeat it. Repeat(P<Expr>, AnonConst), - /// No-op: used solely so we can pretty-print faithfully + /// No-op: used solely so we can pretty-print faithfully. Paren(P<Expr>), - /// `expr?` + /// A try expression (`expr?`). Try(P<Expr>), - /// A `yield`, with an optional value to be yielded + /// A `yield`, with an optional value to be yielded. Yield(Option<P<Expr>>), } -/// The explicit Self type in a "qualified path". The actual +/// The explicit `Self` type in a "qualified path". The actual /// path, including the trait and the associated item, is stored /// separately. `position` represents the index of the associated -/// item qualified with this Self type. +/// item qualified with this `Self` type. /// /// ```ignore (only-for-syntax-highlight) /// <Vec<T> as a::b::Trait>::AssociatedItem @@ -1209,14 +1197,14 @@ pub struct QSelf { pub position: usize, } -/// A capture clause +/// A capture clause. #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum CaptureBy { Value, Ref, } -/// The movability of a generator / closure literal +/// The movability of a generator / closure literal. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum Movability { Static, @@ -1225,12 +1213,12 @@ pub enum Movability { pub type Mac = Spanned<Mac_>; -/// Represents a macro invocation. The Path indicates which macro +/// Represents a macro invocation. The `Path` indicates which macro /// is being invoked, and the vector of token-trees contains the source /// of the macro invocation. /// -/// NB: the additional ident for a macro_rules-style macro is actually -/// stored in the enclosing item. Oog. +/// N.B., the additional ident for a `macro_rules`-style macro is actually +/// stored in the enclosing item. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mac_ { pub path: Path, @@ -1247,7 +1235,7 @@ pub enum MacDelimiter { impl Mac_ { pub fn stream(&self) -> TokenStream { - self.tts.clone().into() + self.tts.stream() } } @@ -1265,15 +1253,15 @@ impl MacroDef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] pub enum StrStyle { - /// A regular string, like `"foo"` + /// A regular string, like `"foo"`. Cooked, - /// A raw string, like `r##"foo"##` + /// A raw string, like `r##"foo"##`. /// /// The value is the number of `#` symbols used. Raw(u16), } -/// A literal +/// A literal. pub type Lit = Spanned<LitKind>; #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] @@ -1285,29 +1273,29 @@ pub enum LitIntType { /// Literal kind. /// -/// E.g. `"foo"`, `42`, `12.34` or `bool` +/// E.g., `"foo"`, `42`, `12.34`, or `bool`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] pub enum LitKind { - /// A string literal (`"foo"`) + /// A string literal (`"foo"`). Str(Symbol, StrStyle), - /// A byte string (`b"foo"`) + /// A byte string (`b"foo"`). ByteStr(Lrc<Vec<u8>>), - /// A byte char (`b'f'`) + /// A byte char (`b'f'`). Byte(u8), - /// A character literal (`'a'`) + /// A character literal (`'a'`). Char(char), - /// An integer literal (`1`) + /// An integer literal (`1`). Int(u128, LitIntType), - /// A float literal (`1f64` or `1E10f64`) + /// A float literal (`1f64` or `1E10f64`). Float(Symbol, FloatTy), - /// A float literal without a suffix (`1.0 or 1.0E10`) + /// A float literal without a suffix (`1.0 or 1.0E10`). FloatUnsuffixed(Symbol), - /// A boolean literal + /// A boolean literal. Bool(bool), } impl LitKind { - /// Returns true if this literal is a string and false otherwise. + /// Returns `true` if this literal is a string. pub fn is_str(&self) -> bool { match *self { LitKind::Str(..) => true, @@ -1315,7 +1303,7 @@ impl LitKind { } } - /// Returns true if this literal is byte literal string false otherwise. + /// Returns `true` if this literal is byte literal string. pub fn is_bytestr(&self) -> bool { match self { LitKind::ByteStr(_) => true, @@ -1323,7 +1311,7 @@ impl LitKind { } } - /// Returns true if this is a numeric literal. + /// Returns `true` if this is a numeric literal. pub fn is_numeric(&self) -> bool { match *self { LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => true, @@ -1331,8 +1319,8 @@ impl LitKind { } } - /// Returns true if this literal has no suffix. Note: this will return true - /// for literals with prefixes such as raw strings and byte strings. + /// Returns `true` if this literal has no suffix. + /// Note: this will return true for literals with prefixes such as raw strings and byte strings. pub fn is_unsuffixed(&self) -> bool { match *self { // unsuffixed variants @@ -1350,14 +1338,14 @@ impl LitKind { } } - /// Returns true if this literal has a suffix. + /// Returns `true` if this literal has a suffix. pub fn is_suffixed(&self) -> bool { !self.is_unsuffixed() } } -// NB: If you change this, you'll probably want to change the corresponding -// type structure in middle/ty.rs as well. +// N.B., If you change this, you'll probably want to change the corresponding +// type structure in `middle/ty.rs` as well. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct MutTy { pub ty: P<Ty>, @@ -1384,7 +1372,7 @@ pub struct TraitItem { pub generics: Generics, pub node: TraitItemKind, pub span: Span, - /// See `Item::tokens` for what this is + /// See `Item::tokens` for what this is. pub tokens: Option<TokenStream>, } @@ -1406,7 +1394,7 @@ pub struct ImplItem { pub generics: Generics, pub node: ImplItemKind, pub span: Span, - /// See `Item::tokens` for what this is + /// See `Item::tokens` for what this is. pub tokens: Option<TokenStream>, } @@ -1454,8 +1442,8 @@ impl IntTy { } pub fn val_to_string(&self, val: i128) -> String { - // cast to a u128 so we can correctly print INT128_MIN. All integral types - // are parsed as u128, so we wouldn't want to print an extra negative + // Cast to a `u128` so we can correctly print `INT128_MIN`. All integral types + // are parsed as `u128`, so we wouldn't want to print an extra negative // sign. format!("{}{}", val as u128, self.ty_to_string()) } @@ -1522,7 +1510,7 @@ impl fmt::Display for UintTy { } } -// Bind a type to an associated type: `A=Foo`. +// Bind a type to an associated type: `A = Foo`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct TypeBinding { pub id: NodeId, @@ -1552,27 +1540,27 @@ pub struct BareFnTy { pub decl: P<FnDecl>, } -/// The different kinds of types recognized by the compiler +/// The different kinds of types recognized by the compiler. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum TyKind { - /// A variable-length slice (`[T]`) + /// A variable-length slice (`[T]`). Slice(P<Ty>), - /// A fixed length array (`[T; n]`) + /// A fixed length array (`[T; n]`). Array(P<Ty>, AnonConst), - /// A raw pointer (`*const T` or `*mut T`) + /// A raw pointer (`*const T` or `*mut T`). Ptr(MutTy), - /// A reference (`&'a T` or `&'a mut T`) + /// A reference (`&'a T` or `&'a mut T`). Rptr(Option<Lifetime>, MutTy), - /// A bare function (e.g. `fn(usize) -> bool`) + /// A bare function (e.g., `fn(usize) -> bool`). BareFn(P<BareFnTy>), - /// The never type (`!`) + /// The never type (`!`). Never, - /// A tuple (`(A, B, C, D,...)`) + /// A tuple (`(A, B, C, D,...)`). Tup(Vec<P<Ty>>), /// A path (`module::module::...::Type`), optionally - /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`. + /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`. /// - /// Type parameters are stored in the Path itself + /// Type parameters are stored in the `Path` itself. Path(Option<QSelf>, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. @@ -1582,18 +1570,18 @@ pub enum TyKind { /// /// The `NodeId` exists to prevent lowering from having to /// generate `NodeId`s on the fly, which would complicate - /// the generation of `existential type` items significantly + /// the generation of `existential type` items significantly. ImplTrait(NodeId, GenericBounds), - /// No-op; kept solely so that we can pretty-print faithfully + /// No-op; kept solely so that we can pretty-print faithfully. Paren(P<Ty>), - /// Unused for now + /// Unused for now. Typeof(AnonConst), - /// TyKind::Infer means the type should be inferred instead of it having been + /// This means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, /// Inferred type of a `self` or `&self` argument in a method. ImplicitSelf, - // A macro in the type position. + /// A macro in the type position. Mac(Mac), /// Placeholder for a kind that has failed to be defined. Err, @@ -1626,7 +1614,7 @@ pub enum TraitObjectSyntax { /// Inline assembly dialect. /// -/// E.g. `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")` +/// E.g., `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum AsmDialect { Att, @@ -1635,7 +1623,7 @@ pub enum AsmDialect { /// Inline assembly. /// -/// E.g. `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")` +/// E.g., `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct InlineAsmOutput { pub constraint: Symbol, @@ -1646,7 +1634,7 @@ pub struct InlineAsmOutput { /// Inline assembly. /// -/// E.g. `asm!("NOP");` +/// E.g., `asm!("NOP");`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct InlineAsm { pub asm: Symbol, @@ -1662,7 +1650,7 @@ pub struct InlineAsm { /// An argument in a function header. /// -/// E.g. `bar: usize` as in `fn foo(bar: usize)` +/// E.g., `bar: usize` as in `fn foo(bar: usize)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Arg { pub ty: P<Ty>, @@ -1672,7 +1660,7 @@ pub struct Arg { /// Alternative representation for `Arg`s describing `self` parameter of methods. /// -/// E.g. `&mut self` as in `fn foo(&mut self)` +/// E.g., `&mut self` as in `fn foo(&mut self)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum SelfKind { /// `self`, `mut self` @@ -1688,7 +1676,7 @@ pub type ExplicitSelf = Spanned<SelfKind>; impl Arg { pub fn to_self(&self) -> Option<ExplicitSelf> { if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node { - if ident.name == keywords::SelfValue.name() { + if ident.name == keywords::SelfLower.name() { return match self.ty.node { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.node.is_implicit_self() => { @@ -1706,7 +1694,7 @@ impl Arg { pub fn is_self(&self) -> bool { if let PatKind::Ident(_, ident, _) = self.pat.node { - ident.name == keywords::SelfValue.name() + ident.name == keywords::SelfLower.name() } else { false } @@ -1751,7 +1739,7 @@ impl Arg { /// Header (not the body) of a function declaration. /// -/// E.g. `fn foo(bar: baz)` +/// E.g., `fn foo(bar: baz)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct FnDecl { pub inputs: Vec<Arg>, @@ -1798,7 +1786,8 @@ impl IsAsync { false } } - /// In case this is an `Async` return the `NodeId` for the generated impl Trait item + + /// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item. pub fn opt_return_id(self) -> Option<NodeId> { match self { IsAsync::Async { @@ -1855,11 +1844,10 @@ impl fmt::Debug for ImplPolarity { pub enum FunctionRetTy { /// Return type is not specified. /// - /// Functions default to `()` and - /// closures default to inference. Span points to where return - /// type would be inserted. + /// Functions default to `()` and closures default to inference. + /// Span points to where return type would be inserted. Default(Span), - /// Everything else + /// Everything else. Ty(P<Ty>), } @@ -1874,7 +1862,7 @@ impl FunctionRetTy { /// Module declaration. /// -/// E.g. `mod foo;` or `mod foo { .. }` +/// E.g., `mod foo;` or `mod foo { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. @@ -1882,22 +1870,22 @@ pub struct Mod { /// to the last token in the external file. pub inner: Span, pub items: Vec<P<Item>>, - /// For `mod foo;` inline is false, for `mod foo { .. }` it is true. + /// `true` for `mod foo { .. }`; `false` for `mod foo;`. pub inline: bool, } /// Foreign module declaration. /// -/// E.g. `extern { .. }` or `extern C { .. }` +/// E.g., `extern { .. }` or `extern C { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignMod { pub abi: Abi, pub items: Vec<ForeignItem>, } -/// Global inline assembly +/// Global inline assembly. /// -/// aka module-level assembly or file-scoped assembly +/// Also known as "module-level assembly" or "file-scoped assembly". #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub struct GlobalAsm { pub asm: Symbol, @@ -1914,7 +1902,7 @@ pub struct Variant_ { pub ident: Ident, pub attrs: Vec<Attribute>, pub data: VariantData, - /// Explicit discriminant, e.g. `Foo = 1` + /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option<AnonConst>, } @@ -1959,7 +1947,7 @@ impl UseTree { } } -/// Distinguishes between Attributes that decorate items and Attributes that +/// Distinguishes between `Attribute`s that decorate items and Attributes that /// are contained as statements within items. These two cases need to be /// distinguished for pretty-printing. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] @@ -1982,8 +1970,8 @@ impl Idx for AttrId { } } -/// Meta-data associated with an item -/// Doc-comments are promoted to attributes that have is_sugared_doc = true +/// Metadata associated with an item. +/// Doc-comments are promoted to attributes that have `is_sugared_doc = true`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Attribute { pub id: AttrId, @@ -1994,12 +1982,12 @@ pub struct Attribute { pub span: Span, } -/// TraitRef's appear in impls. +/// `TraitRef`s appear in impls. /// -/// resolve maps each TraitRef's ref_id to its defining trait; that's all -/// that the ref_id is for. The impl_id maps to the "self type" of this impl. -/// If this impl is an ItemKind::Impl, the impl_id is redundant (it could be the -/// same as the impl's node id). +/// Resolve maps each `TraitRef`'s `ref_id` to its defining trait; that's all +/// that the `ref_id` is for. The `impl_id` maps to the "self type" of this impl. +/// If this impl is an `ItemKind::Impl`, the `impl_id` is redundant (it could be the +/// same as the impl's node-id). #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct TraitRef { pub path: Path, @@ -2032,10 +2020,10 @@ impl PolyTraitRef { #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] pub enum CrateSugar { - /// Source is `pub(crate)` + /// Source is `pub(crate)`. PubCrate, - /// Source is (just) `crate` + /// Source is (just) `crate`. JustCrate, } @@ -2061,7 +2049,7 @@ impl VisibilityKind { /// Field of a struct. /// -/// E.g. `bar: usize` as in `struct Foo { bar: usize }` +/// E.g., `bar: usize` as in `struct Foo { bar: usize }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct StructField { pub span: Span, @@ -2087,15 +2075,15 @@ pub struct StructField { pub enum VariantData { /// Struct variant. /// - /// E.g. `Bar { .. }` as in `enum Foo { Bar { .. } }` + /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. Struct(Vec<StructField>, NodeId), /// Tuple variant. /// - /// E.g. `Bar(..)` as in `enum Foo { Bar(..) }` + /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. Tuple(Vec<StructField>, NodeId), /// Unit variant. /// - /// E.g. `Bar = ..` as in `enum Foo { Bar = .. }` + /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`. Unit(NodeId), } @@ -2134,9 +2122,9 @@ impl VariantData { } } -/// An item +/// An item. /// -/// The name might be a dummy name in case of anonymous items +/// The name might be a dummy name in case of anonymous items. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Item { pub ident: Ident, @@ -2156,10 +2144,10 @@ pub struct Item { pub tokens: Option<TokenStream>, } -/// A function header +/// A function header. /// -/// All the information between the visibility & the name of the function is -/// included in this struct (e.g. `async unsafe fn` or `const extern "C" fn`) +/// All the information between the visibility and the name of the function is +/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub struct FnHeader { pub unsafety: Unsafety, @@ -2183,65 +2171,65 @@ impl Default for FnHeader { pub enum ItemKind { /// An `extern crate` item, with optional *original* crate name if the crate was renamed. /// - /// E.g. `extern crate foo` or `extern crate foo_bar as foo` + /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. ExternCrate(Option<Name>), /// A use declaration (`use` or `pub use`) item. /// - /// E.g. `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;` + /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`. Use(P<UseTree>), /// A static item (`static` or `pub static`). /// - /// E.g. `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";` + /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. Static(P<Ty>, Mutability, P<Expr>), /// A constant item (`const` or `pub const`). /// - /// E.g. `const FOO: i32 = 42;` + /// E.g., `const FOO: i32 = 42;`. Const(P<Ty>, P<Expr>), /// A function declaration (`fn` or `pub fn`). /// - /// E.g. `fn foo(bar: usize) -> usize { .. }` + /// E.g., `fn foo(bar: usize) -> usize { .. }`. Fn(P<FnDecl>, FnHeader, Generics, P<Block>), /// A module declaration (`mod` or `pub mod`). /// - /// E.g. `mod foo;` or `mod foo { .. }` + /// E.g., `mod foo;` or `mod foo { .. }`. Mod(Mod), /// An external module (`extern` or `pub extern`). /// - /// E.g. `extern {}` or `extern "C" {}` + /// E.g., `extern {}` or `extern "C" {}`. ForeignMod(ForeignMod), - /// Module-level inline assembly (from `global_asm!()`) + /// Module-level inline assembly (from `global_asm!()`). GlobalAsm(P<GlobalAsm>), /// A type alias (`type` or `pub type`). /// - /// E.g. `type Foo = Bar<u8>;` + /// E.g., `type Foo = Bar<u8>;`. Ty(P<Ty>, Generics), /// An existential type declaration (`existential type`). /// - /// E.g. `existential type Foo: Bar + Boo;` + /// E.g., `existential type Foo: Bar + Boo;`. Existential(GenericBounds, Generics), /// An enum definition (`enum` or `pub enum`). /// - /// E.g. `enum Foo<A, B> { C<A>, D<B> }` + /// E.g., `enum Foo<A, B> { C<A>, D<B> }`. Enum(EnumDef, Generics), /// A struct definition (`struct` or `pub struct`). /// - /// E.g. `struct Foo<A> { x: A }` + /// E.g., `struct Foo<A> { x: A }`. Struct(VariantData, Generics), /// A union definition (`union` or `pub union`). /// - /// E.g. `union Foo<A, B> { x: A, y: B }` + /// E.g., `union Foo<A, B> { x: A, y: B }`. Union(VariantData, Generics), /// A Trait declaration (`trait` or `pub trait`). /// - /// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}` + /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`. Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>), /// Trait alias /// - /// E.g. `trait Foo = Bar + Quux;` + /// E.g., `trait Foo = Bar + Quux;`. TraitAlias(Generics, GenericBounds), /// An implementation. /// - /// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }` + /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`. Impl( Unsafety, ImplPolarity, @@ -2253,7 +2241,7 @@ pub enum ItemKind { ), /// A macro invocation. /// - /// E.g. `macro_rules! foo { .. }` or `foo!(..)` + /// E.g., `macro_rules! foo { .. }` or `foo!(..)`. Mac(Mac), /// A macro definition. @@ -2293,17 +2281,17 @@ pub struct ForeignItem { pub vis: Visibility, } -/// An item within an `extern` block +/// An item within an `extern` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { - /// A foreign function + /// A foreign function. Fn(P<FnDecl>, Generics), - /// A foreign static item (`static ext: u8`), with optional mutability - /// (the boolean is true when mutable) + /// A foreign static item (`static ext: u8`), with optional mutability. + /// (The boolean is `true` for mutable items). Static(P<Ty>, bool), - /// A foreign type + /// A foreign type. Ty, - /// A macro invocation + /// A macro invocation. Macro(Mac), } @@ -2323,7 +2311,7 @@ mod tests { use super::*; use serialize; - // are ASTs encodable? + // Are ASTs encodable? #[test] fn check_asts_encodable() { fn assert_encodable<T: serialize::Encodable>() {} diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 64876659477..73cbe49f43b 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -34,7 +34,7 @@ use parse::token::{self, Token}; use ptr::P; use symbol::Symbol; use ThinVec; -use tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; +use tokenstream::{TokenStream, TokenTree, DelimSpan}; use GLOBALS; use std::iter; @@ -96,7 +96,7 @@ impl NestedMetaItem { self.meta_item().map_or(false, |meta_item| meta_item.check_name(name)) } - /// Returns the name of the meta item, e.g. `foo` in `#[foo]`, + /// Returns the name of the meta item, e.g., `foo` in `#[foo]`, /// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem pub fn name(&self) -> Option<Name> { self.meta_item().and_then(|meta_item| Some(meta_item.name())) @@ -180,7 +180,7 @@ impl Attribute { } /// Returns the **last** segment of the name of this attribute. - /// E.g. `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`. + /// e.g., `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`. pub fn name(&self) -> Name { name_from_path(&self.path) } @@ -483,7 +483,7 @@ impl MetaItem { last_pos = segment.ident.span.hi(); } idents.push(self.node.tokens(self.span)); - TokenStream::concat(idents) + TokenStream::new(idents) } fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem> @@ -539,7 +539,7 @@ impl MetaItemKind { match *self { MetaItemKind::Word => TokenStream::empty(), MetaItemKind::NameValue(ref lit) => { - TokenStream::concat(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()]) + TokenStream::new(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()]) } MetaItemKind::List(ref list) => { let mut tokens = Vec::new(); @@ -549,10 +549,11 @@ impl MetaItemKind { } tokens.push(item.node.tokens()); } - TokenTree::Delimited(DelimSpan::from_single(span), Delimited { - delim: token::Paren, - tts: TokenStream::concat(tokens).into(), - }).into() + TokenTree::Delimited( + DelimSpan::from_single(span), + token::Paren, + TokenStream::new(tokens).into(), + ).into() } } } @@ -570,9 +571,9 @@ impl MetaItemKind { None }; } - Some(TokenTree::Delimited(_, ref delimited)) if delimited.delim == token::Paren => { + Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => { tokens.next(); - delimited.stream() + tts.stream() } _ => return Some(MetaItemKind::Word), }; @@ -803,7 +804,7 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) - for raw_attr in attrs { let mut parser = parse::new_parser_from_source_str( parse_sess, - FileName::CliCrateAttr, + FileName::cli_crate_attr_source_code(&raw_attr), raw_attr.clone(), ); diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index d8fb20d4250..41307175ade 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -328,7 +328,7 @@ impl<'a> StripUnconfigured<'a> { // Anything else is always required, and thus has to error out // in case of a cfg attr. // - // NB: This is intentionally not part of the fold_expr() function + // N.B., this is intentionally not part of the fold_expr() function // in order for fold_opt_expr() to be able to avoid this check if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { let msg = "removing an expression is not supported in this position"; @@ -421,7 +421,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> { } fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - // Don't configure interpolated AST (c.f. #34171). + // Don't configure interpolated AST (cf. issue #34171). // Interpolated AST will get configured once the surrounding tokens are parsed. mac } diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 1229db9b0e0..3b88767f0e8 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -141,6 +141,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, ]) } +#[allow(deprecated)] pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree]) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index bb927b62a18..b807a65f6ae 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -670,7 +670,7 @@ pub enum SyntaxExtension { /// An attribute-like procedural macro that derives a builtin trait. BuiltinDerive(BuiltinDeriveFn), - /// A declarative macro, e.g. `macro m() {}`. + /// A declarative macro, e.g., `macro m() {}`. DeclMacro { expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>, def_info: Option<(ast::NodeId, Span)>, @@ -732,17 +732,12 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension); pub trait Resolver { fn next_node_id(&mut self) -> ast::NodeId; fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; - fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>; - fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool; fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]); fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>); fn resolve_imports(&mut self); - // Resolves attribute and derive legacy macros from `#![plugin(..)]`. - fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: bool) - -> Option<Attribute>; fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>; @@ -770,16 +765,12 @@ pub struct DummyResolver; impl Resolver for DummyResolver { fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } - fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item } - fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false } fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, _derives: &[Mark]) {} fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {} fn resolve_imports(&mut self) {} - fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool) - -> Option<Attribute> { None } fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool) -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> { Err(Determinacy::Determined) @@ -915,7 +906,7 @@ impl<'a> ExtCtxt<'a> { /// `span_err` should be strongly preferred where-ever possible: /// this should *only* be used when: /// - /// - continuing has a high risk of flow-on errors (e.g. errors in + /// - continuing has a high risk of flow-on errors (e.g., errors in /// declaring a macro would cause all uses of that macro to /// complain about "undefined macro"), or /// - there is literally nothing else that can be done (however, @@ -1002,7 +993,7 @@ pub fn expr_to_spanned_string<'a>( expr }); - // we want to be able to handle e.g. `concat!("foo", "bar")` + // we want to be able to handle e.g., `concat!("foo", "bar")` let expr = cx.expander().fold_expr(expr); Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index cacec867cf1..5770f6bb8a2 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -318,9 +318,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { args: Vec<ast::GenericArg>, bindings: Vec<ast::TypeBinding> ) -> ast::Path { + assert!(!idents.is_empty()); + let add_root = global && !idents[0].is_path_segment_keyword(); + let mut segments = Vec::with_capacity(idents.len() + add_root as usize); + if add_root { + segments.push(ast::PathSegment::path_root(span)); + } let last_ident = idents.pop().unwrap(); - let mut segments: Vec<ast::PathSegment> = vec![]; - segments.extend(idents.into_iter().map(|ident| { ast::PathSegment::from_ident(ident.with_span_pos(span)) })); @@ -334,13 +338,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, args, }); - let mut path = ast::Path { span, segments }; - if global { - if let Some(seg) = path.make_root() { - path.segments.insert(0, seg); - } - } - path + ast::Path { span, segments } } /// Constructs a qualified path. @@ -625,7 +623,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_path(self.path_ident(span, id)) } fn expr_self(&self, span: Span) -> P<ast::Expr> { - self.expr_ident(span, keywords::SelfValue.ident()) + self.expr_ident(span, keywords::SelfLower.ident()) } fn expr_binary(&self, sp: Span, op: ast::BinOpKind, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 68a96293891..57ccc3e9817 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{self, Block, Ident, NodeId, PatKind, Path}; +use ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path}; use ast::{MacStmtStyle, StmtKind, ItemKind}; use attr::{self, HasAttrs}; use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan}; @@ -34,8 +34,8 @@ use tokenstream::{TokenStream, TokenTree}; use visit::{self, Visitor}; use rustc_data_structures::fx::FxHashMap; -use std::fs::File; -use std::io::Read; +use std::fs; +use std::io::ErrorKind; use std::{iter, mem}; use std::rc::Rc; use std::path::PathBuf; @@ -203,10 +203,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { if i != 0 { path_str.push_str("::"); } - - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() - { + if segment.ident.name != keywords::PathRoot.name() { path_str.push_str(&segment.ident.as_str()) } } @@ -622,9 +619,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream { let mut trees = tokens.trees(); match trees.next() { - Some(TokenTree::Delimited(_, delim)) => { + Some(TokenTree::Delimited(_, _, tts)) => { if trees.next().is_none() { - return delim.tts.into() + return tts.into() } } Some(TokenTree::Token(..)) => {} @@ -1134,12 +1131,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); item = item.map_attrs(|mut attrs| { - if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, - true) { - attr = Some(legacy_attr_invoc); - return attrs; - } - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); traits = collect_derives(&mut self.cx, &mut attrs); attrs @@ -1156,12 +1147,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let (mut attr, mut after_derive) = (None, false); item = item.map_attrs(|mut attrs| { - if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, - false) { - attr = Some(legacy_attr_invoc); - return attrs; - } - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); attrs }); @@ -1363,7 +1348,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { module.mod_path.push(item.ident); // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`). - // In the non-inline case, `inner` is never the dummy span (c.f. `parse_item_mod`). + // In the non-inline case, `inner` is never the dummy span (cf. `parse_item_mod`). // Thus, if `inner` is the dummy span, we know the module is inline. let inline_module = item.span.contains(inner) || inner.is_dummy(); @@ -1519,20 +1504,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { return noop_fold_attribute(at, self); } - let mut buf = vec![]; let filename = self.cx.root_path.join(file.to_string()); - - match File::open(&filename).and_then(|mut f| f.read_to_end(&mut buf)) { - Ok(..) => {} - Err(e) => { - self.cx.span_err(at.span, - &format!("couldn't read {}: {}", - filename.display(), - e)); - } - } - - match String::from_utf8(buf) { + match fs::read_to_string(&filename) { Ok(src) => { let src_interned = Symbol::intern(&src); @@ -1542,25 +1515,82 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let include_info = vec![ dummy_spanned(ast::NestedMetaItemKind::MetaItem( - attr::mk_name_value_item_str(Ident::from_str("file"), - dummy_spanned(file)))), + attr::mk_name_value_item_str( + Ident::from_str("file"), + dummy_spanned(file), + ), + )), dummy_spanned(ast::NestedMetaItemKind::MetaItem( - attr::mk_name_value_item_str(Ident::from_str("contents"), - dummy_spanned(src_interned)))), + attr::mk_name_value_item_str( + Ident::from_str("contents"), + dummy_spanned(src_interned), + ), + )), ]; let include_ident = Ident::from_str("include"); let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info); items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item))); } - Err(_) => { - self.cx.span_err(at.span, - &format!("{} wasn't a utf-8 file", - filename.display())); + Err(e) => { + let lit = it + .meta_item() + .and_then(|item| item.name_value_literal()) + .unwrap(); + + if e.kind() == ErrorKind::InvalidData { + self.cx + .struct_span_err( + lit.span, + &format!("{} wasn't a utf-8 file", filename.display()), + ) + .span_label(lit.span, "contains invalid utf-8") + .emit(); + } else { + let mut err = self.cx.struct_span_err( + lit.span, + &format!("couldn't read {}: {}", filename.display(), e), + ); + err.span_label(lit.span, "couldn't read file"); + + if e.kind() == ErrorKind::NotFound { + err.help("external doc paths are relative to the crate root"); + } + + err.emit(); + } } } } else { - items.push(noop_fold_meta_list_item(it, self)); + let mut err = self.cx.struct_span_err( + it.span, + &format!("expected path to external documentation"), + ); + + // Check if the user erroneously used `doc(include(...))` syntax. + let literal = it.meta_item_list().and_then(|list| { + if list.len() == 1 { + list[0].literal().map(|literal| &literal.node) + } else { + None + } + }); + + let (path, applicability) = match &literal { + Some(LitKind::Str(path, ..)) => { + (path.to_string(), Applicability::MachineApplicable) + } + _ => (String::from("<path>"), Applicability::HasPlaceholders), + }; + + err.span_suggestion_with_applicability( + it.span, + "provide a file path with `=`", + format!("include = \"{}\"", path), + applicability, + ); + + err.emit(); } } @@ -1623,7 +1653,6 @@ impl<'feat> ExpansionConfig<'feat> { } feature_tests! { - fn enable_quotes = quote, fn enable_asm = asm, fn enable_custom_test_frameworks = custom_test_frameworks, fn enable_global_asm = global_asm, @@ -1631,7 +1660,6 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_concat_idents = concat_idents, fn enable_trace_macros = trace_macros, fn enable_allow_internal_unstable = allow_internal_unstable, - fn enable_custom_derive = custom_derive, fn enable_format_args_nl = format_args_nl, fn macros_in_extern_enabled = macros_in_extern, fn proc_macro_hygiene = proc_macro_hygiene, diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 69ed318b049..5820b49ab62 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -36,7 +36,7 @@ pub mod rt { use symbol::Symbol; use ThinVec; - use tokenstream::{self, DelimSpan, TokenTree, TokenStream}; + use tokenstream::{DelimSpan, TokenTree, TokenStream}; pub use parse::new_parser_from_tts; pub use syntax_pos::{BytePos, Span, DUMMY_SP, FileName}; @@ -246,9 +246,9 @@ pub mod rt { inner.push(self.tokens.clone()); let delim_span = DelimSpan::from_single(self.span); - r.push(TokenTree::Delimited(delim_span, tokenstream::Delimited { - delim: token::Bracket, tts: TokenStream::concat(inner).into() - })); + r.push(TokenTree::Delimited( + delim_span, token::Bracket, TokenStream::new(inner).into() + )); r } } @@ -262,10 +262,9 @@ pub mod rt { impl ToTokens for () { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> { - vec![TokenTree::Delimited(DelimSpan::dummy(), tokenstream::Delimited { - delim: token::Paren, - tts: TokenStream::empty().into(), - })] + vec![ + TokenTree::Delimited(DelimSpan::dummy(), token::Paren, TokenStream::empty().into()) + ] } } @@ -353,27 +352,27 @@ pub mod rt { impl<'a> ExtParseUtils for ExtCtxt<'a> { fn parse_item(&self, s: String) -> P<ast::Item> { panictry!(parse::parse_item_from_source_str( - FileName::QuoteExpansion, + FileName::quote_expansion_source_code(&s), s, self.parse_sess())).expect("parse error") } fn parse_stmt(&self, s: String) -> ast::Stmt { panictry!(parse::parse_stmt_from_source_str( - FileName::QuoteExpansion, + FileName::quote_expansion_source_code(&s), s, self.parse_sess())).expect("parse error") } fn parse_expr(&self, s: String) -> P<ast::Expr> { panictry!(parse::parse_expr_from_source_str( - FileName::QuoteExpansion, + FileName::quote_expansion_source_code(&s), s, self.parse_sess())) } fn parse_tts(&self, s: String) -> Vec<TokenTree> { - let source_name = FileName::QuoteExpansion; + let source_name = FileName::quote_expansion_source_code(&s); parse::parse_stream_from_source_str(source_name, s, self.parse_sess(), None) .into_trees().collect() } @@ -382,8 +381,6 @@ pub mod rt { // Replaces `Token::OpenDelim .. Token::CloseDelim` with `TokenTree::Delimited(..)`. pub fn unflatten(tts: Vec<TokenTree>) -> Vec<TokenTree> { - use tokenstream::Delimited; - let mut results = Vec::new(); let mut result = Vec::new(); let mut open_span = DUMMY_SP; @@ -395,10 +392,11 @@ pub fn unflatten(tts: Vec<TokenTree>) -> Vec<TokenTree> { } TokenTree::Token(span, token::CloseDelim(delim)) => { let delim_span = DelimSpan::from_pair(open_span, span); - let tree = TokenTree::Delimited(delim_span, Delimited { + let tree = TokenTree::Delimited( + delim_span, delim, - tts: result.into_iter().map(TokenStream::from).collect::<TokenStream>().into(), - }); + result.into_iter().map(TokenStream::from).collect::<TokenStream>().into(), + ); result = results.pop().unwrap(); result.push(tree); } @@ -758,10 +756,10 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, quoted: bool) -> Vec<ast::Stmt vec![e_tok]); vec![cx.stmt_expr(e_push)] }, - TokenTree::Delimited(span, ref delimed) => { - let mut stmts = statements_mk_tt(cx, &delimed.open_tt(span.open), false); - stmts.extend(statements_mk_tts(cx, delimed.stream())); - stmts.extend(statements_mk_tt(cx, &delimed.close_tt(span.close), false)); + TokenTree::Delimited(span, delim, ref tts) => { + let mut stmts = statements_mk_tt(cx, &TokenTree::open_tt(span.open, delim), false); + stmts.extend(statements_mk_tts(cx, tts.stream())); + stmts.extend(statements_mk_tt(cx, &TokenTree::close_tt(span.close, delim), false)); stmts } } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index e1ba8897a47..ec27ceeb74c 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -21,8 +21,8 @@ use smallvec::SmallVec; use symbol::Symbol; use tokenstream; -use std::fs::File; -use std::io::prelude::*; +use std::fs; +use std::io::ErrorKind; use std::path::PathBuf; use rustc_data_structures::sync::Lrc; @@ -137,18 +137,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, file); - let mut bytes = Vec::new(); - match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { - Ok(..) => {} - Err(e) => { - cx.span_err(sp, - &format!("couldn't read {}: {}", - file.display(), - e)); - return DummyResult::expr(sp); - } - }; - match String::from_utf8(bytes) { + match fs::read_to_string(&file) { Ok(src) => { let interned_src = Symbol::intern(&src); @@ -157,11 +146,13 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT cx.source_map().new_source_file(file.into(), src); base::MacEager::expr(cx.expr_str(sp, interned_src)) + }, + Err(ref e) if e.kind() == ErrorKind::InvalidData => { + cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); + DummyResult::expr(sp) } - Err(_) => { - cx.span_err(sp, - &format!("{} wasn't a utf-8 file", - file.display())); + Err(e) => { + cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); DummyResult::expr(sp) } } @@ -174,19 +165,23 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke None => return DummyResult::expr(sp) }; let file = res_rel_file(cx, sp, file); - let mut bytes = Vec::new(); - match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { - Err(e) => { - cx.span_err(sp, - &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) - } - Ok(..) => { - // Add this input file to the code map to make it available as - // dependency information, but don't enter it's contents - cx.source_map().new_source_file(file.into(), String::new()); + match fs::read(&file) { + Ok(bytes) => { + // Add the contents to the source map if it contains UTF-8. + let (contents, bytes) = match String::from_utf8(bytes) { + Ok(s) => { + let bytes = s.as_bytes().to_owned(); + (s, bytes) + }, + Err(e) => (String::new(), e.into_bytes()), + }; + cx.source_map().new_source_file(file.into(), contents); base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))) + }, + Err(e) => { + cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); + DummyResult::expr(sp) } } } @@ -201,6 +196,7 @@ fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: String) -> PathBuf let callsite = sp.source_callsite(); let mut path = match cx.source_map().span_to_unmapped_path(callsite) { FileName::Real(path) => path, + FileName::DocTest(path, _) => path, other => panic!("cannot resolve relative path in non-file source `{}`", other), }; path.pop(); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 8fd9590a664..26348d5ec82 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -214,10 +214,10 @@ struct MatcherPos<'root, 'tt: 'root> { up: Option<MatcherPosHandle<'root, 'tt>>, /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from - /// a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc + /// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc /// comment... /// - /// When matching against matchers with nested delimited submatchers (e.g. `pat ( pat ( .. ) + /// When matching against matchers with nested delimited submatchers (e.g., `pat ( pat ( .. ) /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does /// that where the bottom of the stack is the outermost matcher. /// Also, throughout the comments, this "descent" is often referred to as "unzipping"... @@ -309,7 +309,7 @@ fn create_matches(len: usize) -> Box<[Rc<NamedMatchVec>]> { vec![] } else { let empty_matches = Rc::new(SmallVec::new()); - vec![empty_matches.clone(); len] + vec![empty_matches; len] }.into_boxed_slice() } @@ -373,7 +373,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>( ms: &[TokenTree], mut res: I, ) -> NamedParseResult { - // Recursively descend into each type of matcher (e.g. sequences, delimited, metavars) and make + // Recursively descend into each type of matcher (e.g., sequences, delimited, metavars) and make // sure that each metavar has _exactly one_ binding. If a metavar does not have exactly one // binding, then there is an error. If it does, then we insert the binding into the // `NamedParseResult`. @@ -895,7 +895,7 @@ fn may_begin_with(name: &str, token: &Token) -> bool { /// /// - `p`: the "black-box" parser to use /// - `sp`: the `Span` we want to parse -/// - `name`: the name of the metavar _matcher_ we want to match (e.g. `tt`, `ident`, `block`, +/// - `name`: the name of the metavar _matcher_ we want to match (e.g., `tt`, `ident`, `block`, /// etc...) /// /// # Returns diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index ff622b0c18f..30322ff523d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -77,9 +77,9 @@ impl<'a> ParserAnyMacro<'a> { e })); - // We allow semicolons at the end of expressions -- e.g. the semicolon in + // We allow semicolons at the end of expressions -- e.g., the semicolon in // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`, - // but `m!()` is allowed in expression positions (c.f. issue #34706). + // but `m!()` is allowed in expression positions (cf. issue #34706). if kind == AstFragmentKind::Expr && parser.token == token::Semi { parser.bump(); } @@ -482,15 +482,15 @@ fn check_matcher(sess: &ParseSess, err == sess.span_diagnostic.err_count() } -// The FirstSets for a matcher is a mapping from subsequences in the +// `The FirstSets` for a matcher is a mapping from subsequences in the // matcher to the FIRST set for that subsequence. // // This mapping is partially precomputed via a backwards scan over the // token trees of the matcher, which provides a mapping from each -// repetition sequence to its FIRST set. +// repetition sequence to its *first* set. // -// (Hypothetically sequences should be uniquely identifiable via their -// spans, though perhaps that is false e.g. for macro-generated macros +// (Hypothetically, sequences should be uniquely identifiable via their +// spans, though perhaps that is false, e.g., for macro-generated macros // that do not try to inject artificial span information. My plan is // to try to catch such cases ahead of time and not include them in // the precomputed mapping.) diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index edc431be369..b142f09cdbc 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -93,9 +93,9 @@ pub enum TokenTree { Delimited(DelimSpan, Lrc<Delimited>), /// A kleene-style repetition sequence Sequence(DelimSpan, Lrc<SequenceRepetition>), - /// E.g. `$var` + /// e.g., `$var` MetaVar(Span, ast::Ident), - /// E.g. `$var:expr`. This is only used in the left hand side of MBE macros. + /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros. MetaVarDecl( Span, ast::Ident, /* name to bind */ @@ -199,7 +199,7 @@ pub fn parse( let mut trees = input.trees().peekable(); while let Some(tree) = trees.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually - // parse out the matcher (i.e. in `$id:ident` this would parse the `:` and `ident`). + // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). let tree = parse_tree( tree, &mut trees, @@ -281,16 +281,16 @@ where tokenstream::TokenTree::Token(span, token::Dollar) => match trees.next() { // `tree` is followed by a delimited set of token trees. This indicates the beginning // of a repetition sequence in the macro (e.g. `$(pat)*`). - Some(tokenstream::TokenTree::Delimited(span, delimited)) => { + Some(tokenstream::TokenTree::Delimited(span, delim, tts)) => { // Must have `(` not `{` or `[` - if delimited.delim != token::Paren { - let tok = pprust::token_to_string(&token::OpenDelim(delimited.delim)); + if delim != token::Paren { + let tok = pprust::token_to_string(&token::OpenDelim(delim)); let msg = format!("expected `(`, found `{}`", tok); sess.span_diagnostic.span_err(span.entire(), &msg); } // Parse the contents of the sequence itself let sequence = parse( - delimited.tts.into(), + tts.into(), expect_matchers, sess, features, @@ -309,7 +309,7 @@ where edition, macro_node_id, ); - // Count the number of captured "names" (i.e. named metavars) + // Count the number of captured "names" (i.e., named metavars) let name_captures = macro_parser::count_names(&sequence); TokenTree::Sequence( span, @@ -352,14 +352,14 @@ where // `tree` is an arbitrary token. Keep it. tokenstream::TokenTree::Token(span, tok) => TokenTree::Token(span, tok), - // `tree` is the beginning of a delimited set of tokens (e.g. `(` or `{`). We need to + // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to // descend into the delimited set and further parse it. - tokenstream::TokenTree::Delimited(span, delimited) => TokenTree::Delimited( + tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited( span, Lrc::new(Delimited { - delim: delimited.delim, + delim: delim, tts: parse( - delimited.tts.into(), + tts.into(), expect_matchers, sess, features, @@ -444,7 +444,6 @@ where macro_node_id, ), Edition::Edition2018 => parse_sep_and_kleene_op_2018(input, span, sess, features, attrs), - _ => unimplemented!(), } } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 3d897d17e0b..a63abd40495 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -17,7 +17,7 @@ use fold::noop_fold_tt; use parse::token::{self, Token, NtTT}; use smallvec::SmallVec; use syntax_pos::DUMMY_SP; -use tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; +use tokenstream::{TokenStream, TokenTree, DelimSpan}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -103,12 +103,13 @@ pub fn transcribe(cx: &ExtCtxt, } Frame::Delimited { forest, span, .. } => { if result_stack.is_empty() { - return TokenStream::concat(result); + return TokenStream::new(result); } - let tree = TokenTree::Delimited(span, Delimited { - delim: forest.delim, - tts: TokenStream::concat(result).into(), - }); + let tree = TokenTree::Delimited( + span, + forest.delim, + TokenStream::new(result).into(), + ); result = result_stack.pop().unwrap(); result.push(tree.into()); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index fac7ff2bf34..941a3a288da 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Feature gating +//! # Feature gating //! //! This module implements the gating necessary for preventing certain compiler //! features from being used by default. This module will crawl a pre-expanded @@ -53,8 +53,7 @@ macro_rules! declare_features { /// Represents active features that are currently being implemented or /// currently being considered for addition/removal. const ACTIVE_FEATURES: - &'static [(&'static str, &'static str, Option<u32>, - Option<Edition>, fn(&mut Features, Span))] = + &[(&str, &str, Option<u32>, Option<Edition>, fn(&mut Features, Span))] = &[$((stringify!($feature), $ver, $issue, $edition, set!($feature))),+]; /// A set of features to be used by later passes. @@ -106,7 +105,7 @@ macro_rules! declare_features { } } -// If you change this, please modify src/doc/unstable-book as well. +// If you change this, please modify `src/doc/unstable-book` as well. // // Don't ever remove anything from this list; set them to 'Removed'. // @@ -114,7 +113,7 @@ macro_rules! declare_features { // was set. This is most important for knowing when a particular feature became // stable (active). // -// NB: tools/tidy/src/features.rs parses this information directly out of the +// N.B., `tools/tidy/src/features.rs` parses this information directly out of the // source, so take care when modifying it. declare_features! ( @@ -153,66 +152,61 @@ declare_features! ( (active, panic_runtime, "1.10.0", Some(32837), None), (active, needs_panic_runtime, "1.10.0", Some(32837), None), - // OIBIT specific features + // Features specific to OIBIT (auto traits) (active, optin_builtin_traits, "1.0.0", Some(13231), None), - // Allows use of #[staged_api] + // Allows `#[staged_api]`. // // rustc internal (active, staged_api, "1.0.0", None, None), - // Allows using #![no_core] + // Allows `#![no_core]`. (active, no_core, "1.3.0", Some(29639), None), - // Allows using `box` in patterns; RFC 469 + // Allows the use of `box` in patterns (RFC 469). (active, box_patterns, "1.0.0", Some(29641), None), - // Allows using the unsafe_destructor_blind_to_params attribute; - // RFC 1238 + // Allows the use of the `unsafe_destructor_blind_to_params` attribute (RFC 1238). (active, dropck_parametricity, "1.3.0", Some(28498), None), - // Allows using the may_dangle attribute; RFC 1327 + // Allows using the `may_dangle` attribute (RFC 1327). (active, dropck_eyepatch, "1.10.0", Some(34761), None), - // Allows the use of custom attributes; RFC 572 + // Allows the use of custom attributes (RFC 572). (active, custom_attribute, "1.0.0", Some(29642), None), - // Allows the use of #[derive(Anything)] as sugar for - // #[derive_Anything]. - (active, custom_derive, "1.0.0", Some(29644), None), - - // Allows the use of rustc_* attributes; RFC 572 + // Allows the use of `rustc_*` attributes (RFC 572). (active, rustc_attrs, "1.0.0", Some(29642), None), - // Allows the use of non lexical lifetimes; RFC 2094 + // Allows the use of non lexical lifetimes (RFC 2094). (active, nll, "1.0.0", Some(43234), None), - // Allows the use of #[allow_internal_unstable]. This is an - // attribute on macro_rules! and can't use the attribute handling + // Allows the use of `#[allow_internal_unstable]`. This is an + // attribute on `macro_rules!` and can't use the attribute handling // below (it has to be checked before expansion possibly makes // macros disappear). // // rustc internal (active, allow_internal_unstable, "1.0.0", None, None), - // Allows the use of #[allow_internal_unsafe]. This is an - // attribute on macro_rules! and can't use the attribute handling + // Allows the use of `#[allow_internal_unsafe]`. This is an + // attribute on `macro_rules!` and can't use the attribute handling // below (it has to be checked before expansion possibly makes // macros disappear). // // rustc internal (active, allow_internal_unsafe, "1.0.0", None, None), - // #23121. Array patterns have some hazards yet. + // Allows the use of slice patterns (issue #23121). (active, slice_patterns, "1.0.0", Some(23121), None), - // Allows the definition of `const fn` functions with some advanced features. + // Allows the definition of `const` functions with some advanced features. (active, const_fn, "1.2.0", Some(24111), None), - // Allows let bindings and destructuring in `const fn` functions and constants. + // Allows let bindings and destructuring in `const` functions and constants. (active, const_let, "1.22.1", Some(48821), None), - // Allows accessing fields of unions inside const fn. + // Allows accessing fields of unions inside `const` functions. (active, const_fn_union, "1.27.0", Some(51909), None), // Allows casting raw pointers to `usize` during const eval. @@ -227,10 +221,10 @@ declare_features! ( // Allows comparing raw pointers during const eval. (active, const_compare_raw_pointers, "1.27.0", Some(53020), None), - // Allows panicking during const eval (produces compile-time errors) + // Allows panicking during const eval (producing compile-time errors). (active, const_panic, "1.30.0", Some(51999), None), - // Allows using #[prelude_import] on glob `use` items. + // Allows using `#[prelude_import]` on glob `use` items. // // rustc internal (active, prelude_import, "1.2.0", None, None), @@ -238,117 +232,121 @@ declare_features! ( // Allows default type parameters to influence type inference. (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - // Allows associated type defaults + // Allows associated type defaults. (active, associated_type_defaults, "1.2.0", Some(29661), None), - // Allows `repr(simd)`, and importing the various simd intrinsics + // Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), - // Allows `extern "platform-intrinsic" { ... }` + // Allows `extern "platform-intrinsic" { ... }`. (active, platform_intrinsics, "1.4.0", Some(27731), None), - // Allows `#[unwind(..)]` + // Allows `#[unwind(..)]`. + // // rustc internal for rust runtime (active, unwind_attributes, "1.4.0", None, None), // Allows the use of `#[naked]` on functions. (active, naked_functions, "1.9.0", Some(32408), None), - // Allows `#[no_debug]` + // Allows `#[no_debug]`. (active, no_debug, "1.5.0", Some(29721), None), - // Allows `#[omit_gdb_pretty_printer_section]` + // Allows `#[omit_gdb_pretty_printer_section]`. // // rustc internal (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - // Allows cfg(target_vendor = "..."). + // Allows `cfg(target_vendor = "...")`. (active, cfg_target_vendor, "1.5.0", Some(29718), None), - // Allow attributes on expressions and non-item statements + // Allows attributes on expressions and non-item statements. (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - // allow using type ascription in expressions + // Allows the use of type ascription in expressions. (active, type_ascription, "1.6.0", Some(23416), None), - // Allows cfg(target_thread_local) + // Allows `cfg(target_thread_local)`. (active, cfg_target_thread_local, "1.7.0", Some(29594), None), // rustc internal (active, abi_vectorcall, "1.7.0", None, None), - // X..Y patterns + // Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), // impl specialization (RFC 1210) (active, specialization, "1.7.0", Some(31844), None), - // Allows cfg(target_has_atomic = "..."). + // Allows `cfg(target_has_atomic = "...")`. (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - // The `!` type. Does not imply exhaustive_patterns (below) any more. + // The `!` type. Does not imply 'exhaustive_patterns' (below) any more. (active, never_type, "1.13.0", Some(35121), None), - // Allows exhaustive pattern matching on types that contain uninhabited types + // Allows exhaustive pattern matching on types that contain uninhabited types. (active, exhaustive_patterns, "1.13.0", Some(51085), None), - // Allows untagged unions `union U { ... }` + // Allows untagged unions `union U { ... }`. (active, untagged_unions, "1.13.0", Some(32836), None), - // Used to identify the `compiler_builtins` crate - // rustc internal + // Used to identify the `compiler_builtins` crate. + // + // rustc internal. (active, compiler_builtins, "1.13.0", None, None), - // Allows #[link(..., cfg(..))] + // Allows `#[link(..., cfg(..))]`. (active, link_cfg, "1.14.0", Some(37406), None), - // `extern "ptx-*" fn()` + // Allows `extern "ptx-*" fn()`. (active, abi_ptx, "1.15.0", Some(38788), None), - // The `repr(i128)` annotation for enums + // The `repr(i128)` annotation for enums. (active, repr128, "1.16.0", Some(35118), None), - // The `unadjusted` ABI. Perma unstable. + // The `unadjusted` ABI; perma-unstable. + // // rustc internal (active, abi_unadjusted, "1.16.0", None, None), // Declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412), None), - // Allows #[link(kind="static-nobundle"...)] + // Allows `#[link(kind="static-nobundle"...)]`. (active, static_nobundle, "1.16.0", Some(37403), None), - // `extern "msp430-interrupt" fn()` + // Allows `extern "msp430-interrupt" fn()`. (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - // Used to identify crates that contain sanitizer runtimes + // Used to identify crates that contain sanitizer runtimes. + // // rustc internal (active, sanitizer_runtime, "1.17.0", None, None), - // Used to identify crates that contain the profiler runtime + // Used to identify crates that contain the profiler runtime. // // rustc internal (active, profiler_runtime, "1.18.0", None, None), - // `extern "x86-interrupt" fn()` + // Allows `extern "x86-interrupt" fn()`. (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - // Allows the `try {...}` expression + // Allows the `try {...}` expression. (active, try_blocks, "1.29.0", Some(31436), None), - // Allows module-level inline assembly by way of global_asm!() + // Allows module-level inline assembly by way of `global_asm!()`. (active, global_asm, "1.18.0", Some(35119), None), - // Allows overlapping impls of marker traits + // Allows overlapping impls of marker traits. (active, overlapping_marker_traits, "1.18.0", Some(29864), None), - // Trait attribute to allow overlapping impls + // Trait attribute to allow overlapping impls. (active, marker_trait_attr, "1.30.0", Some(29864), None), // rustc internal (active, abi_thiscall, "1.19.0", None, None), - // Allows a test to fail without failing the whole suite + // Allows a test to fail without failing the whole suite. (active, allow_fail, "1.19.0", Some(46488), None), // Allows unsized tuple coercion. @@ -363,28 +361,28 @@ declare_features! ( // rustc internal (active, allocator_internals, "1.20.0", None, None), - // #[doc(cfg(...))] + // `#[doc(cfg(...))]` (active, doc_cfg, "1.21.0", Some(43781), None), - // #[doc(masked)] + // `#[doc(masked)]` (active, doc_masked, "1.21.0", Some(44027), None), - // #[doc(spotlight)] + // `#[doc(spotlight)]` (active, doc_spotlight, "1.22.0", Some(45040), None), - // #[doc(include="some-file")] + // `#[doc(include = "some-file")]` (active, external_doc, "1.22.0", Some(44732), None), - // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) + // Future-proofing enums/structs with `#[non_exhaustive]` attribute (RFC 2008). (active, non_exhaustive, "1.22.0", Some(44109), None), - // `crate` as visibility modifier, synonymous to `pub(crate)` + // Adds `crate` as visibility modifier, synonymous with `pub(crate)`. (active, crate_visibility_modifier, "1.23.0", Some(53120), None), // extern types (active, extern_types, "1.23.0", Some(43467), None), - // Allows trait methods with arbitrary self types + // Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), - // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) + // In-band lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). (active, in_band_lifetimes, "1.23.0", Some(44524), None), // Generic associated types (RFC 1598) @@ -393,25 +391,19 @@ declare_features! ( // `extern` in paths (active, extern_in_paths, "1.23.0", Some(55600), None), - // Infer static outlives requirements; RFC 2093 + // Infer static outlives requirements (RFC 2093). (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - // Multiple patterns with `|` in `if let` and `while let` + // Multiple patterns with `|` in `if let` and `while let`. (active, if_while_or_patterns, "1.26.0", Some(48215), None), - // Allows `#[repr(packed)]` attribute on structs - (active, repr_packed, "1.26.0", Some(33158), None), - - // `use path as _;` and `extern crate c as _;` - (active, underscore_imports, "1.26.0", Some(48216), None), - - // Allows macro invocations in `extern {}` blocks + // Allows macro invocations in `extern {}` blocks. (active, macros_in_extern, "1.27.0", Some(49476), None), // `existential type` (active, existential_type, "1.28.0", Some(34511), None), - // unstable #[target_feature] directives + // unstable `#[target_feature]` directives (active, arm_target_feature, "1.27.0", Some(44839), None), (active, aarch64_target_feature, "1.27.0", Some(44839), None), (active, hexagon_target_feature, "1.27.0", Some(44839), None), @@ -422,69 +414,71 @@ declare_features! ( (active, sse4a_target_feature, "1.27.0", Some(44839), None), (active, tbm_target_feature, "1.27.0", Some(44839), None), (active, wasm_target_feature, "1.30.0", Some(44839), None), + (active, adx_target_feature, "1.32.0", Some(44839), None), + (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), // Allows macro invocations on modules expressions and statements and // procedural macros to expand to non-items. (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - // #[doc(alias = "...")] + // `#[doc(alias = "...")]` (active, doc_alias, "1.27.0", Some(50146), None), - // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) + // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None), - // 'a: { break 'a; } + // `'a: { break 'a; }` (active, label_break_value, "1.28.0", Some(48594), None), - // Integer match exhaustiveness checking - (active, exhaustive_integer_patterns, "1.30.0", Some(50907), None), + // Exhaustive pattern matching on `usize` and `isize`. + (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - // #[doc(keyword = "...")] + // `#[doc(keyword = "...")]` (active, doc_keyword, "1.28.0", Some(51315), None), - // Allows async and await syntax + // Allows async and await syntax. (active, async_await, "1.28.0", Some(50547), None), - // #[alloc_error_handler] + // `#[alloc_error_handler]` (active, alloc_error_handler, "1.29.0", Some(51540), None), (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - // Perma-unstable; added for testing E0705 + // Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", Some(0), Some(Edition::Edition2018)), - // Support for arbitrary delimited token streams in non-macro attributes + // support for arbitrary delimited token streams in non-macro attributes (active, unrestricted_attribute_tokens, "1.30.0", Some(55208), None), - // Allows `use x::y;` to resolve through `self::x`, not just `::x` + // Allows `use x::y;` to resolve through `self::x`, not just `::x`. (active, uniform_paths, "1.30.0", Some(53130), None), - // Allows unsized rvalues at arguments and parameters + // Allows unsized rvalues at arguments and parameters. (active, unsized_locals, "1.30.0", Some(48055), None), - // #![test_runner] - // #[test_case] + // `#![test_runner]` + // `#[test_case]` (active, custom_test_frameworks, "1.30.0", Some(50297), None), - // Non-builtin attributes in inner attribute position + // non-builtin attributes in inner attribute position (active, custom_inner_attributes, "1.30.0", Some(54726), None), - // allow mixing of bind-by-move in patterns and references to + // Allow mixing of bind-by-move in patterns and references to // those identifiers in guards, *if* we are using MIR-borrowck - // (aka NLL). Essentially this means you need to be on - // edition:2018 or later. + // (aka NLL). Essentially this means you need to be using the + // 2018 edition or later. (active, bind_by_move_pattern_guards, "1.30.0", Some(15287), None), - // Allows `impl Trait` in bindings (`let`, `const`, `static`) + // Allows `impl Trait` in bindings (`let`, `const`, `static`). (active, impl_trait_in_bindings, "1.30.0", Some(34511), None), - // #[cfg_attr(predicate, multiple, attributes, here)] + // `#[cfg_attr(predicate, multiple, attributes, here)]` (active, cfg_attr_multi, "1.31.0", Some(54881), None), - // Allows `const _: TYPE = VALUE` + // Allows `const _: TYPE = VALUE`. (active, underscore_const_names, "1.31.0", Some(54912), None), // `reason = ` in lint attributes and `expect` lint attribute @@ -492,12 +486,15 @@ declare_features! ( // `extern crate self as foo;` puts local crate root into extern prelude under name `foo`. (active, extern_crate_self, "1.31.0", Some(56409), None), + + // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + (active, min_const_unsafe_fn, "1.31.0", Some(55607), None), ); declare_features! ( (removed, import_shadowing, "1.0.0", None, None, None), (removed, managed_boxes, "1.0.0", None, None, None), - // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 + // Allows use of unary negate on unsigned integers, e.g., -e for e: u8 (removed, negate_unsigned, "1.0.0", Some(29645), None, None), (removed, reflect, "1.0.0", Some(27749), None, None), // A way to temporarily opt out of opt in copy. This will *never* be accepted. @@ -528,6 +525,9 @@ declare_features! ( Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, panic_implementation, "1.28.0", Some(44489), None, Some("subsumed by `#[panic_handler]`")), + // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + (removed, custom_derive, "1.0.0", Some(29644), None, + Some("subsumed by `#[proc_macro_derive]`")), ); declare_features! ( @@ -536,9 +536,9 @@ declare_features! ( declare_features! ( (accepted, associated_types, "1.0.0", None, None), - // allow overloading augmented assignment operations like `a += b` + // Allows overloading augmented assignment operations like `a += b`. (accepted, augmented_assignments, "1.8.0", Some(28235), None), - // allow empty structs and enum variants with braces + // Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720), None), // Allows indexing into constant arrays. (accepted, const_indexing, "1.26.0", Some(29947), None), @@ -549,69 +549,68 @@ declare_features! ( // to bootstrap fix for #5723. (accepted, issue_5723_bootstrap, "1.0.0", None, None), (accepted, macro_rules, "1.0.0", None, None), - // Allows using #![no_std] + // Allows using `#![no_std]`. (accepted, no_std, "1.6.0", None, None), (accepted, slicing_syntax, "1.0.0", None, None), (accepted, struct_variant, "1.0.0", None, None), // These are used to test this portion of the compiler, they don't actually - // mean anything + // mean anything. (accepted, test_accepted_feature, "1.0.0", None, None), (accepted, tuple_indexing, "1.0.0", None, None), // Allows macros to appear in the type position. (accepted, type_macros, "1.13.0", Some(27245), None), (accepted, while_let, "1.0.0", None, None), - // Allows `#[deprecated]` attribute + // Allows `#[deprecated]` attribute. (accepted, deprecated, "1.9.0", Some(29935), None), // `expr?` (accepted, question_mark, "1.13.0", Some(31436), None), - // Allows `..` in tuple (struct) patterns + // Allows `..` in tuple (struct) patterns. (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), (accepted, item_like_imports, "1.15.0", Some(35120), None), // Allows using `Self` and associated types in struct expressions and patterns. (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - // elide `'static` lifetimes in `static`s and `const`s + // elide `'static` lifetimes in `static`s and `const`s. (accepted, static_in_const, "1.17.0", Some(35897), None), // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (accepted, field_init_shorthand, "1.17.0", Some(37340), None), // Allows the definition recursive static items. (accepted, static_recursion, "1.17.0", Some(29719), None), - // pub(restricted) visibilities (RFC 1422) + // `pub(restricted)` visibilities (RFC 1422) (accepted, pub_restricted, "1.18.0", Some(32409), None), - // The #![windows_subsystem] attribute + // `#![windows_subsystem]` (accepted, windows_subsystem, "1.18.0", Some(37499), None), // Allows `break {expr}` with a value inside `loop`s. (accepted, loop_break_value, "1.19.0", Some(37339), None), // Permits numeric fields in struct expressions and patterns. (accepted, relaxed_adts, "1.19.0", Some(35626), None), - // Coerces non capturing closures to function pointers + // Coerces non capturing closures to function pointers. (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), // Allows attributes on struct literal fields. (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - // Allows the definition of associated constants in `trait` or `impl` - // blocks. + // Allows the definition of associated constants in `trait` or `impl` blocks. (accepted, associated_consts, "1.20.0", Some(29646), None), - // Usage of the `compile_error!` macro + // Usage of the `compile_error!` macro. (accepted, compile_error, "1.20.0", Some(40872), None), // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work. (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - // Allow Drop types in constants (RFC 1440) + // Allows `Drop` types in constants (RFC 1440). (accepted, drop_types_in_const, "1.22.0", Some(33156), None), // Allows the sysV64 ABI to be specified on all platforms - // instead of just the platforms on which it is the C ABI + // instead of just the platforms on which it is the C ABI. (accepted, abi_sysv64, "1.24.0", Some(36167), None), - // Allows `repr(align(16))` struct attribute (RFC 1358) + // Allows `repr(align(16))` struct attribute (RFC 1358). (accepted, repr_align, "1.25.0", Some(33626), None), - // allow '|' at beginning of match arms (RFC 1925) + // Allows '|' at beginning of match arms (RFC 1925). (accepted, match_beginning_vert, "1.25.0", Some(44101), None), // Nested groups in `use` (RFC 2128) (accepted, use_nested_groups, "1.25.0", Some(44494), None), - // a..=b and ..=b + // `a..=b` and `..=b` (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - // allow `..=` in patterns (RFC 1192) + // Allows `..=` in patterns (RFC 1192). (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), // Termination trait in main (RFC 1937) (accepted, termination_trait, "1.26.0", Some(43301), None), - // Copy/Clone closures (RFC 2132) + // `Copy`/`Clone` closures (RFC 2132). (accepted, clone_closures, "1.26.0", Some(44490), None), (accepted, copy_closures, "1.26.0", Some(44490), None), // Allows `impl Trait` in function arguments. @@ -622,73 +621,79 @@ declare_features! ( (accepted, i128_type, "1.26.0", Some(35118), None), // Default match binding modes (RFC 2005) (accepted, match_default_bindings, "1.26.0", Some(42640), None), - // allow `'_` placeholder lifetimes + // Allows `'_` placeholder lifetimes. (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - // Allows attributes on lifetime/type formal parameters in generics (RFC 1327) + // Allows attributes on lifetime/type formal parameters in generics (RFC 1327). (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - // Allows cfg(target_feature = "..."). + // Allows `cfg(target_feature = "...")`. (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - // Allows #[target_feature(...)] + // Allows `#[target_feature(...)]`. (accepted, target_feature, "1.27.0", None, None), // Trait object syntax with `dyn` prefix (accepted, dyn_trait, "1.27.0", Some(44662), None), - // allow `#[must_use]` on functions; and, must-use operators (RFC 1940) + // Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). (accepted, fn_must_use, "1.27.0", Some(43302), None), - // Allows use of the :lifetime macro fragment specifier + // Allows use of the `:lifetime` macro fragment specifier. (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), // Termination trait in tests (RFC 1937) (accepted, termination_trait_test, "1.27.0", Some(48854), None), - // The #[global_allocator] attribute + // The `#[global_allocator]` attribute (accepted, global_allocator, "1.28.0", Some(27389), None), - // Allows `#[repr(transparent)]` attribute on newtype structs + // Allows `#[repr(transparent)]` attribute on newtype structs. (accepted, repr_transparent, "1.28.0", Some(43036), None), - // Defining procedural macros in `proc-macro` crates + // Procedural macros in `proc-macro` crates (accepted, proc_macro, "1.29.0", Some(38356), None), // `foo.rs` as an alternative to `foo/mod.rs` (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - // Allows use of the :vis macro fragment specifier + // Allows use of the `:vis` macro fragment specifier (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), // Allows importing and reexporting macros with `use`, // enables macro modularization in general. (accepted, use_extern_macros, "1.30.0", Some(35896), None), - // Allows keywords to be escaped for use as identifiers + // Allows keywords to be escaped for use as identifiers. (accepted, raw_identifiers, "1.30.0", Some(48589), None), - // Attributes scoped to tools + // Attributes scoped to tools. (accepted, tool_attributes, "1.30.0", Some(44690), None), - // Allows multi-segment paths in attributes and derives + // Allows multi-segment paths in attributes and derives. (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), // Allows all literals in attribute lists and values of key-value pairs. (accepted, attr_literals, "1.30.0", Some(34981), None), - // Infer outlives requirements; RFC 2093 + // Infer outlives requirements (RFC 2093). (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), (accepted, panic_handler, "1.30.0", Some(44489), None), - // Used to preserve symbols (see llvm.used) + // Used to preserve symbols (see llvm.used). (accepted, used, "1.30.0", Some(40289), None), // `crate` in paths (accepted, crate_in_paths, "1.30.0", Some(45477), None), - // Resolve absolute paths as paths from other crates + // Resolve absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), - // Access to crate names passed via `--extern` through prelude + // Access to crate names passed via `--extern` through prelude. (accepted, extern_prelude, "1.30.0", Some(44660), None), // Parentheses in patterns (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - // Allows the definition of `const fn` functions + // Allows the definition of `const fn` functions. (accepted, min_const_fn, "1.31.0", Some(53555), None), // Scoped lints (accepted, tool_lints, "1.31.0", Some(44690), None), - // impl<I:Iterator> Iterator for &mut Iterator - // impl Debug for Foo<'_> + // `impl<I:Iterator> Iterator for &mut Iterator` + // `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - // `extern crate foo as bar;` puts `bar` into extern prelude + // `extern crate foo as bar;` puts `bar` into extern prelude. (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - // Allows use of the :literal macro fragment specifier (RFC 1576) - (accepted, macro_literal_matcher, "1.31.0", Some(35625), None), - // Use `?` as the Kleene "at most one" operator + // Allows use of the `:literal` macro fragment specifier (RFC 1576). + (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), + // Use `?` as the Kleene "at most one" operator. (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), // `Self` struct constructor (RFC 2302) (accepted, self_struct_ctor, "1.32.0", Some(51994), None), // `Self` in type definitions (RFC 2300) (accepted, self_in_typedefs, "1.32.0", Some(49303), None), + // Integer match exhaustiveness checking (RFC 2591) + (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), + // `use path as _;` and `extern crate c as _;` + (accepted, underscore_imports, "1.33.0", Some(48216), None), + // Allows `#[repr(packed(N))]` attribute on structs. + (accepted, repr_packed, "1.33.0", Some(33158), None), ); // If you change this, please modify `src/doc/unstable-book` as well. You must @@ -769,7 +774,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { } // Attributes that have a special meaning to rustc or rustdoc -pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[ +pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeGate)] = &[ // Normal attributes ("warn", Normal, Ungated), @@ -1273,7 +1278,7 @@ impl<'a> Context<'a> { if attr.path == &**n { // Plugins can't gate attributes, so we don't check for it // unlike the code above; we only use this loop to - // short-circuit to avoid the checks below + // short-circuit to avoid the checks below. debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty); return; } @@ -1283,13 +1288,10 @@ impl<'a> Context<'a> { "unless otherwise specified, attributes \ with the prefix `rustc_` \ are reserved for internal compiler diagnostics"); - } else if name.starts_with("derive_") { - gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE); } else if !attr::is_known(attr) { - // Only run the custom attribute lint during regular - // feature gate checking. Macro gating runs - // before the plugin attributes are registered - // so we skip this then + // Only run the custom attribute lint during regular feature gate + // checking. Macro gating runs before the plugin attributes are + // registered, so we skip this in that case. if !is_macro { let msg = format!("The attribute `{}` is currently unknown to the compiler and \ may have meaning added to it in the future", attr.path); @@ -1383,48 +1385,38 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue } -const EXPLAIN_BOX_SYNTAX: &'static str = +const EXPLAIN_BOX_SYNTAX: &str = "box expression syntax is experimental; you can call `Box::new` instead."; -pub const EXPLAIN_STMT_ATTR_SYNTAX: &'static str = +pub const EXPLAIN_STMT_ATTR_SYNTAX: &str = "attributes on expressions are experimental."; -pub const EXPLAIN_ASM: &'static str = +pub const EXPLAIN_ASM: &str = "inline assembly is not stable enough for use and is subject to change"; -pub const EXPLAIN_GLOBAL_ASM: &'static str = +pub const EXPLAIN_GLOBAL_ASM: &str = "`global_asm!` is not stable enough for use and is subject to change"; -pub const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &'static str = +pub const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &str = "custom test frameworks are an unstable feature"; -pub const EXPLAIN_LOG_SYNTAX: &'static str = +pub const EXPLAIN_LOG_SYNTAX: &str = "`log_syntax!` is not stable enough for use and is subject to change"; -pub const EXPLAIN_CONCAT_IDENTS: &'static str = +pub const EXPLAIN_CONCAT_IDENTS: &str = "`concat_idents` is not stable enough for use and is subject to change"; -pub const EXPLAIN_FORMAT_ARGS_NL: &'static str = +pub const EXPLAIN_FORMAT_ARGS_NL: &str = "`format_args_nl` is only for internal language use and is subject to change"; -pub const EXPLAIN_TRACE_MACROS: &'static str = +pub const EXPLAIN_TRACE_MACROS: &str = "`trace_macros` is not stable enough for use and is subject to change"; -pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str = +pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = "allow_internal_unstable side-steps feature gating and stability checks"; -pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &'static str = +pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = "allow_internal_unsafe side-steps the unsafe_code lint"; -pub const EXPLAIN_CUSTOM_DERIVE: &'static str = - "`#[derive]` for custom traits is deprecated and will be removed in the future."; - -pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &'static str = - "`#[derive]` for custom traits is deprecated and will be removed in the future. \ - Prefer using procedural macro custom derive."; - -pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str = - "attributes of the form `#[derive_*]` are reserved for the compiler"; - -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = "unsized tuple coercion is not stable enough for use and is subject to change"; struct PostExpansionVisitor<'a> { @@ -1555,26 +1547,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) { - if let ast::UseTreeKind::Simple(Some(ident), ..) = use_tree.kind { - if ident.name == "_" { - gate_feature_post!(&self, underscore_imports, use_tree.span, - "renaming imports with `_` is unstable"); - } - } - - visit::walk_use_tree(self, use_tree, id); - } - fn visit_item(&mut self, i: &'a ast::Item) { match i.node { - ast::ItemKind::ExternCrate(_) => { - if i.ident.name == "_" { - gate_feature_post!(&self, underscore_imports, i.span, - "renaming extern crates with `_` is unstable"); - } - } - ast::ItemKind::Static(..) | ast::ItemKind::Const(_,_) => { if i.ident.name == "_" { @@ -1613,13 +1587,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } - if let Some((name, _)) = item.name_value_literal() { - if name == "packed" { - gate_feature_post!(&self, repr_packed, attr.span, - "the `#[repr(packed(n))]` attribute \ - is experimental"); - } - } } } } @@ -1797,14 +1764,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { _node_id: NodeId) { match fn_kind { FnKind::ItemFn(_, header, _, _) => { - // check for const fn and async fn declarations + // Check for const fn and async fn declarations. if header.asyncness.is_async() { gate_feature_post!(&self, async_await, span, "async fn is unstable"); } - // stability of const fn methods are covered in - // visit_trait_item and visit_impl_item below; this is - // because default methods don't pass through this - // point. + // Stability of const fn methods are covered in + // `visit_trait_item` and `visit_impl_item` below; this is + // because default methods don't pass through this point. self.check_abi(header.abi, span); } @@ -1881,7 +1847,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) { for segment in &path.segments { - // Identifiers we are going to check could come from a legacy macro (e.g. `#[test]`). + // Identifiers we are going to check could come from a legacy macro (e.g., `#[test]`). // For such macros identifiers must have empty context, because this context is // used during name resolution and produced names must be unhygienic for compatibility. // On the other hand, we need the actual non-empty context for feature gate checking @@ -1928,7 +1894,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], for &edition in ALL_EDITIONS { if edition <= crate_edition { // The `crate_edition` implies its respective umbrella feature-gate - // (i.e. `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). + // (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX). edition_enabled_features.insert(Symbol::intern(edition.feature_name()), edition); } } @@ -2088,7 +2054,7 @@ pub enum UnstableFeatures { impl UnstableFeatures { pub fn from_environment() -> UnstableFeatures { - // Whether this is a feature-staged build, i.e. on the beta or stable channel + // Whether this is a feature-staged build, i.e., on the beta or stable channel let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); // Whether we should enable unstable features for bootstrapping let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0e6e2f90693..ecb02452638 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -229,7 +229,7 @@ pub trait Folder : Sized { fn fold_mac(&mut self, _mac: Mac) -> Mac { panic!("fold_mac disabled by default"); - // NB: see note about macros above. + // N.B., see note about macros above. // if you really want a folder that // works on macros, use this // definition in your trait impl: @@ -605,12 +605,10 @@ pub fn noop_fold_tt<T: Folder>(tt: TokenTree, fld: &mut T) -> TokenTree { match tt { TokenTree::Token(span, tok) => TokenTree::Token(fld.new_span(span), fld.fold_token(tok)), - TokenTree::Delimited(span, delimed) => TokenTree::Delimited( + TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited( DelimSpan::from_pair(fld.new_span(span.open), fld.new_span(span.close)), - Delimited { - tts: fld.fold_tts(delimed.stream()).into(), - delim: delimed.delim, - } + delim, + fld.fold_tts(tts.stream()).into(), ), } } @@ -637,7 +635,7 @@ pub fn noop_fold_token<T: Folder>(t: token::Token, fld: &mut T) -> token::Token /// apply folder to elements of interpolated nodes // -// NB: this can occur only when applying a fold to partially expanded code, where +// N.B., this can occur only when applying a fold to partially expanded code, where // parsed pieces have gotten implanted ito *other* macro invocations. This is relevant // for macro hygiene, but possibly not elsewhere. // diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index ca9c5ad7b60..1fa11a4d6c8 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -134,7 +134,7 @@ pub mod diagnostics { pub mod metadata; } -// NB: This module needs to be declared first so diagnostics are +// N.B., this module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostic_list; @@ -145,12 +145,6 @@ pub mod util { #[cfg(test)] pub mod parser_testing; pub mod move_map; - - mod rc_slice; - pub use self::rc_slice::RcSlice; - - mod rc_vec; - pub use self::rc_vec::RcVec; } pub mod json; @@ -173,7 +167,6 @@ pub mod parse; pub mod ptr; pub mod show_span; pub mod std_inject; -pub mod str; pub use syntax_pos::edition; pub use syntax_pos::symbol; pub mod test; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index a240604bfe0..1bd0656846b 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -22,8 +22,8 @@ enum InnerAttributeParsePolicy<'a> { NotPermitted { reason: &'a str }, } -const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &'static str = "an inner attribute is not \ - permitted in this context"; +const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ + permitted in this context"; impl<'a> Parser<'a> { /// Parse attributes that appear before an item @@ -170,7 +170,7 @@ impl<'a> Parser<'a> { token::CloseDelim(_) | token::Eof => self.unexpected()?, _ => self.parse_token_tree(), }; - TokenStream::concat(vec![eq.into(), tree.into()]) + TokenStream::new(vec![eq.into(), tree.into()]) } else { TokenStream::empty() }; diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 172a48ddba2..d3039326c89 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -16,7 +16,6 @@ use syntax_pos::{BytePos, CharPos, Pos, FileName}; use parse::lexer::{is_block_doc_comment, is_pattern_whitespace}; use parse::lexer::{self, ParseSess, StringReader, TokenAndSpan}; use print::pprust; -use str::char_at; use std::io::Read; use std::usize; @@ -207,20 +206,14 @@ fn read_line_comments(rdr: &mut StringReader, /// Otherwise returns Some(k) where k is first char offset after that leading /// whitespace. Note k may be outside bounds of s. fn all_whitespace(s: &str, col: CharPos) -> Option<usize> { - let len = s.len(); - let mut col = col.to_usize(); - let mut cursor: usize = 0; - - while col > 0 && cursor < len { - let ch = char_at(s, cursor); + let mut idx = 0; + for (i, ch) in s.char_indices().take(col.to_usize()) { if !ch.is_whitespace() { return None; } - cursor += ch.len_utf8(); - col -= 1; + idx = i + ch.len_utf8(); } - - Some(cursor) + Some(idx) } fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<String>, s: String, col: CharPos) { @@ -228,7 +221,7 @@ fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<String>, s: String, col: let s1 = match all_whitespace(&s[..], col) { Some(col) => { if col < len { - (&s[col..len]).to_string() + s[col..len].to_string() } else { String::new() } @@ -247,20 +240,13 @@ fn read_block_comment(rdr: &mut StringReader, let mut lines: Vec<String> = Vec::new(); // Count the number of chars since the start of the line by rescanning. - let mut src_index = rdr.src_index(rdr.source_file.line_begin_pos(rdr.pos)); + let src_index = rdr.src_index(rdr.source_file.line_begin_pos(rdr.pos)); let end_src_index = rdr.src_index(rdr.pos); assert!(src_index <= end_src_index, "src_index={}, end_src_index={}, line_begin_pos={}", src_index, end_src_index, rdr.source_file.line_begin_pos(rdr.pos).to_u32()); - let mut n = 0; - - while src_index < end_src_index { - let c = char_at(&rdr.src, src_index); - src_index += c.len_utf8(); - n += 1; - } - let col = CharPos(n); + let col = CharPos(rdr.src[src_index..end_src_index].chars().count()); rdr.bump(); rdr.bump(); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index c90c62c13f9..4be54e5bacc 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -13,12 +13,12 @@ use syntax_pos::{self, BytePos, CharPos, Pos, Span, NO_EXPANSION}; use source_map::{SourceMap, FilePathMapping}; use errors::{Applicability, FatalError, Diagnostic, DiagnosticBuilder}; use parse::{token, ParseSess}; -use str::char_at; use symbol::{Symbol, keywords}; use core::unicode::property::Pattern_White_Space; use std::borrow::Cow; use std::char; +use std::iter; use std::mem::replace; use rustc_data_structures::sync::Lrc; @@ -459,45 +459,42 @@ impl<'a> StringReader<'a> { /// Converts CRLF to LF in the given string, raising an error on bare CR. fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> Cow<'b, str> { - let mut i = 0; - while i < s.len() { - let ch = char_at(s, i); - let next = i + ch.len_utf8(); + let mut chars = s.char_indices().peekable(); + while let Some((i, ch)) = chars.next() { if ch == '\r' { - if next < s.len() && char_at(s, next) == '\n' { - return translate_crlf_(self, start, s, errmsg, i).into(); + if let Some((lf_idx, '\n')) = chars.peek() { + return translate_crlf_(self, start, s, *lf_idx, chars, errmsg).into(); } let pos = start + BytePos(i as u32); - let end_pos = start + BytePos(next as u32); + let end_pos = start + BytePos((i + ch.len_utf8()) as u32); self.err_span_(pos, end_pos, errmsg); } - i = next; } return s.into(); fn translate_crlf_(rdr: &StringReader, start: BytePos, s: &str, - errmsg: &str, - mut i: usize) + mut j: usize, + mut chars: iter::Peekable<impl Iterator<Item = (usize, char)>>, + errmsg: &str) -> String { let mut buf = String::with_capacity(s.len()); - let mut j = 0; - while i < s.len() { - let ch = char_at(s, i); - let next = i + ch.len_utf8(); + // Skip first CR + buf.push_str(&s[.. j - 1]); + while let Some((i, ch)) = chars.next() { if ch == '\r' { if j < i { buf.push_str(&s[j..i]); } + let next = i + ch.len_utf8(); j = next; - if next >= s.len() || char_at(s, next) != '\n' { + if chars.peek().map(|(_, ch)| *ch) != Some('\n') { let pos = start + BytePos(i as u32); let end_pos = start + BytePos(next as u32); rdr.err_span_(pos, end_pos, errmsg); } } - i = next; } if j < s.len() { buf.push_str(&s[j..]); @@ -1130,7 +1127,7 @@ impl<'a> StringReader<'a> { "expected at least one digit in exponent" ); if let Some(ch) = self.ch { - // check for e.g. Unicode minus '−' (Issue #49746) + // check for e.g., Unicode minus '−' (Issue #49746) if unicode_chars::check_for_substitution(self, ch, &mut err) { self.bump(); self.scan_digits(10, 10); @@ -1858,6 +1855,11 @@ fn ident_continue(c: Option<char>) -> bool { (c > '\x7f' && c.is_xid_continue()) } +#[inline] +fn char_at(s: &str, byte: usize) -> char { + s[byte..].chars().next().unwrap() +} + #[cfg(test)] mod tests { use super::*; @@ -1898,7 +1900,7 @@ mod tests { sess: &'a ParseSess, teststr: String) -> StringReader<'a> { - let sf = sm.new_source_file(PathBuf::from("zebra.rs").into(), teststr); + let sf = sm.new_source_file(PathBuf::from(teststr.clone()).into(), teststr); StringReader::new(sess, sf, None) } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 8047ab01465..6f9dc247a78 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -11,7 +11,7 @@ use print::pprust::token_to_string; use parse::lexer::StringReader; use parse::{token, PResult}; -use tokenstream::{Delimited, DelimSpan, TokenStream, TokenTree}; +use tokenstream::{DelimSpan, TokenStream, TokenTree}; impl<'a> StringReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. @@ -22,7 +22,7 @@ impl<'a> StringReader<'a> { tts.push(self.parse_token_tree()?); } - Ok(TokenStream::concat(tts)) + Ok(TokenStream::new(tts)) } // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. @@ -30,14 +30,14 @@ impl<'a> StringReader<'a> { let mut tts = vec![]; loop { if let token::CloseDelim(..) = self.token { - return TokenStream::concat(tts); + return TokenStream::new(tts); } match self.parse_token_tree() { Ok(tree) => tts.push(tree), Err(mut e) => { e.emit(); - return TokenStream::concat(tts); + return TokenStream::new(tts); } } } @@ -97,7 +97,15 @@ impl<'a> StringReader<'a> { // Correct delimiter. token::CloseDelim(d) if d == delim => { let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); - self.matching_delim_spans.push((open_brace, open_brace_span, self.span)); + if self.open_braces.len() == 0 { + // Clear up these spans to avoid suggesting them as we've found + // properly matched delimiters so far for an entire block. + self.matching_delim_spans.clear(); + } else { + self.matching_delim_spans.push( + (open_brace, open_brace_span, self.span), + ); + } // Parse the close delimiter. self.real_token(); } @@ -155,10 +163,11 @@ impl<'a> StringReader<'a> { _ => {} } - Ok(TokenTree::Delimited(delim_span, Delimited { + Ok(TokenTree::Delimited( + delim_span, delim, - tts: tts.into(), - }).into()) + tts.into(), + ).into()) }, token::CloseDelim(_) => { // An unexpected closing delimiter (i.e., there is no diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 03bf1b5a4e1..8a620c8067d 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -306,7 +306,7 @@ const UNICODE_ARRAY: &[(char, &str, char)] = &[ ('>', "Fullwidth Greater-Than Sign", '>'), ]; -const ASCII_ARRAY: &'static [(char, &'static str)] = &[ +const ASCII_ARRAY: &[(char, &str)] = &[ (' ', "Space"), ('_', "Underscore"), ('-', "Minus/Hyphen"), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ac972f20f94..200b1cecc03 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -15,11 +15,10 @@ use ast::{self, CrateConfig, NodeId}; use early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; use source_map::{SourceMap, FilePathMapping}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; -use errors::{Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; +use errors::{FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; use feature_gate::UnstableFeatures; use parse::parser::Parser; use ptr::P; -use str::char_at; use symbol::Symbol; use tokenstream::{TokenStream, TokenTree}; use diagnostics::plugin::ErrorMap; @@ -82,6 +81,7 @@ impl ParseSess { } } + #[inline] pub fn source_map(&self) -> &SourceMap { &self.source_map } @@ -193,6 +193,14 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> source_file_to_parser(sess, file_to_source_file(sess, path, None)) } +/// Create a new parser, returning buffered diagnostics if the file doesn't +/// exist or from lexing the initial token stream. +pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) + -> Result<Parser<'a>, Vec<Diagnostic>> { + let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?; + maybe_source_file_to_parser(sess, file) +} + /// Given a session, a crate config, a path, and a span, add /// the file at the given path to the source_map, and return a parser. /// On an error, use the given span as the source of the problem. @@ -238,17 +246,30 @@ pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser { // base abstractions /// Given a session and a path and an optional span (for error reporting), +/// add the path to the session's source_map and return the new source_file or +/// error when a file can't be read. +fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>) + -> Result<Lrc<SourceFile>, Diagnostic> { + sess.source_map().load_file(path) + .map_err(|e| { + let msg = format!("couldn't read {}: {}", path.display(), e); + let mut diag = Diagnostic::new(Level::Fatal, &msg); + if let Some(sp) = spanopt { + diag.set_span(sp); + } + diag + }) +} + +/// Given a session and a path and an optional span (for error reporting), /// add the path to the session's source_map and return the new source_file. fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>) -> Lrc<SourceFile> { - match sess.source_map().load_file(path) { + match try_file_to_source_file(sess, path, spanopt) { Ok(source_file) => source_file, - Err(e) => { - let msg = format!("couldn't read {}: {}", path.display(), e); - match spanopt { - Some(sp) => sess.span_diagnostic.span_fatal(sp, &msg).raise(), - None => sess.span_diagnostic.fatal(&msg).raise() - } + Err(d) => { + DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, d).emit(); + FatalError.raise(); } } } @@ -436,9 +457,7 @@ fn raw_str_lit(lit: &str) -> String { // check if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { - s.len() > 1 && - first_chars.contains(&char_at(s, 0)) && - s[1..].chars().all(|c| '0' <= c && c <= '9') + s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) } macro_rules! err { @@ -645,11 +664,11 @@ fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>) let orig = s; let mut ty = ast::LitIntType::Unsuffixed; - if char_at(s, 0) == '0' && s.len() > 1 { - match char_at(s, 1) { - 'x' => base = 16, - 'o' => base = 8, - 'b' => base = 2, + if s.starts_with('0') && s.len() > 1 { + match s.as_bytes()[1] { + b'x' => base = 16, + b'o' => base = 8, + b'b' => base = 2, _ => { } } } @@ -767,7 +786,7 @@ mod tests { use attr::first_attr_value_str_by_name; use parse; use print::pprust::item_to_string; - use tokenstream::{self, DelimSpan, TokenTree}; + use tokenstream::{DelimSpan, TokenTree}; use util::parser_testing::string_to_stream; use util::parser_testing::{string_to_expr, string_to_item}; use with_globals; @@ -798,42 +817,41 @@ mod tests { Some(&TokenTree::Token(_, token::Ident(name_macro_rules, false))), Some(&TokenTree::Token(_, token::Not)), Some(&TokenTree::Token(_, token::Ident(name_zip, false))), - Some(&TokenTree::Delimited(_, ref macro_delimed)), + Some(&TokenTree::Delimited(_, macro_delim, ref macro_tts)), ) if name_macro_rules.name == "macro_rules" && name_zip.name == "zip" => { - let tts = ¯o_delimed.stream().trees().collect::<Vec<_>>(); + let tts = ¯o_tts.stream().trees().collect::<Vec<_>>(); match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { ( 3, - Some(&TokenTree::Delimited(_, ref first_delimed)), + Some(&TokenTree::Delimited(_, first_delim, ref first_tts)), Some(&TokenTree::Token(_, token::FatArrow)), - Some(&TokenTree::Delimited(_, ref second_delimed)), + Some(&TokenTree::Delimited(_, second_delim, ref second_tts)), ) - if macro_delimed.delim == token::Paren => { - let tts = &first_delimed.stream().trees().collect::<Vec<_>>(); + if macro_delim == token::Paren => { + let tts = &first_tts.stream().trees().collect::<Vec<_>>(); match (tts.len(), tts.get(0), tts.get(1)) { ( 2, Some(&TokenTree::Token(_, token::Dollar)), Some(&TokenTree::Token(_, token::Ident(ident, false))), ) - if first_delimed.delim == token::Paren && ident.name == "a" => {}, - _ => panic!("value 3: {:?}", *first_delimed), + if first_delim == token::Paren && ident.name == "a" => {}, + _ => panic!("value 3: {:?} {:?}", first_delim, first_tts), } - let tts = &second_delimed.stream().trees().collect::<Vec<_>>(); + let tts = &second_tts.stream().trees().collect::<Vec<_>>(); match (tts.len(), tts.get(0), tts.get(1)) { ( 2, Some(&TokenTree::Token(_, token::Dollar)), Some(&TokenTree::Token(_, token::Ident(ident, false))), ) - if second_delimed.delim == token::Paren - && ident.name == "a" => {}, - _ => panic!("value 4: {:?}", *second_delimed), + if second_delim == token::Paren && ident.name == "a" => {}, + _ => panic!("value 4: {:?} {:?}", second_delim, second_tts), } }, - _ => panic!("value 2: {:?}", *macro_delimed), + _ => panic!("value 2: {:?} {:?}", macro_delim, macro_tts), } }, _ => panic!("value: {:?}",tts), @@ -846,31 +864,29 @@ mod tests { with_globals(|| { let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); - let expected = TokenStream::concat(vec![ + let expected = TokenStream::new(vec![ TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"), false)).into(), TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"), false)).into(), TokenTree::Delimited( DelimSpan::from_pair(sp(5, 6), sp(13, 14)), - tokenstream::Delimited { - delim: token::DelimToken::Paren, - tts: TokenStream::concat(vec![ - TokenTree::Token(sp(6, 7), - token::Ident(Ident::from_str("b"), false)).into(), - TokenTree::Token(sp(8, 9), token::Colon).into(), - TokenTree::Token(sp(10, 13), - token::Ident(Ident::from_str("i32"), false)).into(), - ]).into(), - }).into(), + token::DelimToken::Paren, + TokenStream::new(vec![ + TokenTree::Token(sp(6, 7), + token::Ident(Ident::from_str("b"), false)).into(), + TokenTree::Token(sp(8, 9), token::Colon).into(), + TokenTree::Token(sp(10, 13), + token::Ident(Ident::from_str("i32"), false)).into(), + ]).into(), + ).into(), TokenTree::Delimited( DelimSpan::from_pair(sp(15, 16), sp(20, 21)), - tokenstream::Delimited { - delim: token::DelimToken::Brace, - tts: TokenStream::concat(vec![ - TokenTree::Token(sp(17, 18), - token::Ident(Ident::from_str("b"), false)).into(), - TokenTree::Token(sp(18, 19), token::Semi).into(), - ]).into(), - }).into() + token::DelimToken::Brace, + TokenStream::new(vec![ + TokenTree::Token(sp(17, 18), + token::Ident(Ident::from_str("b"), false)).into(), + TokenTree::Token(sp(18, 19), token::Semi).into(), + ]).into(), + ).into() ]); assert_eq!(tts, expected); @@ -977,23 +993,25 @@ mod tests { with_globals(|| { let sess = ParseSess::new(FilePathMapping::empty()); - let name = FileName::Custom("source".to_string()); + let name_1 = FileName::Custom("crlf_source_1".to_string()); let source = "/// doc comment\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name.clone(), source, &sess) + let item = parse_item_from_source_str(name_1, source, &sess) .unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); assert_eq!(doc, "/// doc comment"); + let name_2 = FileName::Custom("crlf_source_2".to_string()); let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name.clone(), source, &sess) + let item = parse_item_from_source_str(name_2, source, &sess) .unwrap().unwrap(); let docs = item.attrs.iter().filter(|a| a.path == "doc") .map(|a| a.value_str().unwrap().to_string()).collect::<Vec<_>>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; assert_eq!(&docs[..], b); + let name_3 = FileName::Custom("clrf_source_3".to_string()); let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); - let item = parse_item_from_source_str(name, source, &sess).unwrap().unwrap(); + let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); assert_eq!(doc, "/** doc comment\n * with CRLF */"); }); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1cd5006f330..5a51b629826 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -48,13 +48,14 @@ use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId}; use parse::{self, SeqSep, classify, token}; use parse::lexer::TokenAndSpan; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; +use parse::token::DelimToken; use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; use util::parser::{AssocOp, Fixity}; use print::pprust; use ptr::P; use parse::PResult; use ThinVec; -use tokenstream::{self, Delimited, DelimSpan, ThinTokenStream, TokenTree, TokenStream}; +use tokenstream::{self, DelimSpan, ThinTokenStream, TokenTree, TokenStream}; use symbol::{Symbol, keywords}; use std::borrow::Cow; @@ -92,12 +93,12 @@ pub enum PathStyle { /// `x<y>` - comparisons, `x::<y>` - unambiguously a path. Expr, /// In other contexts, notably in types, no ambiguity exists and paths can be written - /// without the disambiguator, e.g. `x<y>` - unambiguously a path. + /// without the disambiguator, e.g., `x<y>` - unambiguously a path. /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too. Type, - /// A path with generic arguments disallowed, e.g. `foo::bar::Baz`, used in imports, + /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports, /// visibilities or attributes. - /// Technically, this variant is unnecessary and e.g. `Expr` can be used instead + /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead /// (paths in "mod" contexts have to be checked later for absence of generic arguments /// anyway, due to macros), but it is used to avoid weird suggestions about expected /// tokens when something goes wrong. @@ -293,13 +294,13 @@ enum LastToken { } impl TokenCursorFrame { - fn new(sp: DelimSpan, delimited: &Delimited) -> Self { + fn new(sp: DelimSpan, delim: DelimToken, tts: &ThinTokenStream) -> Self { TokenCursorFrame { - delim: delimited.delim, + delim: delim, span: sp, - open_delim: delimited.delim == token::NoDelim, - tree_cursor: delimited.stream().into_trees(), - close_delim: delimited.delim == token::NoDelim, + open_delim: delim == token::NoDelim, + tree_cursor: tts.stream().into_trees(), + close_delim: delim == token::NoDelim, last_token: LastToken::Was(None), } } @@ -310,14 +311,12 @@ impl TokenCursor { loop { let tree = if !self.frame.open_delim { self.frame.open_delim = true; - Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } - .open_tt(self.frame.span.open) + TokenTree::open_tt(self.frame.span.open, self.frame.delim) } else if let Some(tree) = self.frame.tree_cursor.next() { tree } else if !self.frame.close_delim { self.frame.close_delim = true; - Delimited { delim: self.frame.delim, tts: TokenStream::empty().into() } - .close_tt(self.frame.span.close) + TokenTree::close_tt(self.frame.span.close, self.frame.delim) } else if let Some(frame) = self.stack.pop() { self.frame = frame; continue @@ -332,8 +331,8 @@ impl TokenCursor { match tree { TokenTree::Token(sp, tok) => return TokenAndSpan { tok: tok, sp: sp }, - TokenTree::Delimited(sp, ref delimited) => { - let frame = TokenCursorFrame::new(sp, delimited); + TokenTree::Delimited(sp, delim, tts) => { + let frame = TokenCursorFrame::new(sp, delim, &tts); self.stack.push(mem::replace(&mut self.frame, frame)); } } @@ -362,25 +361,28 @@ impl TokenCursor { } let delim_span = DelimSpan::from_single(sp); - let body = TokenTree::Delimited(delim_span, Delimited { - delim: token::Bracket, - tts: [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)), - TokenTree::Token(sp, token::Eq), - TokenTree::Token(sp, token::Literal( - token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))] - .iter().cloned().collect::<TokenStream>().into(), - }); + let body = TokenTree::Delimited( + delim_span, + token::Bracket, + [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)), + TokenTree::Token(sp, token::Eq), + TokenTree::Token(sp, token::Literal( + token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None)) + ] + .iter().cloned().collect::<TokenStream>().into(), + ); - self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new(delim_span, &Delimited { - delim: token::NoDelim, - tts: if doc_comment_style(&name.as_str()) == AttrStyle::Inner { + self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new( + delim_span, + token::NoDelim, + &if doc_comment_style(&name.as_str()) == AttrStyle::Inner { [TokenTree::Token(sp, token::Pound), TokenTree::Token(sp, token::Not), body] .iter().cloned().collect::<TokenStream>().into() } else { [TokenTree::Token(sp, token::Pound), body] .iter().cloned().collect::<TokenStream>().into() }, - }))); + ))); self.next() } @@ -561,10 +563,11 @@ impl<'a> Parser<'a> { root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { - frame: TokenCursorFrame::new(DelimSpan::dummy(), &Delimited { - delim: token::NoDelim, - tts: tokens.into(), - }), + frame: TokenCursorFrame::new( + DelimSpan::dummy(), + token::NoDelim, + &tokens.into(), + ), stack: Vec::new(), }, desugar_doc_comments, @@ -1238,7 +1241,7 @@ impl<'a> Parser<'a> { f(&match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { Some(tree) => match tree { TokenTree::Token(_, tok) => tok, - TokenTree::Delimited(_, delimited) => token::OpenDelim(delimited.delim), + TokenTree::Delimited(_, delim, _) => token::OpenDelim(delim), }, None => token::CloseDelim(self.token_cursor.frame.delim), }) @@ -1251,7 +1254,7 @@ impl<'a> Parser<'a> { match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { Some(TokenTree::Token(span, _)) => span, - Some(TokenTree::Delimited(span, _)) => span.entire(), + Some(TokenTree::Delimited(span, ..)) => span.entire(), None => self.look_ahead_span(dist - 1), } } @@ -1404,7 +1407,7 @@ impl<'a> Parser<'a> { // definition... // We don't allow argument names to be left off in edition 2018. - p.parse_arg_general(p.span.rust_2018()) + p.parse_arg_general(p.span.rust_2018(), true) })?; generics.where_clause = self.parse_where_clause()?; @@ -1817,7 +1820,7 @@ impl<'a> Parser<'a> { /// This version of parse arg doesn't necessarily require /// identifier names. - fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { + fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool) -> PResult<'a, Arg> { maybe_whole!(self, NtArg, |x| x); if let Ok(Some(_)) = self.parse_self_arg() { @@ -1849,6 +1852,17 @@ impl<'a> Parser<'a> { String::from("<identifier>: <type>"), Applicability::HasPlaceholders, ); + } else if require_name && is_trait_item { + if let PatKind::Ident(_, ident, _) = pat.node { + err.span_suggestion_with_applicability( + pat.span, + "explicitly ignore parameter", + format!("_: {}", ident), + Applicability::MachineApplicable, + ); + } + + err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)"); } return Err(err); @@ -1914,10 +1928,10 @@ impl<'a> Parser<'a> { /// Parse a single function argument crate fn parse_arg(&mut self) -> PResult<'a, Arg> { - self.parse_arg_general(true) + self.parse_arg_general(true, false) } - /// Parse an argument in a lambda header e.g. |arg, arg| + /// Parse an argument in a lambda header e.g., |arg, arg| fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { let pat = self.parse_pat(Some("argument name"))?; let t = if self.eat(&token::Colon) { @@ -2017,6 +2031,17 @@ impl<'a> Parser<'a> { } } + fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { + match self.token { + token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { + let span = self.span; + self.bump(); + Ok(Ident::new(ident.name, span)) + } + _ => self.parse_ident(), + } + } + /// Parses qualified path. /// Assumes that the leading `<` has been parsed already. /// @@ -2082,7 +2107,7 @@ impl<'a> Parser<'a> { let mut segments = Vec::new(); let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { - segments.push(PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); + segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } self.parse_path_segments(&mut segments, style, enable_warning)?; @@ -2306,8 +2331,8 @@ impl<'a> Parser<'a> { return Err(err) } }; - let delimited = match self.parse_token_tree() { - TokenTree::Delimited(_, delimited) => delimited, + let tts = match self.parse_token_tree() { + TokenTree::Delimited(_, _, tts) => tts, _ => unreachable!(), }; let delim = match delim { @@ -2316,14 +2341,14 @@ impl<'a> Parser<'a> { token::Brace => MacDelimiter::Brace, token::NoDelim => self.bug("unexpected no delimiter"), }; - Ok((delim, delimited.stream().into())) + Ok((delim, tts.stream().into())) } /// At the bottom (top?) of the precedence hierarchy, /// parse things like parenthesized exprs, /// macros, return, etc. /// - /// NB: This does not parse outer attributes, + /// N.B., this does not parse outer attributes, /// and is private because it only works /// correctly if called from parse_dot_or_call_expr(). fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> { @@ -2881,10 +2906,11 @@ impl<'a> Parser<'a> { self.token_cursor.stack.pop().unwrap()); self.span = frame.span.entire(); self.bump(); - TokenTree::Delimited(frame.span, Delimited { - delim: frame.delim, - tts: frame.tree_cursor.original_stream().into(), - }) + TokenTree::Delimited( + frame.span, + frame.delim, + frame.tree_cursor.original_stream().into(), + ) }, token::CloseDelim(_) | token::Eof => unreachable!(), _ => { @@ -2913,7 +2939,7 @@ impl<'a> Parser<'a> { _ => result.push(self.parse_token_tree().into()), } } - TokenStream::concat(result) + TokenStream::new(result) } /// Parse a prefix-unary-operator expr @@ -3036,6 +3062,7 @@ impl<'a> Parser<'a> { /// /// This parses an expression accounting for associativity and precedence of the operators in /// the expression. + #[inline] fn parse_assoc_expr(&mut self, already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { @@ -3696,6 +3723,7 @@ impl<'a> Parser<'a> { } /// Parse an expression + #[inline] pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> { self.parse_expr_res(Restrictions::empty(), None) } @@ -3715,13 +3743,14 @@ impl<'a> Parser<'a> { } /// Parse an expression, subject to the given restrictions + #[inline] fn parse_expr_res(&mut self, r: Restrictions, already_parsed_attrs: Option<ThinVec<Attribute>>) -> PResult<'a, P<Expr>> { self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs)) } - /// Parse the RHS of a local variable declaration (e.g. '= 14;') + /// Parse the RHS of a local variable declaration (e.g., '= 14;') fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> { if self.eat(&token::Eq) { Ok(Some(self.parse_expr()?)) @@ -4103,7 +4132,7 @@ impl<'a> Parser<'a> { self.parse_pat_with_range_pat(true, expected) } - /// Parse a pattern, with a setting whether modern range patterns e.g. `a..=b`, `a..b` are + /// Parse a pattern, with a setting whether modern range patterns e.g., `a..=b`, `a..b` are /// allowed. fn parse_pat_with_range_pat( &mut self, @@ -4445,7 +4474,7 @@ impl<'a> Parser<'a> { } /// Parse a statement. This stops just before trailing semicolons on everything but items. - /// e.g. a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. + /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> { Ok(self.parse_stmt_(true)) } @@ -4598,7 +4627,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; let tokens = if self.check(&token::OpenDelim(token::Brace)) { match self.parse_token_tree() { - TokenTree::Delimited(_, ref delimited) => delimited.stream(), + TokenTree::Delimited(_, _, tts) => tts.stream(), _ => unreachable!(), } } else if self.check(&token::OpenDelim(token::Paren)) { @@ -4609,7 +4638,7 @@ impl<'a> Parser<'a> { self.unexpected()?; unreachable!() }; - TokenStream::concat(vec![ + TokenStream::new(vec![ args.into(), TokenTree::Token(token_lo.to(self.prev_span), token::FatArrow).into(), body.into(), @@ -5042,9 +5071,9 @@ impl<'a> Parser<'a> { // Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. // BOUND = TY_BOUND | LT_BOUND - // LT_BOUND = LIFETIME (e.g. `'a`) + // LT_BOUND = LIFETIME (e.g., `'a`) // TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) - // TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`) + // TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`) fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> { let mut bounds = Vec::new(); loop { @@ -5099,7 +5128,7 @@ impl<'a> Parser<'a> { } // Parse bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. - // BOUND = LT_BOUND (e.g. `'a`) + // BOUND = LT_BOUND (e.g., `'a`) fn parse_lt_param_bounds(&mut self) -> GenericBounds { let mut lifetimes = Vec::new(); while self.check_lifetime() { @@ -5458,7 +5487,7 @@ impl<'a> Parser<'a> { } } } else { - match p.parse_arg_general(named_args) { + match p.parse_arg_general(named_args, false) { Ok(arg) => Ok(Some(arg)), Err(mut e) => { e.emit(); @@ -5508,7 +5537,7 @@ impl<'a> Parser<'a> { _ => unreachable!() }; let isolated_self = |this: &mut Self, n| { - this.look_ahead(n, |t| t.is_keyword(keywords::SelfValue)) && + this.look_ahead(n, |t| t.is_keyword(keywords::SelfLower)) && this.look_ahead(n + 1, |t| t != &token::ModSep) }; @@ -5800,20 +5829,14 @@ impl<'a> Parser<'a> { } fn complain_if_pub_macro(&mut self, vis: &VisibilityKind, sp: Span) { - if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) { - err.emit(); - } - } - - fn complain_if_pub_macro_diag(&mut self, vis: &VisibilityKind, sp: Span) -> PResult<'a, ()> { match *vis { - VisibilityKind::Inherited => Ok(()), + VisibilityKind::Inherited => {} _ => { let is_macro_rules: bool = match self.token { token::Ident(sid, _) => sid.name == Symbol::intern("macro_rules"), _ => false, }; - if is_macro_rules { + let mut err = if is_macro_rules { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); err.span_suggestion_with_applicability( @@ -5822,13 +5845,14 @@ impl<'a> Parser<'a> { "#[macro_export]".to_owned(), Applicability::MaybeIncorrect // speculative ); - Err(err) + err } else { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro invocation with `pub`"); err.help("try adjusting the macro to put `pub` inside the invocation"); - Err(err) - } + err + }; + err.emit(); } } } @@ -6137,9 +6161,6 @@ impl<'a> Parser<'a> { fn consume_block(&mut self, delim: token::DelimToken) { let mut brace_depth = 0; - if !self.eat(&token::OpenDelim(delim)) { - return; - } loop { if self.eat(&token::OpenDelim(delim)) { brace_depth += 1; @@ -6150,7 +6171,7 @@ impl<'a> Parser<'a> { brace_depth -= 1; continue; } - } else if self.eat(&token::Eof) || self.eat(&token::CloseDelim(token::NoDelim)) { + } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) { return; } else { self.bump(); @@ -6282,7 +6303,7 @@ impl<'a> Parser<'a> { /// Parse `pub`, `pub(crate)` and `pub(in path)` plus shortcuts `crate` for `pub(crate)`, /// `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`. - /// If the following element can't be a tuple (i.e. it's a function definition, + /// If the following element can't be a tuple (i.e., it's a function definition, /// it's not a tuple struct field) and the contents within the parens /// isn't valid, emit a proper diagnostic. pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { @@ -6330,7 +6351,7 @@ impl<'a> Parser<'a> { return Ok(vis) } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) && self.look_ahead(1, |t| t.is_keyword(keywords::Super) || - t.is_keyword(keywords::SelfValue)) + t.is_keyword(keywords::SelfLower)) { // `pub(self)` or `pub(super)` self.bump(); // `(` @@ -6434,13 +6455,7 @@ impl<'a> Parser<'a> { } fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> { - let id = match self.token { - token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { - self.bump(); // `_` - ident.gensym() - }, - _ => self.parse_ident()?, - }; + let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; self.expect(&token::Eq)?; @@ -6782,7 +6797,7 @@ impl<'a> Parser<'a> { let error_msg = "crate name using dashes are not valid in `extern crate` statements"; let suggestion_msg = "if the original crate name uses dashes you need to use underscores \ in the code"; - let mut ident = if self.token.is_keyword(keywords::SelfValue) { + let mut ident = if self.token.is_keyword(keywords::SelfLower) { self.parse_path_segment_ident() } else { self.parse_ident() @@ -7405,17 +7420,27 @@ impl<'a> Parser<'a> { return Err(err); } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); + self.bump(); // `(` + let kw_name = if let Ok(Some(_)) = self.parse_self_arg() { + "method" + } else { + "function" + }; self.consume_block(token::Paren); - let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) || - self.check(&token::OpenDelim(token::Brace)) - { - ("fn", "method", false) + let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { + self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.bump(); // `{` + ("fn", kw_name, false) } else if self.check(&token::Colon) { let kw = "struct"; (kw, kw, false) } else { - ("fn` or `struct", "method or struct", true) + ("fn` or `struct", "function or struct", true) }; + self.consume_block(token::Brace); let msg = format!("missing `{}` for {} definition", kw, kw_name); let mut err = self.diagnostic().struct_span_err(sp, &msg); @@ -7442,6 +7467,32 @@ impl<'a> Parser<'a> { } } return Err(err); + } else if self.look_ahead(1, |t| *t == token::Lt) { + let ident = self.parse_ident().unwrap(); + self.eat_to_tokens(&[&token::Gt]); + self.bump(); // `>` + let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { + if let Ok(Some(_)) = self.parse_self_arg() { + ("fn", "method", false) + } else { + ("fn", "function", false) + } + } else if self.check(&token::OpenDelim(token::Brace)) { + ("struct", "struct", false) + } else { + ("fn` or `struct", "function or struct", true) + }; + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.diagnostic().struct_span_err(sp, &msg); + if !ambiguous { + err.span_suggestion_short_with_applicability( + sp, + &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), + format!(" {} ", kw), + Applicability::MachineApplicable, + ); + } + return Err(err); } } self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility) @@ -7685,7 +7736,7 @@ impl<'a> Parser<'a> { let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { prefix.segments.push( - PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) + PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) ); } @@ -7725,13 +7776,7 @@ impl<'a> Parser<'a> { fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> { if self.eat_keyword(keywords::As) { - match self.token { - token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { - self.bump(); // `_` - Ok(Some(ident.gensym())) - } - _ => self.parse_ident().map(Some), - } + self.parse_ident_or_underscore().map(Some) } else { Ok(None) } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 4a5f3e240da..badcc4ed876 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -207,6 +207,10 @@ pub enum Token { Eof, } +// `Token` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Token>() == 16); + impl Token { pub fn interpolated(nt: Nonterminal) -> Token { Token::Interpolated(Lrc::new((nt, LazyTokenStream::new()))) @@ -545,11 +549,12 @@ impl Token { let tokens_for_real = nt.1.force(|| { // FIXME(#43081): Avoid this pretty-print + reparse hack let source = pprust::token_to_string(self); - parse_stream_from_source_str(FileName::MacroExpansion, source, sess, Some(span)) + let filename = FileName::macro_expansion_source_code(&source); + parse_stream_from_source_str(filename, source, sess, Some(span)) }); // During early phases of the compiler the AST could get modified - // directly (e.g. attributes added or removed) and the internal cache + // directly (e.g., attributes added or removed) and the internal cache // of tokens my not be invalidated or updated. Consequently if the // "lossless" token stream disagrees with our actual stringification // (which has historically been much more battle-tested) then we go @@ -628,7 +633,9 @@ impl Token { (&Shebang(a), &Shebang(b)) => a == b, (&Lifetime(a), &Lifetime(b)) => a.name == b.name, - (&Ident(a, b), &Ident(c, d)) => a.name == c.name && b == d, + (&Ident(a, b), &Ident(c, d)) => b == d && (a.name == c.name || + a.name == keywords::DollarCrate.name() || + c.name == keywords::DollarCrate.name()), (&Literal(ref a, b), &Literal(ref c, d)) => { b == d && a.probably_equal_for_proc_macro(c) @@ -781,10 +788,12 @@ fn prepend_attrs(sess: &ParseSess, assert_eq!(attr.style, ast::AttrStyle::Outer, "inner attributes should prevent cached tokens from existing"); + let source = pprust::attr_to_string(attr); + let macro_filename = FileName::macro_expansion_source_code(&source); if attr.is_sugared_doc { let stream = parse_stream_from_source_str( - FileName::MacroExpansion, - pprust::attr_to_string(attr), + macro_filename, + source, sess, Some(span), ); @@ -805,8 +814,8 @@ fn prepend_attrs(sess: &ParseSess, // should eventually be removed. } else { let stream = parse_stream_from_source_str( - FileName::MacroExpansion, - pprust::path_to_string(&attr.path), + macro_filename, + source, sess, Some(span), ); @@ -815,16 +824,13 @@ fn prepend_attrs(sess: &ParseSess, brackets.push(attr.tokens.clone()); - let tokens = tokenstream::Delimited { - delim: DelimToken::Bracket, - tts: brackets.build().into(), - }; // The span we list here for `#` and for `[ ... ]` are both wrong in // that it encompasses more than each token, but it hopefully is "good // enough" for now at least. builder.push(tokenstream::TokenTree::Token(attr.span, Pound)); let delim_span = DelimSpan::from_single(attr.span); - builder.push(tokenstream::TokenTree::Delimited(delim_span, tokens)); + builder.push(tokenstream::TokenTree::Delimited( + delim_span, DelimToken::Bracket, brackets.build().into())); } builder.push(tokens.clone()); Some(builder.build()) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index aaed56da29d..0890be728f3 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -109,7 +109,7 @@ //! The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and //! 'right' indices denote the active portion of the ring buffer as well as //! describing hypothetical points-in-the-infinite-stream at most 3N tokens -//! apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch +//! apart (i.e., "not wrapped to ring-buffer boundaries"). The paper will switch //! between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer //! and point-in-infinite-stream senses freely. //! diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a9f08fdd411..5e7707f4e5c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -16,7 +16,6 @@ use util::parser::{self, AssocOp, Fixity}; use attr; use source_map::{self, SourceMap, Spanned}; use syntax_pos::{self, BytePos}; -use syntax_pos::hygiene::{Mark, SyntaxContext}; use parse::token::{self, BinOpToken, Token}; use parse::lexer::comments; use parse::{self, ParseSess}; @@ -724,12 +723,12 @@ pub trait PrintState<'a> { if i > 0 { self.writer().word("::")? } - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() - { - self.writer().word(segment.ident.as_str().get())?; - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; + if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident)?; + } else { + self.writer().word(segment.ident.as_str().get())?; + } } } Ok(()) @@ -815,12 +814,12 @@ pub trait PrintState<'a> { _ => Ok(()) } } - TokenTree::Delimited(_, ref delimed) => { - self.writer().word(token_to_string(&delimed.open_token()))?; + TokenTree::Delimited(_, delim, tts) => { + self.writer().word(token_to_string(&token::OpenDelim(delim)))?; self.writer().space()?; - self.print_tts(delimed.stream())?; + self.print_tts(tts.stream())?; self.writer().space()?; - self.writer().word(token_to_string(&delimed.close_token())) + self.writer().word(token_to_string(&token::CloseDelim(delim))) }, } } @@ -843,17 +842,19 @@ pub trait PrintState<'a> { fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") } - fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> { - if let Some(mark) = ctxt.adjust(Mark::root()) { - // Make a best effort to print something that complies - if mark.is_builtin() { - if let Some(name) = std_inject::injected_crate_name() { - self.writer().word("::")?; - self.writer().word(name)?; - } - } + // AST pretty-printer is used as a fallback for turning AST structures into token streams for + // proc macros. Additionally, proc macros may stringify their input and expect it survive the + // stringification (especially true for proc macro derives written between Rust 1.15 and 1.30). + // So we need to somehow pretty-print `$crate` in paths in a way preserving at least some of + // its hygiene data, most importantly name of the crate it refers to. + // As a result we print `$crate` as `crate` if it refers to the local crate + // and as `::other_crate_name` if it refers to some other crate. + fn print_dollar_crate(&mut self, ident: ast::Ident) -> io::Result<()> { + let name = ident.span.ctxt().dollar_crate_name(); + if !ast::Ident::with_empty_ctxt(name).is_path_segment_keyword() { + self.writer().word("::")?; } - Ok(()) + self.writer().word(name.as_str().get()) } } @@ -2463,14 +2464,15 @@ impl<'a> State<'a> { colons_before_params: bool) -> io::Result<()> { - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() { - self.print_ident(segment.ident)?; + if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident)?; + } else { + self.print_ident(segment.ident)?; + } if let Some(ref args) = segment.args { self.print_generic_args(args, colons_before_params)?; } - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; } Ok(()) } diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 9fbc64758da..17e7730120f 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -16,11 +16,11 @@ //! # Motivations and benefits //! //! * **Identity**: sharing AST nodes is problematic for the various analysis -//! passes (e.g. one may be able to bypass the borrow checker with a shared +//! passes (e.g., one may be able to bypass the borrow checker with a shared //! `ExprKind::AddrOf` node taking a mutable borrow). The only reason `@T` in the //! AST hasn't caused issues is because of inefficient folding passes which //! would always deduplicate any such shared nodes. Even if the AST were to -//! switch to an arena, this would still hold, i.e. it couldn't use `&'a T`, +//! switch to an arena, this would still hold, i.e., it couldn't use `&'a T`, //! but rather a wrapper like `P<'a, T>`. //! //! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>` @@ -34,7 +34,7 @@ //! * **Maintainability**: `P<T>` provides a fixed interface - `Deref`, //! `and_then` and `map` - which can remain fully functional even if the //! implementation changes (using a special thread-local heap, for example). -//! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated. +//! Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated. use std::fmt::{self, Display, Debug}; use std::iter::FromIterator; diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index e8cacc3b5af..9a343123f61 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -31,7 +31,7 @@ use std::path::{Path, PathBuf}; use std::env; use std::fs; -use std::io::{self, Read}; +use std::io; use errors::SourceMapper; /// Return the span itself if it doesn't come from a macro expansion, @@ -96,9 +96,7 @@ impl FileLoader for RealFileLoader { } fn read_file(&self, path: &Path) -> io::Result<String> { - let mut src = String::new(); - fs::File::open(path)?.read_to_string(&mut src)?; - Ok(src) + fs::read_to_string(path) } } @@ -110,11 +108,19 @@ pub struct StableSourceFileId(u128); impl StableSourceFileId { pub fn new(source_file: &SourceFile) -> StableSourceFileId { + StableSourceFileId::new_from_pieces(&source_file.name, + source_file.name_was_remapped, + source_file.unmapped_path.as_ref()) + } + + pub fn new_from_pieces(name: &FileName, + name_was_remapped: bool, + unmapped_path: Option<&FileName>) -> StableSourceFileId { let mut hasher = StableHasher::new(); - source_file.name.hash(&mut hasher); - source_file.name_was_remapped.hash(&mut hasher); - source_file.unmapped_path.hash(&mut hasher); + name.hash(&mut hasher); + name_was_remapped.hash(&mut hasher); + unmapped_path.hash(&mut hasher); StableSourceFileId(hasher.finish()) } @@ -136,9 +142,6 @@ pub struct SourceMap { // This is used to apply the file path remapping as specified via // --remap-path-prefix to all SourceFiles allocated within this SourceMap. path_mapping: FilePathMapping, - /// In case we are in a doctest, replace all file names with the PathBuf, - /// and add the given offsets to the line info - doctest_offset: Option<(FileName, isize)>, } impl SourceMap { @@ -147,17 +150,7 @@ impl SourceMap { files: Default::default(), file_loader: Box::new(RealFileLoader), path_mapping, - doctest_offset: None, - } - } - - pub fn new_doctest(path_mapping: FilePathMapping, - file: FileName, line: isize) -> SourceMap { - SourceMap { - doctest_offset: Some((file, line)), - ..SourceMap::new(path_mapping) } - } pub fn with_file_loader(file_loader: Box<dyn FileLoader + Sync + Send>, @@ -167,7 +160,6 @@ impl SourceMap { files: Default::default(), file_loader: file_loader, path_mapping, - doctest_offset: None, } } @@ -181,11 +173,7 @@ impl SourceMap { pub fn load_file(&self, path: &Path) -> io::Result<Lrc<SourceFile>> { let src = self.file_loader.read_file(path)?; - let filename = if let Some((ref name, _)) = self.doctest_offset { - name.clone() - } else { - path.to_owned().into() - }; + let filename = path.to_owned().into(); Ok(self.new_source_file(filename, src)) } @@ -208,7 +196,8 @@ impl SourceMap { } /// Creates a new source_file. - /// This does not ensure that only one SourceFile exists per file name. + /// If a file already exists in the source_map with the same id, that file is returned + /// unmodified pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile> { let start_pos = self.next_start_pos(); @@ -226,21 +215,30 @@ impl SourceMap { }, other => (other, false), }; - let source_file = Lrc::new(SourceFile::new( - filename, - was_remapped, - unmapped_path, - src, - Pos::from_usize(start_pos), - )); - let mut files = self.files.borrow_mut(); + let file_id = StableSourceFileId::new_from_pieces(&filename, + was_remapped, + Some(&unmapped_path)); - files.source_files.push(source_file.clone()); - files.stable_id_to_source_file.insert(StableSourceFileId::new(&source_file), - source_file.clone()); + return match self.source_file_by_stable_id(file_id) { + Some(lrc_sf) => lrc_sf, + None => { + let source_file = Lrc::new(SourceFile::new( + filename, + was_remapped, + unmapped_path, + src, + Pos::from_usize(start_pos), + )); - source_file + let mut files = self.files.borrow_mut(); + + files.source_files.push(source_file.clone()); + files.stable_id_to_source_file.insert(file_id, source_file.clone()); + + source_file + } + } } /// Allocates a new SourceFile representing a source file from an external @@ -310,15 +308,17 @@ impl SourceMap { } // If there is a doctest_offset, apply it to the line - pub fn doctest_offset_line(&self, mut orig: usize) -> usize { - if let Some((_, line)) = self.doctest_offset { - if line >= 0 { - orig = orig + line as usize; - } else { - orig = orig - (-line) as usize; - } + pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize { + return match file { + FileName::DocTest(_, offset) => { + return if *offset >= 0 { + orig + *offset as usize + } else { + orig - (-(*offset)) as usize + } + }, + _ => orig } - orig } /// Lookup source information about a BytePos @@ -579,7 +579,7 @@ impl SourceMap { match self.span_to_prev_source(sp) { Err(_) => None, Ok(source) => source.split('\n').last().map(|last_line| { - last_line.len() - last_line.trim_left().len() + last_line.len() - last_line.trim_start().len() }) } } @@ -593,7 +593,7 @@ impl SourceMap { /// if no character could be found or if an error occurred while retrieving the code snippet. pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_left(); + let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_start(); if !prev_source.is_empty() && !prev_source.contains('\n') { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -613,7 +613,7 @@ impl SourceMap { for ws in &[" ", "\t", "\n"] { let pat = pat.to_owned() + ws; if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_left(); + let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_start(); if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -627,7 +627,7 @@ impl SourceMap { pub fn span_until_char(&self, sp: Span, c: char) -> Span { match self.span_to_snippet(sp) { Ok(snippet) => { - let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right(); + let snippet = snippet.split(c).nth(0).unwrap_or("").trim_end(); if !snippet.is_empty() && !snippet.contains('\n') { sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32)) } else { @@ -983,8 +983,8 @@ impl SourceMapper for SourceMap { } ) } - fn doctest_offset_line(&self, line: usize) -> usize { - self.doctest_offset_line(line) + fn doctest_offset_line(&self, file: &FileName, line: usize) -> usize { + self.doctest_offset_line(file, line) } } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 1210f331b28..5c994558ab0 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -112,7 +112,7 @@ pub fn maybe_inject_crates_ref( vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), node: ast::ItemKind::Use(P(ast::UseTree { prefix: ast::Path { - segments: iter::once(keywords::CrateRoot.ident()) + segments: iter::once(keywords::PathRoot.ident()) .chain( [name, "prelude", "v1"].iter().cloned() .map(ast::Ident::from_str) diff --git a/src/libsyntax/str.rs b/src/libsyntax/str.rs deleted file mode 100644 index 281861918fd..00000000000 --- a/src/libsyntax/str.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[inline] -pub fn char_at(s: &str, byte: usize) -> char { - s[byte..].chars().next().unwrap() -} diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 8ff4b0d025c..436a167e6a0 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -281,7 +281,7 @@ fn generate_test_harness(sess: &ParseSess, path: Vec::new(), test_cases: Vec::new(), reexport_test_harness_main, - // NB: doesn't consider the value of `--crate-name` passed on the command line. + // N.B., doesn't consider the value of `--crate-name` passed on the command line. is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false), toplevel_reexport: None, ctxt: SyntaxContext::empty().apply_mark(mark), diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 242299f1b1f..013ecd3d343 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -28,58 +28,12 @@ use ext::tt::{macro_parser, quoted}; use parse::Directory; use parse::token::{self, DelimToken, Token}; use print::pprust; +use rustc_data_structures::sync::Lrc; use serialize::{Decoder, Decodable, Encoder, Encodable}; -use util::RcVec; use std::borrow::Cow; use std::{fmt, iter, mem}; -/// A delimited sequence of token trees -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub struct Delimited { - /// The type of delimiter - pub delim: DelimToken, - /// The delimited sequence of token trees - pub tts: ThinTokenStream, -} - -impl Delimited { - /// Returns the opening delimiter as a token. - pub fn open_token(&self) -> token::Token { - token::OpenDelim(self.delim) - } - - /// Returns the closing delimiter as a token. - pub fn close_token(&self) -> token::Token { - token::CloseDelim(self.delim) - } - - /// Returns the opening delimiter as a token tree. - pub fn open_tt(&self, span: Span) -> TokenTree { - let open_span = if span.is_dummy() { - span - } else { - span.with_hi(span.lo() + BytePos(self.delim.len() as u32)) - }; - TokenTree::Token(open_span, self.open_token()) - } - - /// Returns the closing delimiter as a token tree. - pub fn close_tt(&self, span: Span) -> TokenTree { - let close_span = if span.is_dummy() { - span - } else { - span.with_lo(span.hi() - BytePos(self.delim.len() as u32)) - }; - TokenTree::Token(close_span, self.close_token()) - } - - /// Returns the token trees inside the delimiters. - pub fn stream(&self) -> TokenStream { - self.tts.clone().into() - } -} - /// When the main rust parser encounters a syntax-extension invocation, it /// parses the arguments to the invocation as a token-tree. This is a very /// loose structure, such that all sorts of different AST-fragments can @@ -97,7 +51,7 @@ pub enum TokenTree { /// A single token Token(Span, token::Token), /// A delimited sequence of token trees - Delimited(DelimSpan, Delimited), + Delimited(DelimSpan, DelimToken, ThinTokenStream), } impl TokenTree { @@ -116,9 +70,10 @@ impl TokenTree { pub fn eq_unspanned(&self, other: &TokenTree) -> bool { match (self, other) { (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => tk == tk2, - (&TokenTree::Delimited(_, ref dl), &TokenTree::Delimited(_, ref dl2)) => { - dl.delim == dl2.delim && - dl.stream().eq_unspanned(&dl2.stream()) + (&TokenTree::Delimited(_, delim, ref tts), + &TokenTree::Delimited(_, delim2, ref tts2)) => { + delim == delim2 && + tts.stream().eq_unspanned(&tts2.stream()) } (_, _) => false, } @@ -134,9 +89,10 @@ impl TokenTree { (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => { tk.probably_equal_for_proc_macro(tk2) } - (&TokenTree::Delimited(_, ref dl), &TokenTree::Delimited(_, ref dl2)) => { - dl.delim == dl2.delim && - dl.stream().probably_equal_for_proc_macro(&dl2.stream()) + (&TokenTree::Delimited(_, delim, ref tts), + &TokenTree::Delimited(_, delim2, ref tts2)) => { + delim == delim2 && + tts.stream().probably_equal_for_proc_macro(&tts2.stream()) } (_, _) => false, } @@ -146,7 +102,7 @@ impl TokenTree { pub fn span(&self) -> Span { match *self { TokenTree::Token(sp, _) => sp, - TokenTree::Delimited(sp, _) => sp.entire(), + TokenTree::Delimited(sp, ..) => sp.entire(), } } @@ -154,7 +110,7 @@ impl TokenTree { pub fn set_span(&mut self, span: Span) { match *self { TokenTree::Token(ref mut sp, _) => *sp = span, - TokenTree::Delimited(ref mut sp, _) => *sp = DelimSpan::from_single(span), + TokenTree::Delimited(ref mut sp, ..) => *sp = DelimSpan::from_single(span), } } @@ -167,7 +123,27 @@ impl TokenTree { } pub fn joint(self) -> TokenStream { - TokenStream { kind: TokenStreamKind::JointTree(self) } + TokenStream::JointTree(self) + } + + /// Returns the opening delimiter as a token tree. + pub fn open_tt(span: Span, delim: DelimToken) -> TokenTree { + let open_span = if span.is_dummy() { + span + } else { + span.with_hi(span.lo() + BytePos(delim.len() as u32)) + }; + TokenTree::Token(open_span, token::OpenDelim(delim)) + } + + /// Returns the closing delimiter as a token tree. + pub fn close_tt(span: Span, delim: DelimToken) -> TokenTree { + let close_span = if span.is_dummy() { + span + } else { + span.with_lo(span.hi() - BytePos(delim.len() as u32)) + }; + TokenTree::Token(close_span, token::CloseDelim(delim)) } } @@ -178,61 +154,57 @@ impl TokenTree { /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat. #[derive(Clone, Debug)] -pub struct TokenStream { - kind: TokenStreamKind, +pub enum TokenStream { + Empty, + Tree(TokenTree), + JointTree(TokenTree), + Stream(Lrc<Vec<TokenStream>>), } +// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32); + impl TokenStream { /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` /// separating the two arguments with a comma for diagnostic suggestions. pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> { // Used to suggest if a user writes `foo!(a b);` - if let TokenStreamKind::Stream(ref slice) = self.kind { + if let TokenStream::Stream(ref stream) = self { let mut suggestion = None; - let mut iter = slice.iter().enumerate().peekable(); + let mut iter = stream.iter().enumerate().peekable(); while let Some((pos, ts)) = iter.next() { if let Some((_, next)) = iter.peek() { - let sp = match (&ts.kind, &next.kind) { - (TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma)), _) | - (_, TokenStreamKind::Tree(TokenTree::Token(_, token::Token::Comma))) => { + let sp = match (&ts, &next) { + (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma)), _) | + (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma))) => { continue; } - (TokenStreamKind::Tree(TokenTree::Token(sp, _)), _) => *sp, - (TokenStreamKind::Tree(TokenTree::Delimited(sp, _)), _) => sp.entire(), + (TokenStream::Tree(TokenTree::Token(sp, _)), _) => *sp, + (TokenStream::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(), _ => continue, }; let sp = sp.shrink_to_hi(); - let comma = TokenStream { - kind: TokenStreamKind::Tree(TokenTree::Token(sp, token::Comma)), - }; + let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma)); suggestion = Some((pos, comma, sp)); } } if let Some((pos, comma, sp)) = suggestion { - let mut new_slice = vec![]; - let parts = slice.split_at(pos + 1); - new_slice.extend_from_slice(parts.0); - new_slice.push(comma); - new_slice.extend_from_slice(parts.1); - let slice = RcVec::new(new_slice); - return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, sp)); + let mut new_stream = vec![]; + let parts = stream.split_at(pos + 1); + new_stream.extend_from_slice(parts.0); + new_stream.push(comma); + new_stream.extend_from_slice(parts.1); + return Some((TokenStream::new(new_stream), sp)); } } None } } -#[derive(Clone, Debug)] -enum TokenStreamKind { - Empty, - Tree(TokenTree), - JointTree(TokenTree), - Stream(RcVec<TokenStream>), -} - impl From<TokenTree> for TokenStream { fn from(tt: TokenTree) -> TokenStream { - TokenStream { kind: TokenStreamKind::Tree(tt) } + TokenStream::Tree(tt) } } @@ -244,29 +216,29 @@ impl From<Token> for TokenStream { impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream { fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { - TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>()) + TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<_>>()) } } impl Extend<TokenStream> for TokenStream { fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, iter: I) { let iter = iter.into_iter(); - let kind = mem::replace(&mut self.kind, TokenStreamKind::Empty); + let this = mem::replace(self, TokenStream::Empty); // Vector of token streams originally in self. - let tts: Vec<TokenStream> = match kind { - TokenStreamKind::Empty => { + let tts: Vec<TokenStream> = match this { + TokenStream::Empty => { let mut vec = Vec::new(); vec.reserve(iter.size_hint().0); vec } - TokenStreamKind::Tree(_) | TokenStreamKind::JointTree(_) => { + TokenStream::Tree(_) | TokenStream::JointTree(_) => { let mut vec = Vec::new(); vec.reserve(1 + iter.size_hint().0); - vec.push(TokenStream { kind }); + vec.push(this); vec } - TokenStreamKind::Stream(rc_vec) => match RcVec::try_unwrap(rc_vec) { + TokenStream::Stream(rc_vec) => match Lrc::try_unwrap(rc_vec) { Ok(mut vec) => { // Extend in place using the existing capacity if possible. // This is the fast path for libraries like `quote` that @@ -293,12 +265,7 @@ impl Extend<TokenStream> for TokenStream { // Build the resulting token stream. If it contains more than one token, // preserve capacity in the vector in anticipation of the caller // performing additional calls to extend. - let mut tts = builder.0; - *self = match tts.len() { - 0 => TokenStream::empty(), - 1 => tts.pop().unwrap(), - _ => TokenStream::concat_rc_vec(RcVec::new_preserving_capacity(tts)), - }; + *self = TokenStream::new(builder.0); } } @@ -312,7 +279,7 @@ impl PartialEq<TokenStream> for TokenStream { impl TokenStream { pub fn len(&self) -> usize { - if let TokenStreamKind::Stream(ref slice) = self.kind { + if let TokenStream::Stream(ref slice) = self { slice.len() } else { 0 @@ -320,28 +287,24 @@ impl TokenStream { } pub fn empty() -> TokenStream { - TokenStream { kind: TokenStreamKind::Empty } + TokenStream::Empty } pub fn is_empty(&self) -> bool { - match self.kind { - TokenStreamKind::Empty => true, + match self { + TokenStream::Empty => true, _ => false, } } - pub fn concat(mut streams: Vec<TokenStream>) -> TokenStream { + pub fn new(mut streams: Vec<TokenStream>) -> TokenStream { match streams.len() { 0 => TokenStream::empty(), 1 => streams.pop().unwrap(), - _ => TokenStream::concat_rc_vec(RcVec::new(streams)), + _ => TokenStream::Stream(Lrc::new(streams)), } } - fn concat_rc_vec(streams: RcVec<TokenStream>) -> TokenStream { - TokenStream { kind: TokenStreamKind::Stream(streams) } - } - pub fn trees(&self) -> Cursor { self.clone().into_trees() } @@ -385,7 +348,9 @@ impl TokenStream { | TokenTree::Token(_, Token::Semi) // The pretty printer collapses whitespace arbitrarily and can // introduce whitespace from `NoDelim`. - | TokenTree::Token(_, Token::Whitespace) => false, + | TokenTree::Token(_, Token::Whitespace) + // The pretty printer can turn `$crate` into `::crate_name` + | TokenTree::Token(_, Token::ModSep) => false, _ => true } } @@ -403,9 +368,9 @@ impl TokenStream { /// Precondition: `self` consists of a single token tree. /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`. pub fn as_tree(self) -> (TokenTree, bool /* joint? */) { - match self.kind { - TokenStreamKind::Tree(tree) => (tree, false), - TokenStreamKind::JointTree(tree) => (tree, true), + match self { + TokenStream::Tree(tree) => (tree, false), + TokenStream::JointTree(tree) => (tree, true), _ => unreachable!(), } } @@ -415,43 +380,43 @@ impl TokenStream { let mut result = Vec::new(); let mut i = 0; while let Some(stream) = trees.next_as_stream() { - result.push(match stream.kind { - TokenStreamKind::Tree(tree) => f(i, tree).into(), - TokenStreamKind::JointTree(tree) => f(i, tree).joint(), + result.push(match stream { + TokenStream::Tree(tree) => f(i, tree).into(), + TokenStream::JointTree(tree) => f(i, tree).joint(), _ => unreachable!() }); i += 1; } - TokenStream::concat(result) + TokenStream::new(result) } pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream { let mut trees = self.into_trees(); let mut result = Vec::new(); while let Some(stream) = trees.next_as_stream() { - result.push(match stream.kind { - TokenStreamKind::Tree(tree) => f(tree).into(), - TokenStreamKind::JointTree(tree) => f(tree).joint(), + result.push(match stream { + TokenStream::Tree(tree) => f(tree).into(), + TokenStream::JointTree(tree) => f(tree).joint(), _ => unreachable!() }); } - TokenStream::concat(result) + TokenStream::new(result) } fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> { - match self.kind { - TokenStreamKind::Empty => None, - TokenStreamKind::Tree(ref tree) => Some((tree.clone(), false)), - TokenStreamKind::JointTree(ref tree) => Some((tree.clone(), true)), - TokenStreamKind::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(), + match self { + TokenStream::Empty => None, + TokenStream::Tree(ref tree) => Some((tree.clone(), false)), + TokenStream::JointTree(ref tree) => Some((tree.clone(), true)), + TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(), } } fn last_tree_if_joint(&self) -> Option<TokenTree> { - match self.kind { - TokenStreamKind::Empty | TokenStreamKind::Tree(..) => None, - TokenStreamKind::JointTree(ref tree) => Some(tree.clone()), - TokenStreamKind::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), + match self { + TokenStream::Empty | TokenStream::Tree(..) => None, + TokenStream::JointTree(ref tree) => Some(tree.clone()), + TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), } } } @@ -494,28 +459,28 @@ impl TokenStreamBuilder { } pub fn build(self) -> TokenStream { - TokenStream::concat(self.0) + TokenStream::new(self.0) } fn push_all_but_last_tree(&mut self, stream: &TokenStream) { - if let TokenStreamKind::Stream(ref streams) = stream.kind { + if let TokenStream::Stream(ref streams) = stream { let len = streams.len(); match len { 1 => {} 2 => self.0.push(streams[0].clone().into()), - _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(0 .. len - 1))), + _ => self.0.push(TokenStream::new(streams[0 .. len - 1].to_vec())), } self.push_all_but_last_tree(&streams[len - 1]) } } fn push_all_but_first_tree(&mut self, stream: &TokenStream) { - if let TokenStreamKind::Stream(ref streams) = stream.kind { + if let TokenStream::Stream(ref streams) = stream { let len = streams.len(); match len { 1 => {} 2 => self.0.push(streams[1].clone().into()), - _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(1 .. len))), + _ => self.0.push(TokenStream::new(streams[1 .. len].to_vec())), } self.push_all_but_first_tree(&streams[0]) } @@ -535,13 +500,13 @@ enum CursorKind { #[derive(Clone)] struct StreamCursor { - stream: RcVec<TokenStream>, + stream: Lrc<Vec<TokenStream>>, index: usize, - stack: Vec<(RcVec<TokenStream>, usize)>, + stack: Vec<(Lrc<Vec<TokenStream>>, usize)>, } impl StreamCursor { - fn new(stream: RcVec<TokenStream>) -> Self { + fn new(stream: Lrc<Vec<TokenStream>>) -> Self { StreamCursor { stream: stream, index: 0, stack: Vec::new() } } @@ -550,10 +515,10 @@ impl StreamCursor { if self.index < self.stream.len() { self.index += 1; let next = self.stream[self.index - 1].clone(); - match next.kind { - TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => return Some(next), - TokenStreamKind::Stream(stream) => self.insert(stream), - TokenStreamKind::Empty => {} + match next { + TokenStream::Tree(..) | TokenStream::JointTree(..) => return Some(next), + TokenStream::Stream(stream) => self.insert(stream), + TokenStream::Empty => {} } } else if let Some((stream, index)) = self.stack.pop() { self.stream = stream; @@ -564,7 +529,7 @@ impl StreamCursor { } } - fn insert(&mut self, stream: RcVec<TokenStream>) { + fn insert(&mut self, stream: Lrc<Vec<TokenStream>>) { self.stack.push((mem::replace(&mut self.stream, stream), mem::replace(&mut self.index, 0))); } @@ -574,8 +539,8 @@ impl Iterator for Cursor { type Item = TokenTree; fn next(&mut self) -> Option<TokenTree> { - self.next_as_stream().map(|stream| match stream.kind { - TokenStreamKind::Tree(tree) | TokenStreamKind::JointTree(tree) => tree, + self.next_as_stream().map(|stream| match stream { + TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree, _ => unreachable!() }) } @@ -583,11 +548,11 @@ impl Iterator for Cursor { impl Cursor { fn new(stream: TokenStream) -> Self { - Cursor(match stream.kind { - TokenStreamKind::Empty => CursorKind::Empty, - TokenStreamKind::Tree(tree) => CursorKind::Tree(tree, false), - TokenStreamKind::JointTree(tree) => CursorKind::JointTree(tree, false), - TokenStreamKind::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), + Cursor(match stream { + TokenStream::Empty => CursorKind::Empty, + TokenStream::Tree(tree) => CursorKind::Tree(tree, false), + TokenStream::JointTree(tree) => CursorKind::JointTree(tree, false), + TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), }) } @@ -610,7 +575,7 @@ impl Cursor { _ if stream.is_empty() => return, CursorKind::Empty => *self = stream.trees(), CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => { - *self = TokenStream::concat(vec![self.original_stream(), stream]).trees(); + *self = TokenStream::new(vec![self.original_stream(), stream]).trees(); if consumed { self.next(); } @@ -626,21 +591,21 @@ impl Cursor { CursorKind::Empty => TokenStream::empty(), CursorKind::Tree(ref tree, _) => tree.clone().into(), CursorKind::JointTree(ref tree, _) => tree.clone().joint(), - CursorKind::Stream(ref cursor) => TokenStream::concat_rc_vec({ + CursorKind::Stream(ref cursor) => TokenStream::Stream( cursor.stack.get(0).cloned().map(|(stream, _)| stream) .unwrap_or_else(|| cursor.stream.clone()) - }), + ), } } pub fn look_ahead(&self, n: usize) -> Option<TokenTree> { fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize> { for stream in streams { - n = match stream.kind { - TokenStreamKind::Tree(ref tree) | TokenStreamKind::JointTree(ref tree) + n = match stream { + TokenStream::Tree(ref tree) | TokenStream::JointTree(ref tree) if n == 0 => return Ok(tree.clone()), - TokenStreamKind::Tree(..) | TokenStreamKind::JointTree(..) => n - 1, - TokenStreamKind::Stream(ref stream) => match look_ahead(stream, n) { + TokenStream::Tree(..) | TokenStream::JointTree(..) => n - 1, + TokenStream::Stream(ref stream) => match look_ahead(stream, n) { Ok(tree) => return Ok(tree), Err(n) => n, }, @@ -676,22 +641,28 @@ impl Cursor { /// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`. /// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion. #[derive(Debug, Clone)] -pub struct ThinTokenStream(Option<RcVec<TokenStream>>); +pub struct ThinTokenStream(Option<Lrc<Vec<TokenStream>>>); + +impl ThinTokenStream { + pub fn stream(&self) -> TokenStream { + self.clone().into() + } +} impl From<TokenStream> for ThinTokenStream { fn from(stream: TokenStream) -> ThinTokenStream { - ThinTokenStream(match stream.kind { - TokenStreamKind::Empty => None, - TokenStreamKind::Tree(tree) => Some(RcVec::new(vec![tree.into()])), - TokenStreamKind::JointTree(tree) => Some(RcVec::new(vec![tree.joint()])), - TokenStreamKind::Stream(stream) => Some(stream), + ThinTokenStream(match stream { + TokenStream::Empty => None, + TokenStream::Tree(tree) => Some(Lrc::new(vec![tree.into()])), + TokenStream::JointTree(tree) => Some(Lrc::new(vec![tree.joint()])), + TokenStream::Stream(stream) => Some(stream), }) } } impl From<ThinTokenStream> for TokenStream { fn from(stream: ThinTokenStream) -> TokenStream { - stream.0.map(TokenStream::concat_rc_vec).unwrap_or_else(TokenStream::empty) + stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty) } } @@ -790,7 +761,7 @@ mod tests { let test_res = string_to_ts("foo::bar::baz"); let test_fst = string_to_ts("foo::bar"); let test_snd = string_to_ts("::baz"); - let eq_res = TokenStream::concat(vec![test_fst, test_snd]); + let eq_res = TokenStream::new(vec![test_fst, test_snd]); assert_eq!(test_res.trees().count(), 5); assert_eq!(eq_res.trees().count(), 5); assert_eq!(test_res.eq_unspanned(&eq_res), true); diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs index feee2422cb6..e6b81a59d86 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -20,7 +20,7 @@ pub fn lev_distance(a: &str, b: &str) -> usize { return a.chars().count(); } - let mut dcol: Vec<_> = (0..b.len() + 1).collect(); + let mut dcol: Vec<_> = (0..=b.len()).collect(); let mut t_last = 0; for (i, sc) in a.chars().enumerate() { @@ -38,7 +38,8 @@ pub fn lev_distance(a: &str, b: &str) -> usize { current = next; t_last = j; } - } dcol[t_last + 1] + } + dcol[t_last + 1] } /// Find the best match for a given word in the given iterator diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index 6866806cd7c..b7cd2acf8a5 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -340,8 +340,8 @@ impl ExprPrecedence { } -/// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any -/// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and +/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any +/// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not. pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { match value.node { diff --git a/src/libsyntax/util/rc_slice.rs b/src/libsyntax/util/rc_slice.rs deleted file mode 100644 index 520b7a48e30..00000000000 --- a/src/libsyntax/util/rc_slice.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::fmt; -use std::ops::{Deref, Range}; -use rustc_data_structures::sync::Lrc; - -use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, - HashStable}; - -#[derive(Clone)] -pub struct RcSlice<T> { - data: Lrc<Box<[T]>>, - offset: u32, - len: u32, -} - -impl<T> RcSlice<T> { - pub fn new(vec: Vec<T>) -> Self { - RcSlice { - offset: 0, - len: vec.len() as u32, - data: Lrc::new(vec.into_boxed_slice()), - } - } - - pub fn sub_slice(&self, range: Range<usize>) -> Self { - RcSlice { - data: self.data.clone(), - offset: self.offset + range.start as u32, - len: (range.end - range.start) as u32, - } - } -} - -impl<T> Deref for RcSlice<T> { - type Target = [T]; - fn deref(&self) -> &[T] { - &self.data[self.offset as usize .. (self.offset + self.len) as usize] - } -} - -impl<T: fmt::Debug> fmt::Debug for RcSlice<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.deref(), f) - } -} - -impl<CTX, T> HashStable<CTX> for RcSlice<T> - where T: HashStable<CTX> -{ - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut CTX, - hasher: &mut StableHasher<W>) { - (**self).hash_stable(hcx, hasher); - } -} diff --git a/src/libsyntax/util/rc_vec.rs b/src/libsyntax/util/rc_vec.rs deleted file mode 100644 index 99fbce1ad91..00000000000 --- a/src/libsyntax/util/rc_vec.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::fmt; -use std::ops::{Deref, Range}; - -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; -use rustc_data_structures::sync::Lrc; - -#[derive(Clone)] -pub struct RcVec<T> { - data: Lrc<Vec<T>>, - offset: u32, - len: u32, -} - -impl<T> RcVec<T> { - pub fn new(mut vec: Vec<T>) -> Self { - // By default, constructing RcVec from Vec gives it just enough capacity - // to hold the initial elements. Callers that anticipate needing to - // extend the vector may prefer RcVec::new_preserving_capacity. - vec.shrink_to_fit(); - Self::new_preserving_capacity(vec) - } - - pub fn new_preserving_capacity(vec: Vec<T>) -> Self { - RcVec { - offset: 0, - len: vec.len() as u32, - data: Lrc::new(vec), - } - } - - pub fn sub_slice(&self, range: Range<usize>) -> Self { - RcVec { - data: self.data.clone(), - offset: self.offset + range.start as u32, - len: (range.end - range.start) as u32, - } - } - - /// If this RcVec has exactly one strong reference, returns ownership of the - /// underlying vector. Otherwise returns self unmodified. - pub fn try_unwrap(self) -> Result<Vec<T>, Self> { - match Lrc::try_unwrap(self.data) { - // If no other RcVec shares ownership of this data. - Ok(mut vec) => { - // Drop any elements after our view of the data. - vec.truncate(self.offset as usize + self.len as usize); - // Drop any elements before our view of the data. Do this after - // the `truncate` so that elements past the end of our view do - // not need to be copied around. - vec.drain(..self.offset as usize); - Ok(vec) - } - - // If the data is shared. - Err(data) => Err(RcVec { data, ..self }), - } - } -} - -impl<T> Deref for RcVec<T> { - type Target = [T]; - fn deref(&self) -> &[T] { - &self.data[self.offset as usize..(self.offset + self.len) as usize] - } -} - -impl<T: fmt::Debug> fmt::Debug for RcVec<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.deref(), f) - } -} - -impl<CTX, T> HashStable<CTX> for RcVec<T> -where - T: HashStable<CTX>, -{ - fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) { - (**self).hash_stable(hcx, hasher); - } -} diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 77311bf53fd..6747598f375 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -43,7 +43,7 @@ pub enum FnKind<'a> { /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; -/// e.g. the `visit_mod` method by default calls `visit::walk_mod`. +/// e.g., the `visit_mod` method by default calls `visit::walk_mod`. /// /// If you want to ensure that your code handles every variant /// explicitly, you need to override each method. (And you also need @@ -110,7 +110,7 @@ pub trait Visitor<'ast>: Sized { } fn visit_mac(&mut self, _mac: &'ast Mac) { panic!("visit_mac disabled by default"); - // NB: see note about macros above. + // N.B., see note about macros above. // if you really want a visitor that // works on macros, use this // definition in your trait impl: @@ -841,7 +841,7 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) { match tt { TokenTree::Token(_, tok) => visitor.visit_token(tok), - TokenTree::Delimited(_, delimed) => visitor.visit_tts(delimed.stream()), + TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts.stream()), } } |
