Aggregation of cosmetic changes made during work on REPL PRs: libsyntax
This commit is contained in:
parent
ef54f57c5b
commit
49d2fd1725
26 changed files with 538 additions and 524 deletions
|
@ -413,11 +413,11 @@ impl WherePredicate {
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct WhereBoundPredicate {
|
pub struct WhereBoundPredicate {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// Any generics from a `for` binding
|
/// Any generics from a `for` binding.
|
||||||
pub bound_generic_params: Vec<GenericParam>,
|
pub bound_generic_params: Vec<GenericParam>,
|
||||||
/// The type being bounded
|
/// The type being bounded.
|
||||||
pub bounded_ty: P<Ty>,
|
pub bounded_ty: P<Ty>,
|
||||||
/// Trait and lifetime bounds (`Clone+Send+'static`)
|
/// Trait and lifetime bounds (`Clone + Send + 'static`).
|
||||||
pub bounds: GenericBounds,
|
pub bounds: GenericBounds,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,15 +495,15 @@ pub enum MetaItemKind {
|
||||||
NameValue(Lit),
|
NameValue(Lit),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Block (`{ .. }`).
|
/// A block (`{ .. }`).
|
||||||
///
|
///
|
||||||
/// E.g., `{ .. }` as in `fn foo() { .. }`.
|
/// E.g., `{ .. }` as in `fn foo() { .. }`.
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
/// Statements in a block
|
/// The statements in the block.
|
||||||
pub stmts: Vec<Stmt>,
|
pub stmts: Vec<Stmt>,
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
/// Distinguishes between `unsafe { ... }` and `{ ... }`
|
/// Distinguishes between `unsafe { ... }` and `{ ... }`.
|
||||||
pub rules: BlockCheckMode,
|
pub rules: BlockCheckMode,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
@ -908,11 +908,11 @@ pub enum MacStmtStyle {
|
||||||
/// 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)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct Local {
|
pub struct Local {
|
||||||
|
pub id: NodeId,
|
||||||
pub pat: P<Pat>,
|
pub pat: P<Pat>,
|
||||||
pub ty: Option<P<Ty>>,
|
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 init: Option<P<Expr>>,
|
||||||
pub id: NodeId,
|
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub attrs: ThinVec<Attribute>,
|
pub attrs: ThinVec<Attribute>,
|
||||||
}
|
}
|
||||||
|
@ -970,7 +970,7 @@ pub struct AnonConst {
|
||||||
pub value: P<Expr>,
|
pub value: P<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An expression
|
/// An expression.
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Expr {
|
pub struct Expr {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
|
@ -984,26 +984,26 @@ pub struct Expr {
|
||||||
static_assert_size!(Expr, 96);
|
static_assert_size!(Expr, 96);
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
/// Whether this expression would be valid somewhere that expects a value; for example, an `if`
|
/// Returns `true` if this expression would be valid somewhere that expects a value;
|
||||||
/// condition.
|
/// for example, an `if` condition.
|
||||||
pub fn returns(&self) -> bool {
|
pub fn returns(&self) -> bool {
|
||||||
if let ExprKind::Block(ref block, _) = self.node {
|
if let ExprKind::Block(ref block, _) = self.node {
|
||||||
match block.stmts.last().map(|last_stmt| &last_stmt.node) {
|
match block.stmts.last().map(|last_stmt| &last_stmt.node) {
|
||||||
// implicit return
|
// Implicit return
|
||||||
Some(&StmtKind::Expr(_)) => true,
|
Some(&StmtKind::Expr(_)) => true,
|
||||||
Some(&StmtKind::Semi(ref expr)) => {
|
Some(&StmtKind::Semi(ref expr)) => {
|
||||||
if let ExprKind::Ret(_) = expr.node {
|
if let ExprKind::Ret(_) = expr.node {
|
||||||
// last statement is explicit return
|
// Last statement is explicit return.
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This is a block that doesn't end in either an implicit or explicit return
|
// This is a block that doesn't end in either an implicit or explicit return.
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is not a block, it is a value
|
// This is not a block, it is a value.
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2307,37 +2307,37 @@ impl Default for FnHeader {
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum ItemKind {
|
pub enum ItemKind {
|
||||||
/// An `extern crate` item, with optional *original* crate name if the crate was renamed.
|
/// An `extern crate` item, with the 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>),
|
ExternCrate(Option<Name>),
|
||||||
/// A use declaration (`use` or `pub use`) item.
|
/// A use declaration item (`use`).
|
||||||
///
|
///
|
||||||
/// 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>),
|
Use(P<UseTree>),
|
||||||
/// A static item (`static` or `pub static`).
|
/// A static item (`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>),
|
Static(P<Ty>, Mutability, P<Expr>),
|
||||||
/// A constant item (`const` or `pub const`).
|
/// A constant item (`const`).
|
||||||
///
|
///
|
||||||
/// E.g., `const FOO: i32 = 42;`.
|
/// E.g., `const FOO: i32 = 42;`.
|
||||||
Const(P<Ty>, P<Expr>),
|
Const(P<Ty>, P<Expr>),
|
||||||
/// A function declaration (`fn` or `pub fn`).
|
/// A function declaration (`fn`).
|
||||||
///
|
///
|
||||||
/// E.g., `fn foo(bar: usize) -> usize { .. }`.
|
/// E.g., `fn foo(bar: usize) -> usize { .. }`.
|
||||||
Fn(P<FnDecl>, FnHeader, Generics, P<Block>),
|
Fn(P<FnDecl>, FnHeader, Generics, P<Block>),
|
||||||
/// A module declaration (`mod` or `pub mod`).
|
/// A module declaration (`mod`).
|
||||||
///
|
///
|
||||||
/// E.g., `mod foo;` or `mod foo { .. }`.
|
/// E.g., `mod foo;` or `mod foo { .. }`.
|
||||||
Mod(Mod),
|
Mod(Mod),
|
||||||
/// An external module (`extern` or `pub extern`).
|
/// An external module (`extern`).
|
||||||
///
|
///
|
||||||
/// E.g., `extern {}` or `extern "C" {}`.
|
/// E.g., `extern {}` or `extern "C" {}`.
|
||||||
ForeignMod(ForeignMod),
|
ForeignMod(ForeignMod),
|
||||||
/// Module-level inline assembly (from `global_asm!()`).
|
/// Module-level inline assembly (from `global_asm!()`).
|
||||||
GlobalAsm(P<GlobalAsm>),
|
GlobalAsm(P<GlobalAsm>),
|
||||||
/// A type alias (`type` or `pub type`).
|
/// A type alias (`type`).
|
||||||
///
|
///
|
||||||
/// E.g., `type Foo = Bar<u8>;`.
|
/// E.g., `type Foo = Bar<u8>;`.
|
||||||
TyAlias(P<Ty>, Generics),
|
TyAlias(P<Ty>, Generics),
|
||||||
|
@ -2345,19 +2345,19 @@ pub enum ItemKind {
|
||||||
///
|
///
|
||||||
/// E.g., `type Foo = impl Bar + Boo;`.
|
/// E.g., `type Foo = impl Bar + Boo;`.
|
||||||
OpaqueTy(GenericBounds, Generics),
|
OpaqueTy(GenericBounds, Generics),
|
||||||
/// An enum definition (`enum` or `pub enum`).
|
/// An enum definition (`enum`).
|
||||||
///
|
///
|
||||||
/// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
|
/// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
|
||||||
Enum(EnumDef, Generics),
|
Enum(EnumDef, Generics),
|
||||||
/// A struct definition (`struct` or `pub struct`).
|
/// A struct definition (`struct`).
|
||||||
///
|
///
|
||||||
/// E.g., `struct Foo<A> { x: A }`.
|
/// E.g., `struct Foo<A> { x: A }`.
|
||||||
Struct(VariantData, Generics),
|
Struct(VariantData, Generics),
|
||||||
/// A union definition (`union` or `pub union`).
|
/// A union definition (`union`).
|
||||||
///
|
///
|
||||||
/// E.g., `union Foo<A, B> { x: A, y: B }`.
|
/// E.g., `union Foo<A, B> { x: A, y: B }`.
|
||||||
Union(VariantData, Generics),
|
Union(VariantData, Generics),
|
||||||
/// A Trait declaration (`trait` or `pub trait`).
|
/// A trait declaration (`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(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Functions dealing with attributes and meta items
|
//! Functions dealing with attributes and meta items.
|
||||||
|
|
||||||
mod builtin;
|
mod builtin;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ pub fn is_known_lint_tool(m_item: Ident) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedMetaItem {
|
impl NestedMetaItem {
|
||||||
/// Returns the MetaItem if self is a NestedMetaItem::MetaItem.
|
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
|
||||||
pub fn meta_item(&self) -> Option<&MetaItem> {
|
pub fn meta_item(&self) -> Option<&MetaItem> {
|
||||||
match *self {
|
match *self {
|
||||||
NestedMetaItem::MetaItem(ref item) => Some(item),
|
NestedMetaItem::MetaItem(ref item) => Some(item),
|
||||||
|
@ -69,7 +69,7 @@ impl NestedMetaItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Lit if self is a NestedMetaItem::Literal.
|
/// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s.
|
||||||
pub fn literal(&self) -> Option<&Lit> {
|
pub fn literal(&self) -> Option<&Lit> {
|
||||||
match *self {
|
match *self {
|
||||||
NestedMetaItem::Literal(ref lit) => Some(lit),
|
NestedMetaItem::Literal(ref lit) => Some(lit),
|
||||||
|
@ -82,7 +82,7 @@ impl NestedMetaItem {
|
||||||
self.meta_item().map_or(false, |meta_item| meta_item.check_name(name))
|
self.meta_item().map_or(false, |meta_item| meta_item.check_name(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a single-segment meta-item returns its name, otherwise returns `None`.
|
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||||
pub fn ident(&self) -> Option<Ident> {
|
pub fn ident(&self) -> Option<Ident> {
|
||||||
self.meta_item().and_then(|meta_item| meta_item.ident())
|
self.meta_item().and_then(|meta_item| meta_item.ident())
|
||||||
}
|
}
|
||||||
|
@ -90,13 +90,13 @@ impl NestedMetaItem {
|
||||||
self.ident().unwrap_or(Ident::invalid()).name
|
self.ident().unwrap_or(Ident::invalid()).name
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the string value if self is a MetaItem and the MetaItem is a
|
/// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
|
||||||
/// MetaItemKind::NameValue variant containing a string, otherwise None.
|
/// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
|
||||||
pub fn value_str(&self) -> Option<Symbol> {
|
pub fn value_str(&self) -> Option<Symbol> {
|
||||||
self.meta_item().and_then(|meta_item| meta_item.value_str())
|
self.meta_item().and_then(|meta_item| meta_item.value_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a name and single literal value tuple of the MetaItem.
|
/// Returns a name and single literal value tuple of the `MetaItem`.
|
||||||
pub fn name_value_literal(&self) -> Option<(Name, &Lit)> {
|
pub fn name_value_literal(&self) -> Option<(Name, &Lit)> {
|
||||||
self.meta_item().and_then(
|
self.meta_item().and_then(
|
||||||
|meta_item| meta_item.meta_item_list().and_then(
|
|meta_item| meta_item.meta_item_list().and_then(
|
||||||
|
@ -112,32 +112,32 @@ impl NestedMetaItem {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a list of inner meta items from a list MetaItem type.
|
/// Gets a list of inner meta items from a list `MetaItem` type.
|
||||||
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
|
||||||
self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
|
self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the variant is MetaItem.
|
/// Returns `true` if the variant is `MetaItem`.
|
||||||
pub fn is_meta_item(&self) -> bool {
|
pub fn is_meta_item(&self) -> bool {
|
||||||
self.meta_item().is_some()
|
self.meta_item().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the variant is Literal.
|
/// Returns `true` if the variant is `Literal`.
|
||||||
pub fn is_literal(&self) -> bool {
|
pub fn is_literal(&self) -> bool {
|
||||||
self.literal().is_some()
|
self.literal().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if self is a MetaItem and the meta item is a word.
|
/// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
|
||||||
pub fn is_word(&self) -> bool {
|
pub fn is_word(&self) -> bool {
|
||||||
self.meta_item().map_or(false, |meta_item| meta_item.is_word())
|
self.meta_item().map_or(false, |meta_item| meta_item.is_word())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if self is a MetaItem and the meta item is a ValueString.
|
/// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`.
|
||||||
pub fn is_value_str(&self) -> bool {
|
pub fn is_value_str(&self) -> bool {
|
||||||
self.value_str().is_some()
|
self.value_str().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if self is a MetaItem and the meta item is a list.
|
/// Returns `true` if `self` is a `MetaItem` and the meta item is a list.
|
||||||
pub fn is_meta_item_list(&self) -> bool {
|
pub fn is_meta_item_list(&self) -> bool {
|
||||||
self.meta_item_list().is_some()
|
self.meta_item_list().is_some()
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ impl Attribute {
|
||||||
matches
|
matches
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a single-segment attribute returns its name, otherwise returns `None`.
|
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
|
||||||
pub fn ident(&self) -> Option<Ident> {
|
pub fn ident(&self) -> Option<Ident> {
|
||||||
if self.path.segments.len() == 1 {
|
if self.path.segments.len() == 1 {
|
||||||
Some(self.path.segments[0].ident)
|
Some(self.path.segments[0].ident)
|
||||||
|
@ -187,14 +187,14 @@ impl Attribute {
|
||||||
self.meta_item_list().is_some()
|
self.meta_item_list().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates if the attribute is a Value String.
|
/// Indicates if the attribute is a `ValueString`.
|
||||||
pub fn is_value_str(&self) -> bool {
|
pub fn is_value_str(&self) -> bool {
|
||||||
self.value_str().is_some()
|
self.value_str().is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaItem {
|
impl MetaItem {
|
||||||
/// For a single-segment meta-item returns its name, otherwise returns `None`.
|
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||||
pub fn ident(&self) -> Option<Ident> {
|
pub fn ident(&self) -> Option<Ident> {
|
||||||
if self.path.segments.len() == 1 {
|
if self.path.segments.len() == 1 {
|
||||||
Some(self.path.segments[0].ident)
|
Some(self.path.segments[0].ident)
|
||||||
|
@ -206,8 +206,9 @@ impl MetaItem {
|
||||||
self.ident().unwrap_or(Ident::invalid()).name
|
self.ident().unwrap_or(Ident::invalid()).name
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[attribute(name = "value")]
|
// Example:
|
||||||
// ^^^^^^^^^^^^^^
|
// #[attribute(name = "value")]
|
||||||
|
// ^^^^^^^^^^^^^^
|
||||||
pub fn name_value_literal(&self) -> Option<&Lit> {
|
pub fn name_value_literal(&self) -> Option<&Lit> {
|
||||||
match &self.node {
|
match &self.node {
|
||||||
MetaItemKind::NameValue(v) => Some(v),
|
MetaItemKind::NameValue(v) => Some(v),
|
||||||
|
@ -255,7 +256,7 @@ impl MetaItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attribute {
|
impl Attribute {
|
||||||
/// Extracts the MetaItem from inside this Attribute.
|
/// Extracts the `MetaItem` from inside this `Attribute`.
|
||||||
pub fn meta(&self) -> Option<MetaItem> {
|
pub fn meta(&self) -> Option<MetaItem> {
|
||||||
let mut tokens = self.tokens.trees().peekable();
|
let mut tokens = self.tokens.trees().peekable();
|
||||||
Some(MetaItem {
|
Some(MetaItem {
|
||||||
|
@ -318,8 +319,8 @@ impl Attribute {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts self to a normal #[doc="foo"] comment, if it is a
|
/// Converts `self` to a normal `#[doc="foo"]` comment, if it is a
|
||||||
/// comment like `///` or `/** */`. (Returns self unchanged for
|
/// comment like `///` or `/** */`. (Returns `self` unchanged for
|
||||||
/// non-sugared doc attributes.)
|
/// non-sugared doc attributes.)
|
||||||
pub fn with_desugared_doc<T, F>(&self, f: F) -> T where
|
pub fn with_desugared_doc<T, F>(&self, f: F) -> T where
|
||||||
F: FnOnce(&Attribute) -> T,
|
F: FnOnce(&Attribute) -> T,
|
||||||
|
|
|
@ -958,7 +958,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
self.resolver.check_unused_macros();
|
self.resolver.check_unused_macros();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve a path mentioned inside Rust code.
|
/// Resolves a path mentioned inside Rust code.
|
||||||
///
|
///
|
||||||
/// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
|
/// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
//! List of the active feature gates.
|
//! List of the active feature gates.
|
||||||
|
|
||||||
|
use super::{State, Feature};
|
||||||
|
|
||||||
use crate::edition::Edition;
|
use crate::edition::Edition;
|
||||||
use crate::symbol::{Symbol, sym};
|
use crate::symbol::{Symbol, sym};
|
||||||
|
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use super::{State, Feature};
|
|
||||||
|
|
||||||
macro_rules! set {
|
macro_rules! set {
|
||||||
($field: ident) => {{
|
($field: ident) => {{
|
||||||
|
@ -37,9 +39,9 @@ macro_rules! declare_features {
|
||||||
/// A set of features to be used by later passes.
|
/// A set of features to be used by later passes.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Features {
|
pub struct Features {
|
||||||
/// `#![feature]` attrs for language features, for error reporting
|
/// `#![feature]` attrs for language features, for error reporting.
|
||||||
pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
|
pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
|
||||||
/// `#![feature]` attrs for non-language (library) features
|
/// `#![feature]` attrs for non-language (library) features.
|
||||||
pub declared_lib_features: Vec<(Symbol, Span)>,
|
pub declared_lib_features: Vec<(Symbol, Span)>,
|
||||||
$(
|
$(
|
||||||
$(#[doc = $doc])*
|
$(#[doc = $doc])*
|
||||||
|
@ -66,11 +68,11 @@ macro_rules! declare_features {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Feature {
|
impl Feature {
|
||||||
/// Set this feature in `Features`. Panics if called on a non-active feature.
|
/// Sets this feature in `Features`. Panics if called on a non-active feature.
|
||||||
pub fn set(&self, features: &mut Features, span: Span) {
|
pub fn set(&self, features: &mut Features, span: Span) {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Active { set } => set(features, span),
|
State::Active { set } => set(features, span),
|
||||||
_ => panic!("Called `set` on feature `{}` which is not `active`", self.name)
|
_ => panic!("called `set` on feature `{}` which is not `active`", self.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,7 +480,7 @@ declare_features! (
|
||||||
(active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
|
(active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
|
||||||
|
|
||||||
/// Allows relaxing the coherence rules such that
|
/// Allows relaxing the coherence rules such that
|
||||||
/// `impl<T> ForeignTrait<LocalType> for ForeignType<T> is permitted.
|
/// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
|
||||||
(active, re_rebalance_coherence, "1.32.0", Some(55437), None),
|
(active, re_rebalance_coherence, "1.32.0", Some(55437), None),
|
||||||
|
|
||||||
/// Allows using `#[ffi_returns_twice]` on foreign functions.
|
/// Allows using `#[ffi_returns_twice]` on foreign functions.
|
||||||
|
@ -520,7 +522,7 @@ declare_features! (
|
||||||
/// Allows `async || body` closures.
|
/// Allows `async || body` closures.
|
||||||
(active, async_closure, "1.37.0", Some(62290), None),
|
(active, async_closure, "1.37.0", Some(62290), None),
|
||||||
|
|
||||||
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests
|
/// Allows the use of `#[cfg(doctest)]`; set when rustdoc is collecting doctests.
|
||||||
(active, cfg_doctest, "1.37.0", Some(62210), None),
|
(active, cfg_doctest, "1.37.0", Some(62210), None),
|
||||||
|
|
||||||
/// Allows `[x; N]` where `x` is a constant (RFC 2203).
|
/// Allows `[x; N]` where `x` is a constant (RFC 2203).
|
||||||
|
@ -529,7 +531,7 @@ declare_features! (
|
||||||
/// Allows `impl Trait` to be used inside type aliases (RFC 2515).
|
/// Allows `impl Trait` to be used inside type aliases (RFC 2515).
|
||||||
(active, type_alias_impl_trait, "1.38.0", Some(63063), None),
|
(active, type_alias_impl_trait, "1.38.0", Some(63063), None),
|
||||||
|
|
||||||
/// Allows the use of or-patterns, e.g. `0 | 1`.
|
/// Allows the use of or-patterns (e.g., `0 | 1`).
|
||||||
(active, or_patterns, "1.38.0", Some(54883), None),
|
(active, or_patterns, "1.38.0", Some(54883), None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -169,7 +169,7 @@ const INTERAL_UNSTABLE: &str = "this is an internal attribute that will never be
|
||||||
|
|
||||||
pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate);
|
pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate);
|
||||||
|
|
||||||
/// Attributes that have a special meaning to rustc or rustdoc
|
/// Attributes that have a special meaning to rustc or rustdoc.
|
||||||
pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Stable attributes:
|
// Stable attributes:
|
||||||
|
|
|
@ -920,9 +920,9 @@ pub enum UnstableFeatures {
|
||||||
|
|
||||||
impl UnstableFeatures {
|
impl UnstableFeatures {
|
||||||
pub fn from_environment() -> UnstableFeatures {
|
pub fn from_environment() -> UnstableFeatures {
|
||||||
// Whether this is a feature-staged build, i.e., on the beta or stable channel
|
// `true` if 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();
|
let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
|
||||||
// Whether we should enable unstable features for bootstrapping
|
// `true` if we should enable unstable features for bootstrapping.
|
||||||
let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
|
let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
|
||||||
match (disable_unstable_features, bootstrap) {
|
match (disable_unstable_features, bootstrap) {
|
||||||
(_, true) => UnstableFeatures::Cheat,
|
(_, true) => UnstableFeatures::Cheat,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
//! A MutVisitor represents an AST modification; it accepts an AST piece and
|
//! A `MutVisitor` represents an AST modification; it accepts an AST piece and
|
||||||
//! and mutates it in place. So, for instance, macro expansion is a MutVisitor
|
//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor`
|
||||||
//! that walks over an AST and modifies it.
|
//! that walks over an AST and modifies it.
|
||||||
//!
|
//!
|
||||||
//! Note: using a MutVisitor (other than the MacroExpander MutVisitor) on
|
//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on
|
||||||
//! an AST before macro expansion is probably a bad idea. For instance,
|
//! an AST before macro expansion is probably a bad idea. For instance,
|
||||||
//! a MutVisitor renaming item names in a module will miss all of those
|
//! a `MutVisitor` renaming item names in a module will miss all of those
|
||||||
//! that are created by the expansion of a macro.
|
//! that are created by the expansion of a macro.
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
@ -614,7 +614,7 @@ pub fn noop_visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &m
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply ident visitor if it's an ident, apply other visits to interpolated nodes.
|
// Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
|
||||||
// In practice the ident part is not actually used by specific visitors right now,
|
// In practice the ident part is not actually used by specific visitors right now,
|
||||||
// but there's a test below checking that it works.
|
// but there's a test below checking that it works.
|
||||||
pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
||||||
|
@ -625,7 +625,7 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
||||||
vis.visit_ident(&mut ident);
|
vis.visit_ident(&mut ident);
|
||||||
*name = ident.name;
|
*name = ident.name;
|
||||||
*span = ident.span;
|
*span = ident.span;
|
||||||
return; // avoid visiting the span for the second time
|
return; // Avoid visiting the span for the second time.
|
||||||
}
|
}
|
||||||
token::Interpolated(nt) => {
|
token::Interpolated(nt) => {
|
||||||
let mut nt = Lrc::make_mut(nt);
|
let mut nt = Lrc::make_mut(nt);
|
||||||
|
@ -636,28 +636,28 @@ pub fn noop_visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply visitor to elements of interpolated nodes.
|
/// Applies the visitor to elements of interpolated nodes.
|
||||||
//
|
//
|
||||||
// N.B., this can occur only when applying a visitor to partially expanded
|
// N.B., this can occur only when applying a visitor to partially expanded
|
||||||
// code, where parsed pieces have gotten implanted ito *other* macro
|
// code, where parsed pieces have gotten implanted ito *other* macro
|
||||||
// invocations. This is relevant for macro hygiene, but possibly not elsewhere.
|
// invocations. This is relevant for macro hygiene, but possibly not elsewhere.
|
||||||
//
|
//
|
||||||
// One problem here occurs because the types for flat_map_item, flat_map_stmt,
|
// One problem here occurs because the types for flat_map_item, flat_map_stmt,
|
||||||
// etc. allow the visitor to return *multiple* items; this is a problem for the
|
// etc., allow the visitor to return *multiple* items; this is a problem for the
|
||||||
// nodes here, because they insist on having exactly one piece. One solution
|
// nodes here, because they insist on having exactly one piece. One solution
|
||||||
// would be to mangle the MutVisitor trait to include one-to-many and
|
// would be to mangle the MutVisitor trait to include one-to-many and
|
||||||
// one-to-one versions of these entry points, but that would probably confuse a
|
// one-to-one versions of these entry points, but that would probably confuse a
|
||||||
// lot of people and help very few. Instead, I'm just going to put in dynamic
|
// lot of people and help very few. Instead, I'm just going to put in dynamic
|
||||||
// checks. I think the performance impact of this will be pretty much
|
// checks. I think the performance impact of this will be pretty much
|
||||||
// nonexistent. The danger is that someone will apply a MutVisitor to a
|
// nonexistent. The danger is that someone will apply a `MutVisitor` to a
|
||||||
// partially expanded node, and will be confused by the fact that their
|
// partially expanded node, and will be confused by the fact that their
|
||||||
// "flat_map_item" or "flat_map_stmt" isn't getting called on NtItem or NtStmt
|
// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt`
|
||||||
// nodes. Hopefully they'll wind up reading this comment, and doing something
|
// nodes. Hopefully they'll wind up reading this comment, and doing something
|
||||||
// appropriate.
|
// appropriate.
|
||||||
//
|
//
|
||||||
// BTW, design choice: I considered just changing the type of, e.g., NtItem to
|
// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to
|
||||||
// contain multiple items, but decided against it when I looked at
|
// contain multiple items, but decided against it when I looked at
|
||||||
// parse_item_or_view_item and tried to figure out what I would do with
|
// `parse_item_or_view_item` and tried to figure out what I would do with
|
||||||
// multiple items there....
|
// multiple items there....
|
||||||
pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
|
pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
|
||||||
match nt {
|
match nt {
|
||||||
|
@ -1014,7 +1014,7 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutate one item into possibly many items.
|
// Mutates one item into possibly many items.
|
||||||
pub fn noop_flat_map_item<T: MutVisitor>(mut item: P<Item>, visitor: &mut T)
|
pub fn noop_flat_map_item<T: MutVisitor>(mut item: P<Item>, visitor: &mut T)
|
||||||
-> SmallVec<[P<Item>; 1]> {
|
-> SmallVec<[P<Item>; 1]> {
|
||||||
let Item { ident, attrs, id, node, vis, span, tokens: _ } = item.deref_mut();
|
let Item { ident, attrs, id, node, vis, span, tokens: _ } = item.deref_mut();
|
||||||
|
@ -1224,7 +1224,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
|
||||||
ExprKind::Paren(expr) => {
|
ExprKind::Paren(expr) => {
|
||||||
vis.visit_expr(expr);
|
vis.visit_expr(expr);
|
||||||
|
|
||||||
// Nodes that are equal modulo `Paren` sugar no-ops should have the same ids.
|
// Nodes that are equal modulo `Paren` sugar no-ops should have the same IDs.
|
||||||
*id = expr.id;
|
*id = expr.id;
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
visit_thin_attrs(attrs, vis);
|
visit_thin_attrs(attrs, vis);
|
||||||
|
|
|
@ -6,13 +6,13 @@ use crate::print::pprust;
|
||||||
use crate::mut_visit;
|
use crate::mut_visit;
|
||||||
use crate::with_default_globals;
|
use crate::with_default_globals;
|
||||||
|
|
||||||
// this version doesn't care about getting comments or docstrings in.
|
// This version doesn't care about getting comments or doc-strings in.
|
||||||
fn fake_print_crate(s: &mut pprust::State<'_>,
|
fn fake_print_crate(s: &mut pprust::State<'_>,
|
||||||
krate: &ast::Crate) {
|
krate: &ast::Crate) {
|
||||||
s.print_mod(&krate.module, &krate.attrs)
|
s.print_mod(&krate.module, &krate.attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// change every identifier to "zz"
|
// Change every identifier to "zz".
|
||||||
struct ToZzIdentMutVisitor;
|
struct ToZzIdentMutVisitor;
|
||||||
|
|
||||||
impl MutVisitor for ToZzIdentMutVisitor {
|
impl MutVisitor for ToZzIdentMutVisitor {
|
||||||
|
@ -24,7 +24,7 @@ impl MutVisitor for ToZzIdentMutVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe add to expand.rs...
|
// Maybe add to `expand.rs`.
|
||||||
macro_rules! assert_pred {
|
macro_rules! assert_pred {
|
||||||
($pred:expr, $predname:expr, $a:expr , $b:expr) => (
|
($pred:expr, $predname:expr, $a:expr , $b:expr) => (
|
||||||
{
|
{
|
||||||
|
@ -39,7 +39,7 @@ macro_rules! assert_pred {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure idents get transformed everywhere
|
// Make sure idents get transformed everywhere.
|
||||||
#[test] fn ident_transformation () {
|
#[test] fn ident_transformation () {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let mut zz_visitor = ToZzIdentMutVisitor;
|
let mut zz_visitor = ToZzIdentMutVisitor;
|
||||||
|
@ -54,7 +54,7 @@ macro_rules! assert_pred {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// even inside macro defs....
|
// Make sure idents get transformed even inside macro defs.
|
||||||
#[test] fn ident_transformation_in_defs () {
|
#[test] fn ident_transformation_in_defs () {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
let mut zz_visitor = ToZzIdentMutVisitor;
|
let mut zz_visitor = ToZzIdentMutVisitor;
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(attrs)
|
Ok(attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse attributes that appear before an item
|
/// Parses attributes that appear before an item.
|
||||||
crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
|
crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
|
||||||
let mut attrs: Vec<ast::Attribute> = Vec::new();
|
let mut attrs: Vec<ast::Attribute> = Vec::new();
|
||||||
let mut just_parsed_doc_comment = false;
|
let mut just_parsed_doc_comment = false;
|
||||||
|
@ -69,10 +69,10 @@ impl<'a> Parser<'a> {
|
||||||
Ok(attrs)
|
Ok(attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Matches `attribute = # ! [ meta_item ]`
|
/// Matches `attribute = # ! [ meta_item ]`.
|
||||||
///
|
///
|
||||||
/// If permit_inner is true, then a leading `!` indicates an inner
|
/// If `permit_inner` is `true`, then a leading `!` indicates an inner
|
||||||
/// attribute
|
/// attribute.
|
||||||
pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
|
pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> {
|
||||||
debug!("parse_attribute: permit_inner={:?} self.token={:?}",
|
debug!("parse_attribute: permit_inner={:?} self.token={:?}",
|
||||||
permit_inner,
|
permit_inner,
|
||||||
|
@ -167,14 +167,14 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an inner part of attribute - path and following tokens.
|
/// Parses an inner part of an attribute (the path and following tokens).
|
||||||
/// The tokens must be either a delimited token stream, or empty token stream,
|
/// The tokens must be either a delimited token stream, or empty token stream,
|
||||||
/// or the "legacy" key-value form.
|
/// or the "legacy" key-value form.
|
||||||
/// PATH `(` TOKEN_STREAM `)`
|
/// PATH `(` TOKEN_STREAM `)`
|
||||||
/// PATH `[` TOKEN_STREAM `]`
|
/// PATH `[` TOKEN_STREAM `]`
|
||||||
/// PATH `{` TOKEN_STREAM `}`
|
/// PATH `{` TOKEN_STREAM `}`
|
||||||
/// PATH
|
/// PATH
|
||||||
/// PATH `=` TOKEN_TREE
|
/// PATH `=` TOKEN_TREE
|
||||||
/// The delimiters or `=` are still put into the resulting token stream.
|
/// The delimiters or `=` are still put into the resulting token stream.
|
||||||
pub fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
|
pub fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
|
||||||
let meta = match self.token.kind {
|
let meta = match self.token.kind {
|
||||||
|
@ -217,11 +217,11 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse attributes that appear after the opening of an item. These should
|
/// Parses attributes that appear after the opening of an item. These should
|
||||||
/// be preceded by an exclamation mark, but we accept and warn about one
|
/// be preceded by an exclamation mark, but we accept and warn about one
|
||||||
/// terminated by a semicolon.
|
/// terminated by a semicolon.
|
||||||
|
///
|
||||||
/// matches inner_attrs*
|
/// Matches `inner_attrs*`.
|
||||||
crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
|
crate fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
|
||||||
let mut attrs: Vec<ast::Attribute> = vec![];
|
let mut attrs: Vec<ast::Attribute> = vec![];
|
||||||
loop {
|
loop {
|
||||||
|
@ -237,7 +237,7 @@ impl<'a> Parser<'a> {
|
||||||
attrs.push(attr);
|
attrs.push(attr);
|
||||||
}
|
}
|
||||||
token::DocComment(s) => {
|
token::DocComment(s) => {
|
||||||
// we need to get the position of this token before we bump.
|
// We need to get the position of this token before we bump.
|
||||||
let attr = attr::mk_sugared_doc_attr(s, self.token.span);
|
let attr = attr::mk_sugared_doc_attr(s, self.token.span);
|
||||||
if attr.style == ast::AttrStyle::Inner {
|
if attr.style == ast::AttrStyle::Inner {
|
||||||
attrs.push(attr);
|
attrs.push(attr);
|
||||||
|
@ -268,10 +268,10 @@ impl<'a> Parser<'a> {
|
||||||
Ok(lit)
|
Ok(lit)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Per RFC#1559, matches the following grammar:
|
/// Matches the following grammar (per RFC 1559).
|
||||||
///
|
///
|
||||||
/// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
|
/// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ;
|
||||||
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
|
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
|
||||||
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
|
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
|
||||||
let nt_meta = match self.token.kind {
|
let nt_meta = match self.token.kind {
|
||||||
token::Interpolated(ref nt) => match **nt {
|
token::Interpolated(ref nt) => match **nt {
|
||||||
|
@ -303,7 +303,7 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;
|
/// Matches `meta_item_inner : (meta_item | UNSUFFIXED_LIT) ;`.
|
||||||
fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
|
fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
|
||||||
match self.parse_unsuffixed_lit() {
|
match self.parse_unsuffixed_lit() {
|
||||||
Ok(lit) => {
|
Ok(lit) => {
|
||||||
|
@ -324,7 +324,7 @@ impl<'a> Parser<'a> {
|
||||||
Err(self.diagnostic().struct_span_err(self.token.span, &msg))
|
Err(self.diagnostic().struct_span_err(self.token.span, &msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// matches meta_seq = ( COMMASEP(meta_item_inner) )
|
/// Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
|
||||||
fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
|
fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
|
||||||
self.parse_seq_to_end(&token::CloseDelim(token::Paren),
|
self.parse_seq_to_end(&token::CloseDelim(token::Paren),
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
SeqSep::trailing_allowed(token::Comma),
|
||||||
|
|
|
@ -240,7 +240,7 @@ impl<'a> Parser<'a> {
|
||||||
) -> PResult<'a, bool /* recovered */> {
|
) -> PResult<'a, bool /* recovered */> {
|
||||||
fn tokens_to_string(tokens: &[TokenType]) -> String {
|
fn tokens_to_string(tokens: &[TokenType]) -> String {
|
||||||
let mut i = tokens.iter();
|
let mut i = tokens.iter();
|
||||||
// This might be a sign we need a connect method on Iterator.
|
// This might be a sign we need a connect method on `Iterator`.
|
||||||
let b = i.next()
|
let b = i.next()
|
||||||
.map_or(String::new(), |t| t.to_string());
|
.map_or(String::new(), |t| t.to_string());
|
||||||
i.enumerate().fold(b, |mut b, (i, a)| {
|
i.enumerate().fold(b, |mut b, (i, a)| {
|
||||||
|
@ -301,7 +301,7 @@ impl<'a> Parser<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let sp = if self.token == token::Eof {
|
let sp = if self.token == token::Eof {
|
||||||
// This is EOF, don't want to point at the following char, but rather the last token
|
// This is EOF; don't want to point at the following char, but rather the last token.
|
||||||
self.prev_span
|
self.prev_span
|
||||||
} else {
|
} else {
|
||||||
label_sp
|
label_sp
|
||||||
|
@ -317,9 +317,9 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_semi_suggestable = expected.iter().any(|t| match t {
|
let is_semi_suggestable = expected.iter().any(|t| match t {
|
||||||
TokenType::Token(token::Semi) => true, // we expect a `;` here
|
TokenType::Token(token::Semi) => true, // We expect a `;` here.
|
||||||
_ => false,
|
_ => false,
|
||||||
}) && ( // a `;` would be expected before the current keyword
|
}) && ( // A `;` would be expected before the current keyword.
|
||||||
self.token.is_keyword(kw::Break) ||
|
self.token.is_keyword(kw::Break) ||
|
||||||
self.token.is_keyword(kw::Continue) ||
|
self.token.is_keyword(kw::Continue) ||
|
||||||
self.token.is_keyword(kw::For) ||
|
self.token.is_keyword(kw::For) ||
|
||||||
|
@ -541,16 +541,16 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce an error if comparison operators are chained (RFC #558).
|
/// Produces an error if comparison operators are chained (RFC #558).
|
||||||
/// We only need to check lhs, not rhs, because all comparison ops
|
/// We only need to check the LHS, not the RHS, because all comparison ops
|
||||||
/// have same precedence and are left-associative
|
/// have same precedence and are left-associative.
|
||||||
crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> {
|
crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> {
|
||||||
debug_assert!(outer_op.is_comparison(),
|
debug_assert!(outer_op.is_comparison(),
|
||||||
"check_no_chained_comparison: {:?} is not comparison",
|
"check_no_chained_comparison: {:?} is not comparison",
|
||||||
outer_op);
|
outer_op);
|
||||||
match lhs.node {
|
match lhs.node {
|
||||||
ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
|
ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
|
||||||
// respan to include both operators
|
// Respan to include both operators.
|
||||||
let op_span = op.span.to(self.token.span);
|
let op_span = op.span.to(self.token.span);
|
||||||
let mut err = self.struct_span_err(
|
let mut err = self.struct_span_err(
|
||||||
op_span,
|
op_span,
|
||||||
|
@ -691,9 +691,9 @@ impl<'a> Parser<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
|
/// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
|
||||||
/// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem`
|
/// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem`
|
||||||
/// tail, and combine them into a `<Ty>::AssocItem` expression/pattern/type.
|
/// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
|
||||||
crate fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
|
crate fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: P<T>,
|
base: P<T>,
|
||||||
|
@ -708,8 +708,8 @@ impl<'a> Parser<'a> {
|
||||||
Ok(base)
|
Ok(base)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given an already parsed `Ty` parse the `::AssocItem` tail and
|
/// Given an already parsed `Ty`, parses the `::AssocItem` tail and
|
||||||
/// combine them into a `<Ty>::AssocItem` expression/pattern/type.
|
/// combines them into a `<Ty>::AssocItem` expression/pattern/type.
|
||||||
crate fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
|
crate fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ty_span: Span,
|
ty_span: Span,
|
||||||
|
@ -730,7 +730,7 @@ impl<'a> Parser<'a> {
|
||||||
self.diagnostic()
|
self.diagnostic()
|
||||||
.struct_span_err(path.span, "missing angle brackets in associated item path")
|
.struct_span_err(path.span, "missing angle brackets in associated item path")
|
||||||
.span_suggestion(
|
.span_suggestion(
|
||||||
// this is a best-effort recovery
|
// This is a best-effort recovery.
|
||||||
path.span,
|
path.span,
|
||||||
"try",
|
"try",
|
||||||
format!("<{}>::{}", ty_str, path),
|
format!("<{}>::{}", ty_str, path),
|
||||||
|
@ -738,7 +738,7 @@ impl<'a> Parser<'a> {
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0
|
let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
|
||||||
Ok(P(T::recovered(
|
Ok(P(T::recovered(
|
||||||
Some(QSelf {
|
Some(QSelf {
|
||||||
ty,
|
ty,
|
||||||
|
@ -761,8 +761,8 @@ impl<'a> Parser<'a> {
|
||||||
if !items.is_empty() {
|
if !items.is_empty() {
|
||||||
let previous_item = &items[items.len() - 1];
|
let previous_item = &items[items.len() - 1];
|
||||||
let previous_item_kind_name = match previous_item.node {
|
let previous_item_kind_name = match previous_item.node {
|
||||||
// say "braced struct" because tuple-structs and
|
// Say "braced struct" because tuple-structs and
|
||||||
// braceless-empty-struct declarations do take a semicolon
|
// braceless-empty-struct declarations do take a semicolon.
|
||||||
ItemKind::Struct(..) => Some("braced struct"),
|
ItemKind::Struct(..) => Some("braced struct"),
|
||||||
ItemKind::Enum(..) => Some("enum"),
|
ItemKind::Enum(..) => Some("enum"),
|
||||||
ItemKind::Trait(..) => Some("trait"),
|
ItemKind::Trait(..) => Some("trait"),
|
||||||
|
@ -783,7 +783,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a
|
/// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a
|
||||||
/// closing delimiter.
|
/// closing delimiter.
|
||||||
pub fn unexpected_try_recover(
|
pub fn unexpected_try_recover(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -841,7 +841,7 @@ impl<'a> Parser<'a> {
|
||||||
extern_sp: Span,
|
extern_sp: Span,
|
||||||
) -> PResult<'a, ()> {
|
) -> PResult<'a, ()> {
|
||||||
if self.token != token::Semi {
|
if self.token != token::Semi {
|
||||||
// this might be an incorrect fn definition (#62109)
|
// This might be an incorrect fn definition (#62109).
|
||||||
let parser_snapshot = self.clone();
|
let parser_snapshot = self.clone();
|
||||||
match self.parse_inner_attrs_and_block() {
|
match self.parse_inner_attrs_and_block() {
|
||||||
Ok((_, body)) => {
|
Ok((_, body)) => {
|
||||||
|
@ -871,7 +871,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
|
/// Consumes alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
|
||||||
/// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
|
/// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
|
||||||
crate fn parse_incorrect_await_syntax(
|
crate fn parse_incorrect_await_syntax(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -924,7 +924,7 @@ impl<'a> Parser<'a> {
|
||||||
sp
|
sp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If encountering `future.await()`, consume and emit error.
|
/// If encountering `future.await()`, consumes and emits an error.
|
||||||
crate fn recover_from_await_method_call(&mut self) {
|
crate fn recover_from_await_method_call(&mut self) {
|
||||||
if self.token == token::OpenDelim(token::Paren) &&
|
if self.token == token::OpenDelim(token::Paren) &&
|
||||||
self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren))
|
self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren))
|
||||||
|
@ -944,7 +944,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recover a situation like `for ( $pat in $expr )`
|
/// Recovers a situation like `for ( $pat in $expr )`
|
||||||
/// and suggest writing `for $pat in $expr` instead.
|
/// and suggest writing `for $pat in $expr` instead.
|
||||||
///
|
///
|
||||||
/// This should be called before parsing the `$block`.
|
/// This should be called before parsing the `$block`.
|
||||||
|
@ -1010,7 +1010,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
// recover from parse error
|
// Recover from parse error.
|
||||||
self.consume_block(delim);
|
self.consume_block(delim);
|
||||||
self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
|
self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
|
||||||
}
|
}
|
||||||
|
@ -1023,7 +1023,7 @@ impl<'a> Parser<'a> {
|
||||||
mut err: DiagnosticBuilder<'a>,
|
mut err: DiagnosticBuilder<'a>,
|
||||||
) -> PResult<'a, bool> {
|
) -> PResult<'a, bool> {
|
||||||
let mut pos = None;
|
let mut pos = None;
|
||||||
// we want to use the last closing delim that would apply
|
// We want to use the last closing delim that would apply.
|
||||||
for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
|
for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
|
||||||
if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
|
if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
|
||||||
&& Some(self.token.span) > unmatched.unclosed_span
|
&& Some(self.token.span) > unmatched.unclosed_span
|
||||||
|
@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> {
|
||||||
let unmatched = self.unclosed_delims.remove(pos);
|
let unmatched = self.unclosed_delims.remove(pos);
|
||||||
let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
|
let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
|
||||||
|
|
||||||
// We want to suggest the inclusion of the closing delimiter where it makes
|
// We want to suggest the inclusion of the closing delimiter where it makes
|
||||||
// the most sense, which is immediately after the last token:
|
// the most sense, which is immediately after the last token:
|
||||||
//
|
//
|
||||||
// {foo(bar {}}
|
// {foo(bar {}}
|
||||||
|
@ -1067,7 +1067,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
|
/// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid.
|
||||||
crate fn eat_bad_pub(&mut self) {
|
crate fn eat_bad_pub(&mut self) {
|
||||||
if self.token.is_keyword(kw::Pub) {
|
if self.token.is_keyword(kw::Pub) {
|
||||||
match self.parse_visibility(false) {
|
match self.parse_visibility(false) {
|
||||||
|
@ -1082,21 +1082,21 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eat tokens until we can be relatively sure we reached the end of the
|
/// Eats tokens until we can be relatively sure we reached the end of the
|
||||||
// statement. This is something of a best-effort heuristic.
|
/// statement. This is something of a best-effort heuristic.
|
||||||
//
|
///
|
||||||
// We terminate when we find an unmatched `}` (without consuming it).
|
/// We terminate when we find an unmatched `}` (without consuming it).
|
||||||
crate fn recover_stmt(&mut self) {
|
pub fn recover_stmt(&mut self) {
|
||||||
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
|
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If `break_on_semi` is `Break`, then we will stop consuming tokens after
|
/// If `break_on_semi` is `Break`, then we will stop consuming tokens after
|
||||||
// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
|
/// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
|
||||||
// approximate - it can mean we break too early due to macros, but that
|
/// approximate -- it can mean we break too early due to macros, but that
|
||||||
// should only lead to sub-optimal recovery, not inaccurate parsing).
|
/// should only lead to sub-optimal recovery, not inaccurate parsing).
|
||||||
//
|
///
|
||||||
// If `break_on_block` is `Break`, then we will stop consuming tokens
|
/// If `break_on_block` is `Break`, then we will stop consuming tokens
|
||||||
// after finding (and consuming) a brace-delimited block.
|
/// after finding (and consuming) a brace-delimited block.
|
||||||
crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) {
|
crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) {
|
||||||
let mut brace_depth = 0;
|
let mut brace_depth = 0;
|
||||||
let mut bracket_depth = 0;
|
let mut bracket_depth = 0;
|
||||||
|
|
|
@ -4,9 +4,10 @@ use crate::symbol::Symbol;
|
||||||
use crate::source_map::{SourceMap, FilePathMapping};
|
use crate::source_map::{SourceMap, FilePathMapping};
|
||||||
use crate::parse::token;
|
use crate::parse::token;
|
||||||
use crate::with_default_globals;
|
use crate::with_default_globals;
|
||||||
|
|
||||||
|
use errors::{Handler, emitter::EmitterWriter};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use errors::{Handler, emitter::EmitterWriter};
|
|
||||||
use syntax_pos::{BytePos, Span};
|
use syntax_pos::{BytePos, Span};
|
||||||
|
|
||||||
fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
|
fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
|
||||||
|
@ -21,7 +22,7 @@ fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
|
||||||
ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm)
|
ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// open a string reader for the given string
|
// Creates a string reader for the given string.
|
||||||
fn setup<'a>(sm: &SourceMap,
|
fn setup<'a>(sm: &SourceMap,
|
||||||
sess: &'a ParseSess,
|
sess: &'a ParseSess,
|
||||||
teststr: String)
|
teststr: String)
|
||||||
|
@ -38,7 +39,7 @@ fn t1() {
|
||||||
let mut string_reader = setup(
|
let mut string_reader = setup(
|
||||||
&sm,
|
&sm,
|
||||||
&sh,
|
&sh,
|
||||||
"/* my source file */ fn main() { println!(\"zebra\"); }\n".to_string(),
|
"/* my source file */ fn main() { println!(\"zebra\"); }\n".to_owned(),
|
||||||
);
|
);
|
||||||
assert_eq!(string_reader.next_token(), token::Comment);
|
assert_eq!(string_reader.next_token(), token::Comment);
|
||||||
assert_eq!(string_reader.next_token(), token::Whitespace);
|
assert_eq!(string_reader.next_token(), token::Whitespace);
|
||||||
|
@ -50,7 +51,7 @@ fn t1() {
|
||||||
assert_eq!(tok1.kind, tok2.kind);
|
assert_eq!(tok1.kind, tok2.kind);
|
||||||
assert_eq!(tok1.span, tok2.span);
|
assert_eq!(tok1.span, tok2.span);
|
||||||
assert_eq!(string_reader.next_token(), token::Whitespace);
|
assert_eq!(string_reader.next_token(), token::Whitespace);
|
||||||
// read another token:
|
// Read another token.
|
||||||
let tok3 = string_reader.next_token();
|
let tok3 = string_reader.next_token();
|
||||||
assert_eq!(string_reader.pos.clone(), BytePos(28));
|
assert_eq!(string_reader.pos.clone(), BytePos(28));
|
||||||
let tok4 = Token::new(
|
let tok4 = Token::new(
|
||||||
|
@ -65,15 +66,15 @@ fn t1() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that the given reader produces the desired stream
|
// Checks that the given reader produces the desired stream
|
||||||
// of tokens (stop checking after exhausting the expected vec)
|
// of tokens (stop checking after exhausting `expected`).
|
||||||
fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec<TokenKind>) {
|
fn check_tokenization(mut string_reader: StringReader<'_>, expected: Vec<TokenKind>) {
|
||||||
for expected_tok in &expected {
|
for expected_tok in &expected {
|
||||||
assert_eq!(&string_reader.next_token(), expected_tok);
|
assert_eq!(&string_reader.next_token(), expected_tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make the identifier by looking up the string in the interner
|
// Makes the identifier by looking up the string in the interner.
|
||||||
fn mk_ident(id: &str) -> TokenKind {
|
fn mk_ident(id: &str) -> TokenKind {
|
||||||
token::Ident(Symbol::intern(id), false)
|
token::Ident(Symbol::intern(id), false)
|
||||||
}
|
}
|
||||||
|
@ -201,7 +202,7 @@ fn literal_suffixes() {
|
||||||
setup(&sm, &sh, format!("{}suffix", $input)).next_token(),
|
setup(&sm, &sh, format!("{}suffix", $input)).next_token(),
|
||||||
mk_lit(token::$tok_type, $tok_contents, Some("suffix")),
|
mk_lit(token::$tok_type, $tok_contents, Some("suffix")),
|
||||||
);
|
);
|
||||||
// with a whitespace separator:
|
// with a whitespace separator
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
setup(&sm, &sh, format!("{} suffix", $input)).next_token(),
|
setup(&sm, &sh, format!("{} suffix", $input)).next_token(),
|
||||||
mk_lit(token::$tok_type, $tok_contents, None),
|
mk_lit(token::$tok_type, $tok_contents, None),
|
||||||
|
|
|
@ -13,12 +13,12 @@ use crate::print::pprust;
|
||||||
use crate::symbol::Symbol;
|
use crate::symbol::Symbol;
|
||||||
|
|
||||||
use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
|
use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
|
||||||
|
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
||||||
use rustc_data_structures::sync::{Lrc, Lock, Once};
|
use rustc_data_structures::sync::{Lrc, Lock, Once};
|
||||||
use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
|
use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
|
||||||
use syntax_pos::edition::Edition;
|
use syntax_pos::edition::Edition;
|
||||||
use syntax_pos::hygiene::ExpnId;
|
use syntax_pos::hygiene::ExpnId;
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
@ -81,25 +81,27 @@ pub struct ParseSess {
|
||||||
impl ParseSess {
|
impl ParseSess {
|
||||||
pub fn new(file_path_mapping: FilePathMapping) -> Self {
|
pub fn new(file_path_mapping: FilePathMapping) -> Self {
|
||||||
let cm = Lrc::new(SourceMap::new(file_path_mapping));
|
let cm = Lrc::new(SourceMap::new(file_path_mapping));
|
||||||
let handler = Handler::with_tty_emitter(ColorConfig::Auto,
|
let handler = Handler::with_tty_emitter(
|
||||||
true,
|
ColorConfig::Auto,
|
||||||
None,
|
true,
|
||||||
Some(cm.clone()));
|
None,
|
||||||
|
Some(cm.clone()),
|
||||||
|
);
|
||||||
ParseSess::with_span_handler(handler, cm)
|
ParseSess::with_span_handler(handler, cm)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> ParseSess {
|
pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
|
||||||
ParseSess {
|
Self {
|
||||||
span_diagnostic: handler,
|
span_diagnostic: handler,
|
||||||
unstable_features: UnstableFeatures::from_environment(),
|
unstable_features: UnstableFeatures::from_environment(),
|
||||||
config: FxHashSet::default(),
|
config: FxHashSet::default(),
|
||||||
|
edition: ExpnId::root().expn_data().edition,
|
||||||
missing_fragment_specifiers: Lock::new(FxHashSet::default()),
|
missing_fragment_specifiers: Lock::new(FxHashSet::default()),
|
||||||
raw_identifier_spans: Lock::new(Vec::new()),
|
raw_identifier_spans: Lock::new(Vec::new()),
|
||||||
registered_diagnostics: Lock::new(ErrorMap::new()),
|
registered_diagnostics: Lock::new(ErrorMap::new()),
|
||||||
included_mod_stack: Lock::new(vec![]),
|
included_mod_stack: Lock::new(vec![]),
|
||||||
source_map,
|
source_map,
|
||||||
buffered_lints: Lock::new(vec![]),
|
buffered_lints: Lock::new(vec![]),
|
||||||
edition: ExpnId::root().expn_data().edition,
|
|
||||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||||
injected_crate_name: Once::new(),
|
injected_crate_name: Once::new(),
|
||||||
gated_spans: GatedSpans::default(),
|
gated_spans: GatedSpans::default(),
|
||||||
|
@ -155,17 +157,17 @@ pub struct Directory<'a> {
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum DirectoryOwnership {
|
pub enum DirectoryOwnership {
|
||||||
Owned {
|
Owned {
|
||||||
// None if `mod.rs`, `Some("foo")` if we're in `foo.rs`
|
// None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
|
||||||
relative: Option<ast::Ident>,
|
relative: Option<ast::Ident>,
|
||||||
},
|
},
|
||||||
UnownedViaBlock,
|
UnownedViaBlock,
|
||||||
UnownedViaMod(bool /* legacy warnings? */),
|
UnownedViaMod(bool /* legacy warnings? */),
|
||||||
}
|
}
|
||||||
|
|
||||||
// a bunch of utility functions of the form parse_<thing>_from_<source>
|
// A bunch of utility functions of the form `parse_<thing>_from_<source>`
|
||||||
// where <thing> includes crate, expr, item, stmt, tts, and one that
|
// where <thing> includes crate, expr, item, stmt, tts, and one that
|
||||||
// uses a HOF to parse anything, and <source> includes file and
|
// uses a HOF to parse anything, and <source> includes file and
|
||||||
// source_str.
|
// `source_str`.
|
||||||
|
|
||||||
pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
|
pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
|
||||||
let mut parser = new_parser_from_file(sess, input);
|
let mut parser = new_parser_from_file(sess, input);
|
||||||
|
@ -219,14 +221,13 @@ pub fn maybe_new_parser_from_source_str(sess: &ParseSess, name: FileName, source
|
||||||
Ok(parser)
|
Ok(parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new parser, handling errors as appropriate
|
/// Creates a new parser, handling errors as appropriate if the file doesn't exist.
|
||||||
/// if the file doesn't exist
|
|
||||||
pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> {
|
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))
|
source_file_to_parser(sess, file_to_source_file(sess, path, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new parser, returning buffered diagnostics if the file doesn't
|
/// Creates a new parser, returning buffered diagnostics if the file doesn't exist,
|
||||||
/// exist or from lexing the initial token stream.
|
/// or from lexing the initial token stream.
|
||||||
pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path)
|
pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path)
|
||||||
-> Result<Parser<'a>, Vec<Diagnostic>> {
|
-> Result<Parser<'a>, Vec<Diagnostic>> {
|
||||||
let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?;
|
let file = try_file_to_source_file(sess, path, None).map_err(|db| vec![db])?;
|
||||||
|
@ -234,8 +235,8 @@ pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a session, a crate config, a path, and a span, add
|
/// 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.
|
/// the file at the given path to the `source_map`, and returns a parser.
|
||||||
/// On an error, use the given span as the source of the problem.
|
/// On an error, uses the given span as the source of the problem.
|
||||||
pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
|
pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
directory_ownership: DirectoryOwnership,
|
directory_ownership: DirectoryOwnership,
|
||||||
|
@ -247,13 +248,13 @@ pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a source_file and config, return a parser
|
/// Given a `source_file` and config, returns a parser.
|
||||||
fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Parser<'_> {
|
fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Parser<'_> {
|
||||||
panictry_buffer!(&sess.span_diagnostic,
|
panictry_buffer!(&sess.span_diagnostic,
|
||||||
maybe_source_file_to_parser(sess, source_file))
|
maybe_source_file_to_parser(sess, source_file))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the
|
/// Given a `source_file` and config, return a parser. Returns any buffered errors from lexing the
|
||||||
/// initial token stream.
|
/// initial token stream.
|
||||||
fn maybe_source_file_to_parser(
|
fn maybe_source_file_to_parser(
|
||||||
sess: &ParseSess,
|
sess: &ParseSess,
|
||||||
|
@ -270,14 +271,14 @@ fn maybe_source_file_to_parser(
|
||||||
Ok(parser)
|
Ok(parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
// must preserve old name for now, because quote! from the *existing*
|
// Must preserve old name for now, because `quote!` from the *existing*
|
||||||
// compiler expands into it
|
// compiler expands into it.
|
||||||
pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser<'_> {
|
pub fn new_parser_from_tts(sess: &ParseSess, tts: Vec<TokenTree>) -> Parser<'_> {
|
||||||
stream_to_parser(sess, tts.into_iter().collect(), crate::MACRO_ARGUMENTS)
|
stream_to_parser(sess, tts.into_iter().collect(), crate::MACRO_ARGUMENTS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// base abstractions
|
// Base abstractions
|
||||||
|
|
||||||
/// Given a session and a path and an optional span (for error reporting),
|
/// 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
|
/// add the path to the session's source_map and return the new source_file or
|
||||||
|
@ -296,7 +297,7 @@ fn try_file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a session and a path and an optional span (for error reporting),
|
/// 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`.
|
/// adds the path to the session's `source_map` and returns the new `source_file`.
|
||||||
fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
|
fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
|
||||||
-> Lrc<SourceFile> {
|
-> Lrc<SourceFile> {
|
||||||
match try_file_to_source_file(sess, path, spanopt) {
|
match try_file_to_source_file(sess, path, spanopt) {
|
||||||
|
@ -308,7 +309,7 @@ fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a source_file, produces a sequence of token trees.
|
/// Given a `source_file`, produces a sequence of token trees.
|
||||||
pub fn source_file_to_stream(
|
pub fn source_file_to_stream(
|
||||||
sess: &ParseSess,
|
sess: &ParseSess,
|
||||||
source_file: Lrc<SourceFile>,
|
source_file: Lrc<SourceFile>,
|
||||||
|
@ -352,7 +353,7 @@ pub fn maybe_file_to_stream(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given stream and the `ParseSess`, produces a parser.
|
/// Given a stream and the `ParseSess`, produces a parser.
|
||||||
pub fn stream_to_parser<'a>(
|
pub fn stream_to_parser<'a>(
|
||||||
sess: &'a ParseSess,
|
sess: &'a ParseSess,
|
||||||
stream: TokenStream,
|
stream: TokenStream,
|
||||||
|
@ -361,7 +362,7 @@ pub fn stream_to_parser<'a>(
|
||||||
Parser::new(sess, stream, None, true, false, subparser_name)
|
Parser::new(sess, stream, None, true, false, subparser_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given stream, the `ParseSess` and the base directory, produces a parser.
|
/// Given a stream, the `ParseSess` and the base directory, produces a parser.
|
||||||
///
|
///
|
||||||
/// Use this function when you are creating a parser from the token stream
|
/// Use this function when you are creating a parser from the token stream
|
||||||
/// and also care about the current working directory of the parser (e.g.,
|
/// and also care about the current working directory of the parser (e.g.,
|
||||||
|
|
|
@ -10,22 +10,22 @@ pub use path::PathStyle;
|
||||||
mod stmt;
|
mod stmt;
|
||||||
mod generics;
|
mod generics;
|
||||||
|
|
||||||
use crate::ast::{self, AttrStyle, Attribute, Param, BindingMode, StrStyle, SelfKind};
|
use crate::ast::{
|
||||||
use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind};
|
self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, FnDecl, Ident,
|
||||||
use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar};
|
IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility,
|
||||||
use crate::source_map::{self, respan};
|
VisibilityKind, Unsafety,
|
||||||
use crate::parse::{SeqSep, literal, token};
|
};
|
||||||
|
use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token};
|
||||||
|
use crate::parse::diagnostics::{Error, dummy_arg};
|
||||||
use crate::parse::lexer::UnmatchedBrace;
|
use crate::parse::lexer::UnmatchedBrace;
|
||||||
use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
|
use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
|
||||||
use crate::parse::token::{Token, TokenKind, DelimToken};
|
use crate::parse::token::{Token, TokenKind, DelimToken};
|
||||||
use crate::parse::{ParseSess, Directory, DirectoryOwnership};
|
|
||||||
use crate::print::pprust;
|
use crate::print::pprust;
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::parse::PResult;
|
use crate::source_map::{self, respan};
|
||||||
use crate::ThinVec;
|
|
||||||
use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
|
|
||||||
use crate::symbol::{kw, sym, Symbol};
|
use crate::symbol::{kw, sym, Symbol};
|
||||||
use crate::parse::diagnostics::{Error, dummy_arg};
|
use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
|
||||||
|
use crate::ThinVec;
|
||||||
|
|
||||||
use errors::{Applicability, DiagnosticId, FatalError};
|
use errors::{Applicability, DiagnosticId, FatalError};
|
||||||
use rustc_target::spec::abi::{self, Abi};
|
use rustc_target::spec::abi::{self, Abi};
|
||||||
|
@ -56,7 +56,7 @@ crate enum BlockMode {
|
||||||
Ignore,
|
Ignore,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// As maybe_whole_expr, but for things other than expressions
|
/// Like `maybe_whole_expr`, but for things other than expressions.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! maybe_whole {
|
macro_rules! maybe_whole {
|
||||||
($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
|
($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
|
||||||
|
@ -116,11 +116,11 @@ pub struct Parser<'a> {
|
||||||
/// with non-interpolated identifier and lifetime tokens they refer to.
|
/// with non-interpolated identifier and lifetime tokens they refer to.
|
||||||
/// Perhaps the normalized / non-normalized setup can be simplified somehow.
|
/// Perhaps the normalized / non-normalized setup can be simplified somehow.
|
||||||
pub token: Token,
|
pub token: Token,
|
||||||
/// Span of the current non-normalized token.
|
/// The span of the current non-normalized token.
|
||||||
meta_var_span: Option<Span>,
|
meta_var_span: Option<Span>,
|
||||||
/// Span of the previous non-normalized token.
|
/// The span of the previous non-normalized token.
|
||||||
pub prev_span: Span,
|
pub prev_span: Span,
|
||||||
/// Kind of the previous normalized token (in simplified form).
|
/// The kind of the previous normalized token (in simplified form).
|
||||||
prev_token_kind: PrevTokenKind,
|
prev_token_kind: PrevTokenKind,
|
||||||
restrictions: Restrictions,
|
restrictions: Restrictions,
|
||||||
/// Used to determine the path to externally loaded source files.
|
/// Used to determine the path to externally loaded source files.
|
||||||
|
@ -143,7 +143,7 @@ pub struct Parser<'a> {
|
||||||
/// See the comments in the `parse_path_segment` function for more details.
|
/// See the comments in the `parse_path_segment` function for more details.
|
||||||
crate unmatched_angle_bracket_count: u32,
|
crate unmatched_angle_bracket_count: u32,
|
||||||
crate max_angle_bracket_count: u32,
|
crate max_angle_bracket_count: u32,
|
||||||
/// List of all unclosed delimiters found by the lexer. If an entry is used for error recovery
|
/// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery
|
||||||
/// it gets removed from here. Every entry left at the end gets emitted as an independent
|
/// it gets removed from here. Every entry left at the end gets emitted as an independent
|
||||||
/// error.
|
/// error.
|
||||||
crate unclosed_delims: Vec<UnmatchedBrace>,
|
crate unclosed_delims: Vec<UnmatchedBrace>,
|
||||||
|
@ -799,14 +799,14 @@ impl<'a> Parser<'a> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Err(mut e) => {
|
Err(mut e) => {
|
||||||
// Attempt to keep parsing if it was a similar separator
|
// Attempt to keep parsing if it was a similar separator.
|
||||||
if let Some(ref tokens) = t.similar_tokens() {
|
if let Some(ref tokens) = t.similar_tokens() {
|
||||||
if tokens.contains(&self.token.kind) {
|
if tokens.contains(&self.token.kind) {
|
||||||
self.bump();
|
self.bump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.emit();
|
e.emit();
|
||||||
// Attempt to keep parsing if it was an omitted separator
|
// Attempt to keep parsing if it was an omitted separator.
|
||||||
match f(self) {
|
match f(self) {
|
||||||
Ok(t) => {
|
Ok(t) => {
|
||||||
v.push(t);
|
v.push(t);
|
||||||
|
@ -871,7 +871,7 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_delim_comma_seq(token::Paren, f)
|
self.parse_delim_comma_seq(token::Paren, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance the parser by one token
|
/// Advance the parser by one token.
|
||||||
pub fn bump(&mut self) {
|
pub fn bump(&mut self) {
|
||||||
if self.prev_token_kind == PrevTokenKind::Eof {
|
if self.prev_token_kind == PrevTokenKind::Eof {
|
||||||
// Bumping after EOF is a bad sign, usually an infinite loop.
|
// Bumping after EOF is a bad sign, usually an infinite loop.
|
||||||
|
@ -894,17 +894,17 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
self.token = self.next_tok();
|
self.token = self.next_tok();
|
||||||
self.expected_tokens.clear();
|
self.expected_tokens.clear();
|
||||||
// check after each token
|
// Check after each token.
|
||||||
self.process_potential_macro_variable();
|
self.process_potential_macro_variable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advance the parser using provided token as a next one. Use this when
|
/// Advances the parser using provided token as a next one. Use this when
|
||||||
/// consuming a part of a token. For example a single `<` from `<<`.
|
/// consuming a part of a token. For example a single `<` from `<<`.
|
||||||
fn bump_with(&mut self, next: TokenKind, span: Span) {
|
fn bump_with(&mut self, next: TokenKind, span: Span) {
|
||||||
self.prev_span = self.token.span.with_hi(span.lo());
|
self.prev_span = self.token.span.with_hi(span.lo());
|
||||||
// It would be incorrect to record the kind of the current token, but
|
// It would be incorrect to record the kind of the current token, but
|
||||||
// fortunately for tokens currently using `bump_with`, the
|
// fortunately for tokens currently using `bump_with`, the
|
||||||
// prev_token_kind will be of no use anyway.
|
// `prev_token_kind` will be of no use anyway.
|
||||||
self.prev_token_kind = PrevTokenKind::Other;
|
self.prev_token_kind = PrevTokenKind::Other;
|
||||||
self.token = Token::new(next, span);
|
self.token = Token::new(next, span);
|
||||||
self.expected_tokens.clear();
|
self.expected_tokens.clear();
|
||||||
|
@ -937,8 +937,8 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_asyncness(&mut self) -> IsAsync {
|
fn parse_asyncness(&mut self) -> IsAsync {
|
||||||
if self.eat_keyword(kw::Async) {
|
if self.eat_keyword(kw::Async) {
|
||||||
IsAsync::Async {
|
IsAsync::Async {
|
||||||
closure_id: ast::DUMMY_NODE_ID,
|
closure_id: DUMMY_NODE_ID,
|
||||||
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
return_impl_trait_id: DUMMY_NODE_ID,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IsAsync::NotAsync
|
IsAsync::NotAsync
|
||||||
|
@ -1040,7 +1040,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let span = lo.to(self.token.span);
|
let span = lo.to(self.token.span);
|
||||||
|
|
||||||
Ok(Param { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty })
|
Ok(Param { attrs: attrs.into(), id: DUMMY_NODE_ID, pat, span, ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses mutability (`mut` or nothing).
|
/// Parses mutability (`mut` or nothing).
|
||||||
|
@ -1497,7 +1497,7 @@ impl<'a> Parser<'a> {
|
||||||
format!("in {}", path),
|
format!("in {}", path),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit(); // emit diagnostic, but continue with public visibility
|
.emit(); // Emit diagnostic, but continue with public visibility.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle};
|
use super::{
|
||||||
use super::{BlockMode, SemiColonMode};
|
Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode, SemiColonMode,
|
||||||
use super::{SeqSep, TokenExpectType};
|
SeqSep, TokenExpectType,
|
||||||
|
};
|
||||||
use super::pat::{GateOr, PARAM_EXPECTED};
|
use super::pat::{GateOr, PARAM_EXPECTED};
|
||||||
|
|
||||||
|
use crate::ast::{
|
||||||
|
self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode,
|
||||||
|
Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind,
|
||||||
|
FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field,
|
||||||
|
};
|
||||||
use crate::maybe_recover_from_interpolated_ty_qpath;
|
use crate::maybe_recover_from_interpolated_ty_qpath;
|
||||||
use crate::ptr::P;
|
|
||||||
use crate::ast::{self, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode};
|
|
||||||
use crate::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm};
|
|
||||||
use crate::ast::{Ty, TyKind, FunctionRetTy, Param, FnDecl};
|
|
||||||
use crate::ast::{BinOpKind, BinOp, UnOp};
|
|
||||||
use crate::ast::{Mac, AnonConst, Field};
|
|
||||||
|
|
||||||
use crate::parse::classify;
|
use crate::parse::classify;
|
||||||
use crate::parse::token::{self, Token};
|
use crate::parse::token::{self, Token};
|
||||||
use crate::parse::diagnostics::{Error};
|
use crate::parse::diagnostics::Error;
|
||||||
use crate::print::pprust;
|
use crate::print::pprust;
|
||||||
|
use crate::ptr::P;
|
||||||
use crate::source_map::{self, Span};
|
use crate::source_map::{self, Span};
|
||||||
use crate::symbol::{kw, sym};
|
use crate::symbol::{kw, sym};
|
||||||
use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
|
use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
use errors::Applicability;
|
use errors::Applicability;
|
||||||
|
use std::mem;
|
||||||
use rustc_data_structures::thin_vec::ThinVec;
|
use rustc_data_structures::thin_vec::ThinVec;
|
||||||
|
|
||||||
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
|
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
|
||||||
|
@ -51,7 +51,7 @@ macro_rules! maybe_whole_expr {
|
||||||
$p.token.span, ExprKind::Block(block, None), ThinVec::new()
|
$p.token.span, ExprKind::Block(block, None), ThinVec::new()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// N.B: `NtIdent(ident)` is normalized to `Ident` in `fn bump`.
|
// N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`.
|
||||||
_ => {},
|
_ => {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -340,7 +340,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
fn is_at_start_of_range_notation_rhs(&self) -> bool {
|
fn is_at_start_of_range_notation_rhs(&self) -> bool {
|
||||||
if self.token.can_begin_expr() {
|
if self.token.can_begin_expr() {
|
||||||
// parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
|
// Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
|
||||||
if self.token == token::OpenDelim(token::Brace) {
|
if self.token == token::OpenDelim(token::Brace) {
|
||||||
return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
|
return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
|
||||||
}
|
}
|
||||||
|
@ -350,12 +350,12 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr`
|
/// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
|
||||||
fn parse_prefix_range_expr(
|
fn parse_prefix_range_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
already_parsed_attrs: Option<ThinVec<Attribute>>
|
already_parsed_attrs: Option<ThinVec<Attribute>>
|
||||||
) -> PResult<'a, P<Expr>> {
|
) -> PResult<'a, P<Expr>> {
|
||||||
// Check for deprecated `...` syntax
|
// Check for deprecated `...` syntax.
|
||||||
if self.token == token::DotDotDot {
|
if self.token == token::DotDotDot {
|
||||||
self.err_dotdotdot_syntax(self.token.span);
|
self.err_dotdotdot_syntax(self.token.span);
|
||||||
}
|
}
|
||||||
|
@ -389,7 +389,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(lo.to(hi), r, attrs))
|
Ok(self.mk_expr(lo.to(hi), r, attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a prefix-unary-operator expr
|
/// Parses a prefix-unary-operator expr.
|
||||||
fn parse_prefix_expr(
|
fn parse_prefix_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
already_parsed_attrs: Option<ThinVec<Attribute>>
|
already_parsed_attrs: Option<ThinVec<Attribute>>
|
||||||
|
@ -549,7 +549,7 @@ impl<'a> Parser<'a> {
|
||||||
let expr = mk_expr(self, P(Ty {
|
let expr = mk_expr(self, P(Ty {
|
||||||
span: path.span,
|
span: path.span,
|
||||||
node: TyKind::Path(None, path),
|
node: TyKind::Path(None, path),
|
||||||
id: ast::DUMMY_NODE_ID
|
id: DUMMY_NODE_ID,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let expr_str = self.span_to_snippet(expr.span)
|
let expr_str = self.span_to_snippet(expr.span)
|
||||||
|
@ -565,7 +565,7 @@ impl<'a> Parser<'a> {
|
||||||
expr.span,
|
expr.span,
|
||||||
&format!("try {} the cast value", op_verb),
|
&format!("try {} the cast value", op_verb),
|
||||||
format!("({})", expr_str),
|
format!("({})", expr_str),
|
||||||
Applicability::MachineApplicable
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
|
@ -741,7 +741,6 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// At the bottom (top?) of the precedence hierarchy,
|
/// At the bottom (top?) of the precedence hierarchy,
|
||||||
/// Parses things like parenthesized exprs, macros, `return`, etc.
|
/// Parses things like parenthesized exprs, macros, `return`, etc.
|
||||||
///
|
///
|
||||||
|
@ -755,7 +754,7 @@ impl<'a> Parser<'a> {
|
||||||
// added to the return value after the fact.
|
// added to the return value after the fact.
|
||||||
//
|
//
|
||||||
// Therefore, prevent sub-parser from parsing
|
// Therefore, prevent sub-parser from parsing
|
||||||
// attributes by giving them a empty "already parsed" list.
|
// attributes by giving them a empty "already-parsed" list.
|
||||||
let mut attrs = ThinVec::new();
|
let mut attrs = ThinVec::new();
|
||||||
|
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
|
@ -778,7 +777,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: when adding new syntax here, don't forget to adjust TokenKind::can_begin_expr().
|
// Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
|
||||||
match self.token.kind {
|
match self.token.kind {
|
||||||
// This match arm is a special-case of the `_` match arm below and
|
// This match arm is a special-case of the `_` match arm below and
|
||||||
// could be removed without changing functionality, but it's faster
|
// could be removed without changing functionality, but it's faster
|
||||||
|
@ -791,8 +790,8 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
attrs.extend(self.parse_inner_attributes()?);
|
attrs.extend(self.parse_inner_attributes()?);
|
||||||
|
|
||||||
// (e) is parenthesized e
|
// `(e)` is parenthesized `e`.
|
||||||
// (e,) is a tuple with only one field, e
|
// `(e,)` is a tuple with only one field, `e`.
|
||||||
let mut es = vec![];
|
let mut es = vec![];
|
||||||
let mut trailing_comma = false;
|
let mut trailing_comma = false;
|
||||||
let mut recovered = false;
|
let mut recovered = false;
|
||||||
|
@ -800,7 +799,7 @@ impl<'a> Parser<'a> {
|
||||||
es.push(match self.parse_expr() {
|
es.push(match self.parse_expr() {
|
||||||
Ok(es) => es,
|
Ok(es) => es,
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
// recover from parse error in tuple list
|
// Recover from parse error in tuple list.
|
||||||
match self.token.kind {
|
match self.token.kind {
|
||||||
token::Ident(name, false)
|
token::Ident(name, false)
|
||||||
if name == kw::Underscore && self.look_ahead(1, |t| {
|
if name == kw::Underscore && self.look_ahead(1, |t| {
|
||||||
|
@ -844,7 +843,7 @@ impl<'a> Parser<'a> {
|
||||||
return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs);
|
return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs);
|
||||||
}
|
}
|
||||||
token::BinOp(token::Or) | token::OrOr => {
|
token::BinOp(token::Or) | token::OrOr => {
|
||||||
return self.parse_lambda_expr(attrs);
|
return self.parse_closure(attrs);
|
||||||
}
|
}
|
||||||
token::OpenDelim(token::Bracket) => {
|
token::OpenDelim(token::Bracket) => {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
@ -852,21 +851,21 @@ impl<'a> Parser<'a> {
|
||||||
attrs.extend(self.parse_inner_attributes()?);
|
attrs.extend(self.parse_inner_attributes()?);
|
||||||
|
|
||||||
if self.eat(&token::CloseDelim(token::Bracket)) {
|
if self.eat(&token::CloseDelim(token::Bracket)) {
|
||||||
// Empty vector.
|
// Empty vector
|
||||||
ex = ExprKind::Array(Vec::new());
|
ex = ExprKind::Array(Vec::new());
|
||||||
} else {
|
} else {
|
||||||
// Nonempty vector.
|
// Non-empty vector
|
||||||
let first_expr = self.parse_expr()?;
|
let first_expr = self.parse_expr()?;
|
||||||
if self.eat(&token::Semi) {
|
if self.eat(&token::Semi) {
|
||||||
// Repeating array syntax: [ 0; 512 ]
|
// Repeating array syntax: `[ 0; 512 ]`
|
||||||
let count = AnonConst {
|
let count = AnonConst {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
value: self.parse_expr()?,
|
value: self.parse_expr()?,
|
||||||
};
|
};
|
||||||
self.expect(&token::CloseDelim(token::Bracket))?;
|
self.expect(&token::CloseDelim(token::Bracket))?;
|
||||||
ex = ExprKind::Repeat(first_expr, count);
|
ex = ExprKind::Repeat(first_expr, count);
|
||||||
} else if self.eat(&token::Comma) {
|
} else if self.eat(&token::Comma) {
|
||||||
// Vector with two or more elements.
|
// Vector with two or more elements
|
||||||
let remaining_exprs = self.parse_seq_to_end(
|
let remaining_exprs = self.parse_seq_to_end(
|
||||||
&token::CloseDelim(token::Bracket),
|
&token::CloseDelim(token::Bracket),
|
||||||
SeqSep::trailing_allowed(token::Comma),
|
SeqSep::trailing_allowed(token::Comma),
|
||||||
|
@ -876,7 +875,7 @@ impl<'a> Parser<'a> {
|
||||||
exprs.extend(remaining_exprs);
|
exprs.extend(remaining_exprs);
|
||||||
ex = ExprKind::Array(exprs);
|
ex = ExprKind::Array(exprs);
|
||||||
} else {
|
} else {
|
||||||
// Vector with one element.
|
// Vector with one element
|
||||||
self.expect(&token::CloseDelim(token::Bracket))?;
|
self.expect(&token::CloseDelim(token::Bracket))?;
|
||||||
ex = ExprKind::Array(vec![first_expr]);
|
ex = ExprKind::Array(vec![first_expr]);
|
||||||
}
|
}
|
||||||
|
@ -892,7 +891,7 @@ impl<'a> Parser<'a> {
|
||||||
if self.token.is_path_start() {
|
if self.token.is_path_start() {
|
||||||
let path = self.parse_path(PathStyle::Expr)?;
|
let path = self.parse_path(PathStyle::Expr)?;
|
||||||
|
|
||||||
// `!`, as an operator, is prefix, so we know this isn't that
|
// `!`, as an operator, is prefix, so we know this isn't that.
|
||||||
if self.eat(&token::Not) {
|
if self.eat(&token::Not) {
|
||||||
// MACRO INVOCATION expression
|
// MACRO INVOCATION expression
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||||
|
@ -920,7 +919,7 @@ impl<'a> Parser<'a> {
|
||||||
return self.maybe_recover_from_bad_qpath(expr, true);
|
return self.maybe_recover_from_bad_qpath(expr, true);
|
||||||
}
|
}
|
||||||
if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
|
if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
|
||||||
return self.parse_lambda_expr(attrs);
|
return self.parse_closure(attrs);
|
||||||
}
|
}
|
||||||
if self.eat_keyword(kw::If) {
|
if self.eat_keyword(kw::If) {
|
||||||
return self.parse_if_expr(attrs);
|
return self.parse_if_expr(attrs);
|
||||||
|
@ -991,13 +990,13 @@ impl<'a> Parser<'a> {
|
||||||
return self.parse_try_block(lo, attrs);
|
return self.parse_try_block(lo, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Span::rust_2018() is somewhat expensive; don't get it repeatedly.
|
// `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
|
||||||
let is_span_rust_2018 = self.token.span.rust_2018();
|
let is_span_rust_2018 = self.token.span.rust_2018();
|
||||||
if is_span_rust_2018 && self.check_keyword(kw::Async) {
|
if is_span_rust_2018 && self.check_keyword(kw::Async) {
|
||||||
return if self.is_async_block() { // check for `async {` and `async move {`
|
return if self.is_async_block() { // Check for `async {` and `async move {`.
|
||||||
self.parse_async_block(attrs)
|
self.parse_async_block(attrs)
|
||||||
} else {
|
} else {
|
||||||
self.parse_lambda_expr(attrs)
|
self.parse_closure(attrs)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if self.eat_keyword(kw::Return) {
|
if self.eat_keyword(kw::Return) {
|
||||||
|
@ -1043,13 +1042,12 @@ impl<'a> Parser<'a> {
|
||||||
// recovery in order to keep the error count down. Fixing the
|
// recovery in order to keep the error count down. Fixing the
|
||||||
// delimiters will possibly also fix the bare semicolon found in
|
// delimiters will possibly also fix the bare semicolon found in
|
||||||
// expression context. For example, silence the following error:
|
// expression context. For example, silence the following error:
|
||||||
// ```
|
//
|
||||||
// error: expected expression, found `;`
|
// error: expected expression, found `;`
|
||||||
// --> file.rs:2:13
|
// --> file.rs:2:13
|
||||||
// |
|
// |
|
||||||
// 2 | foo(bar(;
|
// 2 | foo(bar(;
|
||||||
// | ^ expected expression
|
// | ^ expected expression
|
||||||
// ```
|
|
||||||
self.bump();
|
self.bump();
|
||||||
return Ok(self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()));
|
return Ok(self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()));
|
||||||
}
|
}
|
||||||
|
@ -1096,11 +1094,11 @@ impl<'a> Parser<'a> {
|
||||||
attrs.extend(self.parse_inner_attributes()?);
|
attrs.extend(self.parse_inner_attributes()?);
|
||||||
|
|
||||||
let blk = self.parse_block_tail(lo, blk_mode)?;
|
let blk = self.parse_block_tail(lo, blk_mode)?;
|
||||||
return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs));
|
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `move |args| expr`.
|
/// Parses a closure (e.g., `move |args| expr`).
|
||||||
fn parse_lambda_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
fn parse_closure(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
|
|
||||||
let movability = if self.eat_keyword(kw::Static) {
|
let movability = if self.eat_keyword(kw::Static) {
|
||||||
|
@ -1115,7 +1113,7 @@ impl<'a> Parser<'a> {
|
||||||
IsAsync::NotAsync
|
IsAsync::NotAsync
|
||||||
};
|
};
|
||||||
if asyncness.is_async() {
|
if asyncness.is_async() {
|
||||||
// Feature gate `async ||` closures.
|
// Feature-gate `async ||` closures.
|
||||||
self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span);
|
self.sess.gated_spans.async_closure.borrow_mut().push(self.prev_span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1128,8 +1126,7 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_expr_res(restrictions, None)?
|
self.parse_expr_res(restrictions, None)?
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// If an explicit return type is given, require a
|
// If an explicit return type is given, require a block to appear (RFC 968).
|
||||||
// block to appear (RFC 968).
|
|
||||||
let body_lo = self.token.span;
|
let body_lo = self.token.span;
|
||||||
self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())?
|
self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())?
|
||||||
}
|
}
|
||||||
|
@ -1141,7 +1138,7 @@ impl<'a> Parser<'a> {
|
||||||
attrs))
|
attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an optional `move` prefix to a closure lke construct.
|
/// Parses an optional `move` prefix to a closure lke construct.
|
||||||
fn parse_capture_clause(&mut self) -> CaptureBy {
|
fn parse_capture_clause(&mut self) -> CaptureBy {
|
||||||
if self.eat_keyword(kw::Move) {
|
if self.eat_keyword(kw::Move) {
|
||||||
CaptureBy::Value
|
CaptureBy::Value
|
||||||
|
@ -1176,7 +1173,7 @@ impl<'a> Parser<'a> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a parameter in a lambda header (e.g., `|arg, arg|`).
|
/// Parses a parameter in a closure header (e.g., `|arg, arg|`).
|
||||||
fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
|
fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let attrs = self.parse_param_attributes()?;
|
let attrs = self.parse_param_attributes()?;
|
||||||
|
@ -1185,7 +1182,7 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_ty()?
|
self.parse_ty()?
|
||||||
} else {
|
} else {
|
||||||
P(Ty {
|
P(Ty {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
node: TyKind::Infer,
|
node: TyKind::Infer,
|
||||||
span: self.prev_span,
|
span: self.prev_span,
|
||||||
})
|
})
|
||||||
|
@ -1196,7 +1193,7 @@ impl<'a> Parser<'a> {
|
||||||
ty: t,
|
ty: t,
|
||||||
pat,
|
pat,
|
||||||
span,
|
span,
|
||||||
id: ast::DUMMY_NODE_ID
|
id: DUMMY_NODE_ID
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1233,7 +1230,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs))
|
Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the condition of a `if`- or `while`-expression
|
/// Parses the condition of a `if` or `while` expression.
|
||||||
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
|
let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
|
||||||
|
|
||||||
|
@ -1261,7 +1258,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs))
|
Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `else` token already eaten
|
/// Parses an `else { ... }` expression (`else` token already eaten).
|
||||||
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
if self.eat_keyword(kw::If) {
|
if self.eat_keyword(kw::If) {
|
||||||
return self.parse_if_expr(ThinVec::new());
|
return self.parse_if_expr(ThinVec::new());
|
||||||
|
@ -1271,7 +1268,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
|
/// Parses a `for ... in` expression (`for` token already eaten).
|
||||||
fn parse_for_expr(
|
fn parse_for_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
opt_label: Option<Label>,
|
opt_label: Option<Label>,
|
||||||
|
@ -1327,7 +1324,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
|
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse `loop {...}`, `loop` token already eaten.
|
/// Parses `loop { ... }` (`loop` token already eaten).
|
||||||
fn parse_loop_expr(
|
fn parse_loop_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
opt_label: Option<Label>,
|
opt_label: Option<Label>,
|
||||||
|
@ -1350,7 +1347,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `match` token already eaten
|
/// Parses a `match ... { ... }` expression (`match` token already eaten).
|
||||||
fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
let match_span = self.prev_span;
|
let match_span = self.prev_span;
|
||||||
let lo = self.prev_span;
|
let lo = self.prev_span;
|
||||||
|
@ -1457,7 +1454,7 @@ impl<'a> Parser<'a> {
|
||||||
guard,
|
guard,
|
||||||
body: expr,
|
body: expr,
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1491,7 +1488,7 @@ impl<'a> Parser<'a> {
|
||||||
self.token.is_keyword(kw::Try) &&
|
self.token.is_keyword(kw::Try) &&
|
||||||
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
|
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
|
||||||
self.token.span.rust_2018() &&
|
self.token.span.rust_2018() &&
|
||||||
// prevent `while try {} {}`, `if try {} {} else {}`, etc.
|
// Prevent `while try {} {}`, `if try {} {} else {}`, etc.
|
||||||
!self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
|
!self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1504,7 +1501,7 @@ impl<'a> Parser<'a> {
|
||||||
attrs.extend(iattrs);
|
attrs.extend(iattrs);
|
||||||
Ok(self.mk_expr(
|
Ok(self.mk_expr(
|
||||||
span_lo.to(body.span),
|
span_lo.to(body.span),
|
||||||
ExprKind::Async(capture_clause, ast::DUMMY_NODE_ID, body), attrs))
|
ExprKind::Async(capture_clause, DUMMY_NODE_ID, body), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_async_block(&self) -> bool {
|
fn is_async_block(&self) -> bool {
|
||||||
|
@ -1527,18 +1524,18 @@ impl<'a> Parser<'a> {
|
||||||
) -> Option<PResult<'a, P<Expr>>> {
|
) -> Option<PResult<'a, P<Expr>>> {
|
||||||
let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
|
let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
|
||||||
let certainly_not_a_block = || self.look_ahead(1, |t| t.is_ident()) && (
|
let certainly_not_a_block = || self.look_ahead(1, |t| t.is_ident()) && (
|
||||||
// `{ ident, ` cannot start a block
|
// `{ ident, ` cannot start a block.
|
||||||
self.look_ahead(2, |t| t == &token::Comma) ||
|
self.look_ahead(2, |t| t == &token::Comma) ||
|
||||||
self.look_ahead(2, |t| t == &token::Colon) && (
|
self.look_ahead(2, |t| t == &token::Colon) && (
|
||||||
// `{ ident: token, ` cannot start a block
|
// `{ ident: token, ` cannot start a block.
|
||||||
self.look_ahead(4, |t| t == &token::Comma) ||
|
self.look_ahead(4, |t| t == &token::Comma) ||
|
||||||
// `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`
|
// `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`.
|
||||||
self.look_ahead(3, |t| !t.can_begin_type())
|
self.look_ahead(3, |t| !t.can_begin_type())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if struct_allowed || certainly_not_a_block() {
|
if struct_allowed || certainly_not_a_block() {
|
||||||
// This is a struct literal, but we don't can't accept them here
|
// This is a struct literal, but we don't can't accept them here.
|
||||||
let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone());
|
let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone());
|
||||||
if let (Ok(expr), false) = (&expr, struct_allowed) {
|
if let (Ok(expr), false) = (&expr, struct_allowed) {
|
||||||
self.struct_span_err(
|
self.struct_span_err(
|
||||||
|
@ -1606,14 +1603,14 @@ impl<'a> Parser<'a> {
|
||||||
let mut recovery_field = None;
|
let mut recovery_field = None;
|
||||||
if let token::Ident(name, _) = self.token.kind {
|
if let token::Ident(name, _) = self.token.kind {
|
||||||
if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
|
if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
|
||||||
// Use in case of error after field-looking code: `S { foo: () with a }`
|
// Use in case of error after field-looking code: `S { foo: () with a }`.
|
||||||
recovery_field = Some(ast::Field {
|
recovery_field = Some(ast::Field {
|
||||||
ident: Ident::new(name, self.token.span),
|
ident: Ident::new(name, self.token.span),
|
||||||
span: self.token.span,
|
span: self.token.span,
|
||||||
expr: self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()),
|
expr: self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()),
|
||||||
is_shorthand: false,
|
is_shorthand: false,
|
||||||
attrs: ThinVec::new(),
|
attrs: ThinVec::new(),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1639,7 +1636,7 @@ impl<'a> Parser<'a> {
|
||||||
match self.expect_one_of(&[token::Comma],
|
match self.expect_one_of(&[token::Comma],
|
||||||
&[token::CloseDelim(token::Brace)]) {
|
&[token::CloseDelim(token::Brace)]) {
|
||||||
Ok(_) => if let Some(f) = parsed_field.or(recovery_field) {
|
Ok(_) => if let Some(f) = parsed_field.or(recovery_field) {
|
||||||
// only include the field if there's no parse error for the field name
|
// Only include the field if there's no parse error for the field name.
|
||||||
fields.push(f);
|
fields.push(f);
|
||||||
}
|
}
|
||||||
Err(mut e) => {
|
Err(mut e) => {
|
||||||
|
@ -1659,7 +1656,7 @@ impl<'a> Parser<'a> {
|
||||||
return Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs));
|
return Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse ident (COLON expr)?
|
/// Parses `ident (COLON expr)?`.
|
||||||
fn parse_field(&mut self) -> PResult<'a, Field> {
|
fn parse_field(&mut self) -> PResult<'a, Field> {
|
||||||
let attrs = self.parse_outer_attributes()?;
|
let attrs = self.parse_outer_attributes()?;
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
|
@ -1699,7 +1696,7 @@ impl<'a> Parser<'a> {
|
||||||
expr,
|
expr,
|
||||||
is_shorthand,
|
is_shorthand,
|
||||||
attrs: attrs.into(),
|
attrs: attrs.into(),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1772,6 +1769,6 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn mk_expr(&self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
|
crate fn mk_expr(&self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
|
||||||
P(Expr { node, span, attrs, id: ast::DUMMY_NODE_ID })
|
P(Expr { node, span, attrs, id: DUMMY_NODE_ID })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,34 +2,36 @@ use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode};
|
||||||
|
|
||||||
use crate::maybe_whole;
|
use crate::maybe_whole;
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::ast::{self, Ident, Attribute, AttrStyle};
|
use crate::ast::{
|
||||||
use crate::ast::{Item, ItemKind, ImplItem, TraitItem, TraitItemKind};
|
self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle,
|
||||||
use crate::ast::{UseTree, UseTreeKind, PathSegment};
|
Item, ItemKind, ImplItem, TraitItem, TraitItemKind,
|
||||||
use crate::ast::{IsAuto, Constness, IsAsync, Unsafety, Defaultness};
|
UseTree, UseTreeKind, PathSegment,
|
||||||
use crate::ast::{Visibility, VisibilityKind, Mutability, FnDecl, FnHeader};
|
IsAuto, Constness, IsAsync, Unsafety, Defaultness,
|
||||||
use crate::ast::{ForeignItem, ForeignItemKind};
|
Visibility, VisibilityKind, Mutability, FnDecl, FnHeader,
|
||||||
use crate::ast::{Ty, TyKind, GenericBounds, TraitRef};
|
ForeignItem, ForeignItemKind,
|
||||||
use crate::ast::{EnumDef, VariantData, StructField, AnonConst};
|
Ty, TyKind, Generics, GenericBounds, TraitRef,
|
||||||
use crate::ast::{Mac, MacDelimiter};
|
EnumDef, VariantData, StructField, AnonConst,
|
||||||
|
Mac, MacDelimiter,
|
||||||
|
};
|
||||||
use crate::ext::base::DummyResult;
|
use crate::ext::base::DummyResult;
|
||||||
use crate::parse::token;
|
use crate::parse::token;
|
||||||
use crate::parse::parser::maybe_append;
|
use crate::parse::parser::maybe_append;
|
||||||
use crate::parse::diagnostics::{Error};
|
use crate::parse::diagnostics::Error;
|
||||||
use crate::tokenstream::{TokenTree, TokenStream};
|
use crate::tokenstream::{TokenTree, TokenStream};
|
||||||
use crate::source_map::{respan, Span, Spanned};
|
use crate::source_map::{respan, Span, Spanned};
|
||||||
use crate::symbol::{kw, sym};
|
use crate::symbol::{kw, sym};
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use rustc_target::spec::abi::{Abi};
|
use rustc_target::spec::abi::Abi;
|
||||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||||
|
|
||||||
/// Whether the type alias or associated type is a concrete type or an opaque type
|
/// Whether the type alias or associated type is a concrete type or an opaque type.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AliasKind {
|
pub enum AliasKind {
|
||||||
/// Just a new name for the same type
|
/// Just a new name for the same type.
|
||||||
Weak(P<Ty>),
|
Weak(P<Ty>),
|
||||||
/// Only trait impls of the type will be usable, not the actual type itself
|
/// Only trait impls of the type will be usable, not the actual type itself.
|
||||||
OpaqueTy(GenericBounds),
|
OpaqueTy(GenericBounds),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +202,7 @@ impl<'a> Parser<'a> {
|
||||||
return Ok(Some(item));
|
return Ok(Some(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse `async unsafe? fn`.
|
// Parses `async unsafe? fn`.
|
||||||
if self.check_keyword(kw::Async) {
|
if self.check_keyword(kw::Async) {
|
||||||
let async_span = self.token.span;
|
let async_span = self.token.span;
|
||||||
if self.is_keyword_ahead(1, &[kw::Fn])
|
if self.is_keyword_ahead(1, &[kw::Fn])
|
||||||
|
@ -214,8 +216,8 @@ impl<'a> Parser<'a> {
|
||||||
let (ident, item_, extra_attrs) =
|
let (ident, item_, extra_attrs) =
|
||||||
self.parse_item_fn(unsafety,
|
self.parse_item_fn(unsafety,
|
||||||
respan(async_span, IsAsync::Async {
|
respan(async_span, IsAsync::Async {
|
||||||
closure_id: ast::DUMMY_NODE_ID,
|
closure_id: DUMMY_NODE_ID,
|
||||||
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
return_impl_trait_id: DUMMY_NODE_ID,
|
||||||
}),
|
}),
|
||||||
respan(fn_span, Constness::NotConst),
|
respan(fn_span, Constness::NotConst),
|
||||||
Abi::Rust)?;
|
Abi::Rust)?;
|
||||||
|
@ -286,7 +288,7 @@ impl<'a> Parser<'a> {
|
||||||
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
|
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
|
||||||
// UNSAFE FUNCTION ITEM
|
// UNSAFE FUNCTION ITEM
|
||||||
self.bump(); // `unsafe`
|
self.bump(); // `unsafe`
|
||||||
// `{` is also expected after `unsafe`, in case of error, include it in the diagnostic
|
// `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
|
||||||
self.check(&token::OpenDelim(token::Brace));
|
self.check(&token::OpenDelim(token::Brace));
|
||||||
let abi = if self.eat_keyword(kw::Extern) {
|
let abi = if self.eat_keyword(kw::Extern) {
|
||||||
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
self.parse_opt_abi()?.unwrap_or(Abi::C)
|
||||||
|
@ -521,7 +523,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let mac_lo = self.token.span;
|
let mac_lo = self.token.span;
|
||||||
|
|
||||||
// item macro.
|
// Item macro
|
||||||
let path = self.parse_path(PathStyle::Mod)?;
|
let path = self.parse_path(PathStyle::Mod)?;
|
||||||
self.expect(&token::Not)?;
|
self.expect(&token::Not)?;
|
||||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||||
|
@ -659,7 +661,7 @@ impl<'a> Parser<'a> {
|
||||||
let mut generics = if self.choose_generics_over_qpath() {
|
let mut generics = if self.choose_generics_over_qpath() {
|
||||||
self.parse_generics()?
|
self.parse_generics()?
|
||||||
} else {
|
} else {
|
||||||
ast::Generics::default()
|
Generics::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
|
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
|
||||||
|
@ -676,7 +678,7 @@ impl<'a> Parser<'a> {
|
||||||
self.look_ahead(1, |t| t != &token::Lt) {
|
self.look_ahead(1, |t| t != &token::Lt) {
|
||||||
let span = self.prev_span.between(self.token.span);
|
let span = self.prev_span.between(self.token.span);
|
||||||
self.struct_span_err(span, "missing trait in a trait impl").emit();
|
self.struct_span_err(span, "missing trait in a trait impl").emit();
|
||||||
P(Ty { node: TyKind::Path(None, err_path(span)), span, id: ast::DUMMY_NODE_ID })
|
P(Ty { node: TyKind::Path(None, err_path(span)), span, id: DUMMY_NODE_ID })
|
||||||
} else {
|
} else {
|
||||||
self.parse_ty()?
|
self.parse_ty()?
|
||||||
};
|
};
|
||||||
|
@ -798,7 +800,7 @@ impl<'a> Parser<'a> {
|
||||||
self.expect(&token::Eq)?;
|
self.expect(&token::Eq)?;
|
||||||
let expr = self.parse_expr()?;
|
let expr = self.parse_expr()?;
|
||||||
self.expect(&token::Semi)?;
|
self.expect(&token::Semi)?;
|
||||||
(name, ast::ImplItemKind::Const(typ, expr), ast::Generics::default())
|
(name, ast::ImplItemKind::Const(typ, expr), Generics::default())
|
||||||
} else {
|
} else {
|
||||||
let (name, inner_attrs, generics, node) = self.parse_impl_method(&vis, at_end)?;
|
let (name, inner_attrs, generics, node) = self.parse_impl_method(&vis, at_end)?;
|
||||||
attrs.extend(inner_attrs);
|
attrs.extend(inner_attrs);
|
||||||
|
@ -806,7 +808,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ImplItem {
|
Ok(ImplItem {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
ident: name,
|
ident: name,
|
||||||
vis,
|
vis,
|
||||||
|
@ -847,14 +849,13 @@ impl<'a> Parser<'a> {
|
||||||
!self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
|
!self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a method or a macro invocation in a trait impl.
|
/// Parses a method or a macro invocation in a trait impl.
|
||||||
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
|
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
|
||||||
-> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
|
-> PResult<'a, (Ident, Vec<Attribute>, Generics, ast::ImplItemKind)> {
|
||||||
ast::ImplItemKind)> {
|
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
|
||||||
// code copied from parse_macro_use_or_failure... abstraction!
|
|
||||||
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
|
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
|
||||||
// method macro
|
// method macro
|
||||||
Ok((Ident::invalid(), vec![], ast::Generics::default(),
|
Ok((Ident::invalid(), vec![], Generics::default(),
|
||||||
ast::ImplItemKind::Macro(mac)))
|
ast::ImplItemKind::Macro(mac)))
|
||||||
} else {
|
} else {
|
||||||
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
||||||
|
@ -930,7 +931,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.eat(&token::Eq) {
|
if self.eat(&token::Eq) {
|
||||||
// it's a trait alias
|
// It's a trait alias.
|
||||||
let bounds = self.parse_generic_bounds(None)?;
|
let bounds = self.parse_generic_bounds(None)?;
|
||||||
tps.where_clause = self.parse_where_clause()?;
|
tps.where_clause = self.parse_where_clause()?;
|
||||||
self.expect(&token::Semi)?;
|
self.expect(&token::Semi)?;
|
||||||
|
@ -948,7 +949,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
|
Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
|
||||||
} else {
|
} else {
|
||||||
// it's a normal trait
|
// It's a normal trait.
|
||||||
tps.where_clause = self.parse_where_clause()?;
|
tps.where_clause = self.parse_where_clause()?;
|
||||||
self.expect(&token::OpenDelim(token::Brace))?;
|
self.expect(&token::OpenDelim(token::Brace))?;
|
||||||
let mut trait_items = vec![];
|
let mut trait_items = vec![];
|
||||||
|
@ -1023,10 +1024,10 @@ impl<'a> Parser<'a> {
|
||||||
self.expect(&token::Semi)?;
|
self.expect(&token::Semi)?;
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
(ident, TraitItemKind::Const(ty, default), ast::Generics::default())
|
(ident, TraitItemKind::Const(ty, default), Generics::default())
|
||||||
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
|
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
|
||||||
// trait item macro.
|
// trait item macro.
|
||||||
(Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
|
(Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default())
|
||||||
} else {
|
} else {
|
||||||
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
||||||
|
|
||||||
|
@ -1089,7 +1090,7 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(TraitItem {
|
Ok(TraitItem {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
ident: name,
|
ident: name,
|
||||||
attrs,
|
attrs,
|
||||||
generics,
|
generics,
|
||||||
|
@ -1103,7 +1104,7 @@ impl<'a> Parser<'a> {
|
||||||
///
|
///
|
||||||
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
||||||
fn parse_trait_item_assoc_ty(&mut self)
|
fn parse_trait_item_assoc_ty(&mut self)
|
||||||
-> PResult<'a, (Ident, TraitItemKind, ast::Generics)> {
|
-> PResult<'a, (Ident, TraitItemKind, Generics)> {
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
let mut generics = self.parse_generics()?;
|
let mut generics = self.parse_generics()?;
|
||||||
|
|
||||||
|
@ -1165,7 +1166,7 @@ impl<'a> Parser<'a> {
|
||||||
UseTreeKind::Nested(self.parse_use_tree_list()?)
|
UseTreeKind::Nested(self.parse_use_tree_list()?)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UseTreeKind::Simple(self.parse_rename()?, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID)
|
UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1178,7 +1179,7 @@ impl<'a> Parser<'a> {
|
||||||
/// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
|
/// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
|
fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
|
||||||
self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, ast::DUMMY_NODE_ID)))
|
self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, DUMMY_NODE_ID)))
|
||||||
.map(|(r, _)| r)
|
.map(|(r, _)| r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1240,9 +1241,9 @@ impl<'a> Parser<'a> {
|
||||||
let mut idents = vec![];
|
let mut idents = vec![];
|
||||||
let mut replacement = vec![];
|
let mut replacement = vec![];
|
||||||
let mut fixed_crate_name = false;
|
let mut fixed_crate_name = false;
|
||||||
// Accept `extern crate name-like-this` for better diagnostics
|
// Accept `extern crate name-like-this` for better diagnostics.
|
||||||
let dash = token::BinOp(token::BinOpToken::Minus);
|
let dash = token::BinOp(token::BinOpToken::Minus);
|
||||||
if self.token == dash { // Do not include `-` as part of the expected tokens list
|
if self.token == dash { // Do not include `-` as part of the expected tokens list.
|
||||||
while self.eat(&dash) {
|
while self.eat(&dash) {
|
||||||
fixed_crate_name = true;
|
fixed_crate_name = true;
|
||||||
replacement.push((self.prev_span, "_".to_string()));
|
replacement.push((self.prev_span, "_".to_string()));
|
||||||
|
@ -1283,7 +1284,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the name and optional generic types of a function header.
|
/// Parses the name and optional generic types of a function header.
|
||||||
fn parse_fn_header(&mut self) -> PResult<'a, (Ident, ast::Generics)> {
|
fn parse_fn_header(&mut self) -> PResult<'a, (Ident, Generics)> {
|
||||||
let id = self.parse_ident()?;
|
let id = self.parse_ident()?;
|
||||||
let generics = self.parse_generics()?;
|
let generics = self.parse_generics()?;
|
||||||
Ok((id, generics))
|
Ok((id, generics))
|
||||||
|
@ -1379,7 +1380,7 @@ impl<'a> Parser<'a> {
|
||||||
ForeignItem {
|
ForeignItem {
|
||||||
ident: Ident::invalid(),
|
ident: Ident::invalid(),
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
attrs,
|
attrs,
|
||||||
vis: visibility,
|
vis: visibility,
|
||||||
node: ForeignItemKind::Macro(mac),
|
node: ForeignItemKind::Macro(mac),
|
||||||
|
@ -1415,7 +1416,7 @@ impl<'a> Parser<'a> {
|
||||||
ident,
|
ident,
|
||||||
attrs,
|
attrs,
|
||||||
node: ForeignItemKind::Fn(decl, generics),
|
node: ForeignItemKind::Fn(decl, generics),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
vis,
|
vis,
|
||||||
})
|
})
|
||||||
|
@ -1435,7 +1436,7 @@ impl<'a> Parser<'a> {
|
||||||
ident,
|
ident,
|
||||||
attrs,
|
attrs,
|
||||||
node: ForeignItemKind::Static(ty, mutbl),
|
node: ForeignItemKind::Static(ty, mutbl),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
vis,
|
vis,
|
||||||
})
|
})
|
||||||
|
@ -1453,7 +1454,7 @@ impl<'a> Parser<'a> {
|
||||||
ident,
|
ident,
|
||||||
attrs,
|
attrs,
|
||||||
node: ForeignItemKind::Ty,
|
node: ForeignItemKind::Ty,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
vis
|
vis
|
||||||
})
|
})
|
||||||
|
@ -1461,7 +1462,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
fn is_static_global(&mut self) -> bool {
|
fn is_static_global(&mut self) -> bool {
|
||||||
if self.check_keyword(kw::Static) {
|
if self.check_keyword(kw::Static) {
|
||||||
// Check if this could be a closure
|
// Check if this could be a closure.
|
||||||
!self.look_ahead(1, |token| {
|
!self.look_ahead(1, |token| {
|
||||||
if token.is_keyword(kw::Move) {
|
if token.is_keyword(kw::Move) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1492,7 +1493,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parses `type Foo = Bar;` or returns `None`
|
/// Parses `type Foo = Bar;` or returns `None`
|
||||||
/// without modifying the parser state.
|
/// without modifying the parser state.
|
||||||
fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> {
|
fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, Generics)>> {
|
||||||
// This parses the grammar:
|
// This parses the grammar:
|
||||||
// Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
|
// Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
|
||||||
if self.eat_keyword(kw::Type) {
|
if self.eat_keyword(kw::Type) {
|
||||||
|
@ -1503,7 +1504,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a type alias or opaque type.
|
/// Parses a type alias or opaque type.
|
||||||
fn parse_type_alias(&mut self) -> PResult<'a, (Ident, AliasKind, ast::Generics)> {
|
fn parse_type_alias(&mut self) -> PResult<'a, (Ident, AliasKind, Generics)> {
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
let mut tps = self.parse_generics()?;
|
let mut tps = self.parse_generics()?;
|
||||||
tps.where_clause = self.parse_where_clause()?;
|
tps.where_clause = self.parse_where_clause()?;
|
||||||
|
@ -1536,7 +1537,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the part of an enum declaration following the `{`.
|
/// Parses the part of an enum declaration following the `{`.
|
||||||
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
|
fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
|
||||||
let mut variants = Vec::new();
|
let mut variants = Vec::new();
|
||||||
while self.token != token::CloseDelim(token::Brace) {
|
while self.token != token::CloseDelim(token::Brace) {
|
||||||
let variant_attrs = self.parse_outer_attributes()?;
|
let variant_attrs = self.parse_outer_attributes()?;
|
||||||
|
@ -1552,15 +1553,15 @@ impl<'a> Parser<'a> {
|
||||||
} else if self.check(&token::OpenDelim(token::Paren)) {
|
} else if self.check(&token::OpenDelim(token::Paren)) {
|
||||||
VariantData::Tuple(
|
VariantData::Tuple(
|
||||||
self.parse_tuple_struct_body()?,
|
self.parse_tuple_struct_body()?,
|
||||||
ast::DUMMY_NODE_ID,
|
DUMMY_NODE_ID,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
VariantData::Unit(ast::DUMMY_NODE_ID)
|
VariantData::Unit(DUMMY_NODE_ID)
|
||||||
};
|
};
|
||||||
|
|
||||||
let disr_expr = if self.eat(&token::Eq) {
|
let disr_expr = if self.eat(&token::Eq) {
|
||||||
Some(AnonConst {
|
Some(AnonConst {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
value: self.parse_expr()?,
|
value: self.parse_expr()?,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -1569,7 +1570,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let vr = ast::Variant {
|
let vr = ast::Variant {
|
||||||
ident,
|
ident,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
attrs: variant_attrs,
|
attrs: variant_attrs,
|
||||||
data: struct_def,
|
data: struct_def,
|
||||||
disr_expr,
|
disr_expr,
|
||||||
|
@ -1622,7 +1623,7 @@ impl<'a> Parser<'a> {
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
if self.eat(&token::Semi) {
|
if self.eat(&token::Semi) {
|
||||||
// If we see a: `struct Foo<T> where T: Copy;` style decl.
|
// If we see a: `struct Foo<T> where T: Copy;` style decl.
|
||||||
VariantData::Unit(ast::DUMMY_NODE_ID)
|
VariantData::Unit(DUMMY_NODE_ID)
|
||||||
} else {
|
} else {
|
||||||
// If we see: `struct Foo<T> where T: Copy { ... }`
|
// If we see: `struct Foo<T> where T: Copy { ... }`
|
||||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||||
|
@ -1630,14 +1631,14 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
// No `where` so: `struct Foo<T>;`
|
// No `where` so: `struct Foo<T>;`
|
||||||
} else if self.eat(&token::Semi) {
|
} else if self.eat(&token::Semi) {
|
||||||
VariantData::Unit(ast::DUMMY_NODE_ID)
|
VariantData::Unit(DUMMY_NODE_ID)
|
||||||
// Record-style struct definition
|
// Record-style struct definition
|
||||||
} else if self.token == token::OpenDelim(token::Brace) {
|
} else if self.token == token::OpenDelim(token::Brace) {
|
||||||
let (fields, recovered) = self.parse_record_struct_body()?;
|
let (fields, recovered) = self.parse_record_struct_body()?;
|
||||||
VariantData::Struct(fields, recovered)
|
VariantData::Struct(fields, recovered)
|
||||||
// Tuple-style struct definition with optional where-clause.
|
// Tuple-style struct definition with optional where-clause.
|
||||||
} else if self.token == token::OpenDelim(token::Paren) {
|
} else if self.token == token::OpenDelim(token::Paren) {
|
||||||
let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
|
let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID);
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
self.expect(&token::Semi)?;
|
self.expect(&token::Semi)?;
|
||||||
body
|
body
|
||||||
|
@ -1726,7 +1727,7 @@ impl<'a> Parser<'a> {
|
||||||
span: lo.to(ty.span),
|
span: lo.to(ty.span),
|
||||||
vis,
|
vis,
|
||||||
ident: None,
|
ident: None,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
ty,
|
ty,
|
||||||
attrs,
|
attrs,
|
||||||
})
|
})
|
||||||
|
@ -1817,7 +1818,7 @@ impl<'a> Parser<'a> {
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
ident: Some(name),
|
ident: Some(name),
|
||||||
vis,
|
vis,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
ty,
|
ty,
|
||||||
attrs,
|
attrs,
|
||||||
})
|
})
|
||||||
|
@ -1909,7 +1910,7 @@ impl<'a> Parser<'a> {
|
||||||
P(Item {
|
P(Item {
|
||||||
ident,
|
ident,
|
||||||
attrs,
|
attrs,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
node,
|
node,
|
||||||
vis,
|
vis,
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -36,12 +36,12 @@ impl<'a> Parser<'a> {
|
||||||
krate
|
krate
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a `mod <foo> { ... }` or `mod <foo>;` item
|
/// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
|
||||||
pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> {
|
pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> {
|
||||||
let (in_cfg, outer_attrs) = {
|
let (in_cfg, outer_attrs) = {
|
||||||
let mut strip_unconfigured = crate::config::StripUnconfigured {
|
let mut strip_unconfigured = crate::config::StripUnconfigured {
|
||||||
sess: self.sess,
|
sess: self.sess,
|
||||||
features: None, // don't perform gated feature checking
|
features: None, // Don't perform gated feature checking.
|
||||||
};
|
};
|
||||||
let mut outer_attrs = outer_attrs.to_owned();
|
let mut outer_attrs = outer_attrs.to_owned();
|
||||||
strip_unconfigured.process_cfg_attrs(&mut outer_attrs);
|
strip_unconfigured.process_cfg_attrs(&mut outer_attrs);
|
||||||
|
@ -57,7 +57,7 @@ impl<'a> Parser<'a> {
|
||||||
self.submod_path(id, &outer_attrs, id_span)?;
|
self.submod_path(id, &outer_attrs, id_span)?;
|
||||||
let (module, mut attrs) =
|
let (module, mut attrs) =
|
||||||
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
|
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
|
||||||
// Record that we fetched the mod from an external file
|
// Record that we fetched the mod from an external file.
|
||||||
if warn {
|
if warn {
|
||||||
let attr = attr::mk_attr_outer(
|
let attr = attr::mk_attr_outer(
|
||||||
attr::mk_word_item(Ident::with_dummy_span(sym::warn_directory_ownership)));
|
attr::mk_word_item(Ident::with_dummy_span(sym::warn_directory_ownership)));
|
||||||
|
|
|
@ -844,14 +844,14 @@ impl<'a> Parser<'a> {
|
||||||
// Check if a colon exists one ahead. This means we're parsing a fieldname.
|
// Check if a colon exists one ahead. This means we're parsing a fieldname.
|
||||||
let hi;
|
let hi;
|
||||||
let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
|
let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
|
||||||
// Parsing a pattern of the form "fieldname: pat"
|
// Parsing a pattern of the form `fieldname: pat`.
|
||||||
let fieldname = self.parse_field_name()?;
|
let fieldname = self.parse_field_name()?;
|
||||||
self.bump();
|
self.bump();
|
||||||
let pat = self.parse_pat_with_or_inner()?;
|
let pat = self.parse_pat_with_or_inner()?;
|
||||||
hi = pat.span;
|
hi = pat.span;
|
||||||
(pat, fieldname, false)
|
(pat, fieldname, false)
|
||||||
} else {
|
} else {
|
||||||
// Parsing a pattern of the form "(box) (ref) (mut) fieldname"
|
// Parsing a pattern of the form `(box) (ref) (mut) fieldname`.
|
||||||
let is_box = self.eat_keyword(kw::Box);
|
let is_box = self.eat_keyword(kw::Box);
|
||||||
let boxed_span = self.token.span;
|
let boxed_span = self.token.span;
|
||||||
let is_ref = self.eat_keyword(kw::Ref);
|
let is_ref = self.eat_keyword(kw::Ref);
|
||||||
|
|
|
@ -5,12 +5,12 @@ use super::pat::GateOr;
|
||||||
|
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::{maybe_whole, ThinVec};
|
use crate::{maybe_whole, ThinVec};
|
||||||
use crate::ast::{self, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
|
use crate::ast::{self, DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind};
|
||||||
use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter};
|
use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter};
|
||||||
use crate::ext::base::DummyResult;
|
use crate::ext::base::DummyResult;
|
||||||
use crate::parse::{classify, DirectoryOwnership};
|
use crate::parse::{classify, DirectoryOwnership};
|
||||||
use crate::parse::diagnostics::Error;
|
use crate::parse::diagnostics::Error;
|
||||||
use crate::parse::token::{self};
|
use crate::parse::token;
|
||||||
use crate::source_map::{respan, Span};
|
use crate::source_map::{respan, Span};
|
||||||
use crate::symbol::{kw, sym};
|
use crate::symbol::{kw, sym};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ use std::mem;
|
||||||
use errors::Applicability;
|
use errors::Applicability;
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
/// Parse a statement. This stops just before trailing semicolons on everything but items.
|
/// Parses 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>> {
|
pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> {
|
||||||
Ok(self.parse_stmt_(true))
|
Ok(self.parse_stmt_(true))
|
||||||
|
@ -43,7 +43,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
Ok(Some(if self.eat_keyword(kw::Let) {
|
Ok(Some(if self.eat_keyword(kw::Let) {
|
||||||
Stmt {
|
Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
node: StmtKind::Local(self.parse_local(attrs.into())?),
|
node: StmtKind::Local(self.parse_local(attrs.into())?),
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ impl<'a> Parser<'a> {
|
||||||
lo,
|
lo,
|
||||||
)? {
|
)? {
|
||||||
Stmt {
|
Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
node: StmtKind::Item(macro_def),
|
node: StmtKind::Item(macro_def),
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ impl<'a> Parser<'a> {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
return Ok(Some(Stmt {
|
return Ok(Some(Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
node: StmtKind::Expr(expr),
|
node: StmtKind::Expr(expr),
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
}));
|
}));
|
||||||
|
@ -114,17 +114,17 @@ impl<'a> Parser<'a> {
|
||||||
// We used to incorrectly stop parsing macro-expanded statements here.
|
// We used to incorrectly stop parsing macro-expanded statements here.
|
||||||
// If the next token will be an error anyway but could have parsed with the
|
// If the next token will be an error anyway but could have parsed with the
|
||||||
// earlier behavior, stop parsing here and emit a warning to avoid breakage.
|
// earlier behavior, stop parsing here and emit a warning to avoid breakage.
|
||||||
else if macro_legacy_warnings &&
|
else if macro_legacy_warnings && self.token.can_begin_expr() &&
|
||||||
self.token.can_begin_expr() &&
|
match self.token.kind {
|
||||||
match self.token.kind {
|
// These can continue an expression, so we can't stop parsing and warn.
|
||||||
// These can continue an expression, so we can't stop parsing and warn.
|
token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
|
||||||
token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
|
token::BinOp(token::Minus) | token::BinOp(token::Star) |
|
||||||
token::BinOp(token::Minus) | token::BinOp(token::Star) |
|
token::BinOp(token::And) | token::BinOp(token::Or) |
|
||||||
token::BinOp(token::And) | token::BinOp(token::Or) |
|
token::AndAnd | token::OrOr |
|
||||||
token::AndAnd | token::OrOr |
|
token::DotDot | token::DotDotDot | token::DotDotEq => false,
|
||||||
token::DotDot | token::DotDotDot | token::DotDotEq => false,
|
_ => true,
|
||||||
_ => true,
|
}
|
||||||
} {
|
{
|
||||||
self.warn_missing_semicolon();
|
self.warn_missing_semicolon();
|
||||||
StmtKind::Mac(P((mac, style, attrs.into())))
|
StmtKind::Mac(P((mac, style, attrs.into())))
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,7 +135,7 @@ impl<'a> Parser<'a> {
|
||||||
StmtKind::Expr(e)
|
StmtKind::Expr(e)
|
||||||
};
|
};
|
||||||
Stmt {
|
Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
node,
|
node,
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
Some(i) => Stmt {
|
Some(i) => Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(i.span),
|
span: lo.to(i.span),
|
||||||
node: StmtKind::Item(i),
|
node: StmtKind::Item(i),
|
||||||
},
|
},
|
||||||
|
@ -178,7 +178,7 @@ impl<'a> Parser<'a> {
|
||||||
// an empty tuple that spans the excess semicolons
|
// an empty tuple that spans the excess semicolons
|
||||||
// to preserve this info until the lint stage
|
// to preserve this info until the lint stage
|
||||||
return Ok(Some(Stmt {
|
return Ok(Some(Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(last_semi),
|
span: lo.to(last_semi),
|
||||||
node: StmtKind::Semi(self.mk_expr(lo.to(last_semi),
|
node: StmtKind::Semi(self.mk_expr(lo.to(last_semi),
|
||||||
ExprKind::Tup(Vec::new()),
|
ExprKind::Tup(Vec::new()),
|
||||||
|
@ -196,7 +196,7 @@ impl<'a> Parser<'a> {
|
||||||
let e = self.parse_expr_res(
|
let e = self.parse_expr_res(
|
||||||
Restrictions::STMT_EXPR, Some(attrs.into()))?;
|
Restrictions::STMT_EXPR, Some(attrs.into()))?;
|
||||||
Stmt {
|
Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(e.span),
|
span: lo.to(e.span),
|
||||||
node: StmtKind::Expr(e),
|
node: StmtKind::Expr(e),
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ impl<'a> Parser<'a> {
|
||||||
match self.parse_ty() {
|
match self.parse_ty() {
|
||||||
Ok(ty) => (None, Some(ty)),
|
Ok(ty) => (None, Some(ty)),
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
// Rewind to before attempting to parse the type and continue parsing
|
// Rewind to before attempting to parse the type and continue parsing.
|
||||||
let parser_snapshot_after_type = self.clone();
|
let parser_snapshot_after_type = self.clone();
|
||||||
mem::replace(self, parser_snapshot_before_type);
|
mem::replace(self, parser_snapshot_before_type);
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ impl<'a> Parser<'a> {
|
||||||
ty,
|
ty,
|
||||||
pat,
|
pat,
|
||||||
init,
|
init,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
span: lo.to(hi),
|
span: lo.to(hi),
|
||||||
attrs,
|
attrs,
|
||||||
}))
|
}))
|
||||||
|
@ -334,18 +334,18 @@ impl<'a> Parser<'a> {
|
||||||
// if (cond)
|
// if (cond)
|
||||||
// bar;
|
// bar;
|
||||||
//
|
//
|
||||||
// Which is valid in other languages, but not Rust.
|
// which is valid in other languages, but not Rust.
|
||||||
match self.parse_stmt_without_recovery(false) {
|
match self.parse_stmt_without_recovery(false) {
|
||||||
Ok(Some(stmt)) => {
|
Ok(Some(stmt)) => {
|
||||||
if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
|
if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
|
||||||
|| do_not_suggest_help {
|
|| do_not_suggest_help {
|
||||||
// if the next token is an open brace (e.g., `if a b {`), the place-
|
// If the next token is an open brace (e.g., `if a b {`), the place-
|
||||||
// inside-a-block suggestion would be more likely wrong than right
|
// inside-a-block suggestion would be more likely wrong than right.
|
||||||
e.span_label(sp, "expected `{`");
|
e.span_label(sp, "expected `{`");
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
let mut stmt_span = stmt.span;
|
let mut stmt_span = stmt.span;
|
||||||
// expand the span to include the semicolon, if it exists
|
// Expand the span to include the semicolon, if it exists.
|
||||||
if self.eat(&token::Semi) {
|
if self.eat(&token::Semi) {
|
||||||
stmt_span = stmt_span.with_hi(self.prev_span.hi());
|
stmt_span = stmt_span.with_hi(self.prev_span.hi());
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,7 @@ impl<'a> Parser<'a> {
|
||||||
stmt_span,
|
stmt_span,
|
||||||
"try placing this code inside a block",
|
"try placing this code inside a block",
|
||||||
format!("{{ {} }}", snippet),
|
format!("{{ {} }}", snippet),
|
||||||
// speculative, has been misleading in the past (#46836)
|
// Speculative; has been misleading in the past (#46836).
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,7 @@ impl<'a> Parser<'a> {
|
||||||
err.emit();
|
err.emit();
|
||||||
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
|
self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
|
||||||
Some(Stmt {
|
Some(Stmt {
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
node: StmtKind::Expr(DummyResult::raw_expr(self.token.span, true)),
|
node: StmtKind::Expr(DummyResult::raw_expr(self.token.span, true)),
|
||||||
span: self.token.span,
|
span: self.token.span,
|
||||||
})
|
})
|
||||||
|
@ -415,15 +415,15 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Ok(P(ast::Block {
|
Ok(P(ast::Block {
|
||||||
stmts,
|
stmts,
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
rules: s,
|
rules: s,
|
||||||
span: lo.to(self.prev_span),
|
span: lo.to(self.prev_span),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a statement, including the trailing semicolon.
|
/// Parses a statement, including the trailing semicolon.
|
||||||
crate fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option<Stmt>> {
|
pub fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option<Stmt>> {
|
||||||
// skip looking for a trailing semicolon when we have an interpolated statement
|
// Skip looking for a trailing semicolon when we have an interpolated statement.
|
||||||
maybe_whole!(self, NtStmt, |x| Some(x));
|
maybe_whole!(self, NtStmt, |x| Some(x));
|
||||||
|
|
||||||
let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? {
|
let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? {
|
||||||
|
|
|
@ -25,12 +25,12 @@ fn parse_item_from_source_str(name: FileName, source: String, sess: &ParseSess)
|
||||||
new_parser_from_source_str(sess, name, source).parse_item()
|
new_parser_from_source_str(sess, name, source).parse_item()
|
||||||
}
|
}
|
||||||
|
|
||||||
// produce a syntax_pos::span
|
// Produces a `syntax_pos::span`.
|
||||||
fn sp(a: u32, b: u32) -> Span {
|
fn sp(a: u32, b: u32) -> Span {
|
||||||
Span::with_root_ctxt(BytePos(a), BytePos(b))
|
Span::with_root_ctxt(BytePos(a), BytePos(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string, return an expr
|
/// Parses a string, return an expression.
|
||||||
fn string_to_expr(source_str : String) -> P<ast::Expr> {
|
fn string_to_expr(source_str : String) -> P<ast::Expr> {
|
||||||
let ps = ParseSess::new(FilePathMapping::empty());
|
let ps = ParseSess::new(FilePathMapping::empty());
|
||||||
with_error_checking_parse(source_str, &ps, |p| {
|
with_error_checking_parse(source_str, &ps, |p| {
|
||||||
|
@ -38,7 +38,7 @@ fn string_to_expr(source_str : String) -> P<ast::Expr> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string, return an item
|
/// Parses a string, returns an item.
|
||||||
fn string_to_item(source_str : String) -> Option<P<ast::Item>> {
|
fn string_to_item(source_str : String) -> Option<P<ast::Item>> {
|
||||||
let ps = ParseSess::new(FilePathMapping::empty());
|
let ps = ParseSess::new(FilePathMapping::empty());
|
||||||
with_error_checking_parse(source_str, &ps, |p| {
|
with_error_checking_parse(source_str, &ps, |p| {
|
||||||
|
@ -53,7 +53,7 @@ fn string_to_item(source_str : String) -> Option<P<ast::Item>> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the token-tree-ization of macros
|
// Checks the token-tree-ization of macros.
|
||||||
#[test]
|
#[test]
|
||||||
fn string_to_tts_macro () {
|
fn string_to_tts_macro () {
|
||||||
with_default_globals(|| {
|
with_default_globals(|| {
|
||||||
|
|
|
@ -119,19 +119,19 @@ pub fn print_crate<'a>(cm: &'a SourceMap,
|
||||||
if is_expanded && sess.injected_crate_name.try_get().is_some() {
|
if is_expanded && sess.injected_crate_name.try_get().is_some() {
|
||||||
// We need to print `#![no_std]` (and its feature gate) so that
|
// We need to print `#![no_std]` (and its feature gate) so that
|
||||||
// compiling pretty-printed source won't inject libstd again.
|
// compiling pretty-printed source won't inject libstd again.
|
||||||
// However we don't want these attributes in the AST because
|
// However, we don't want these attributes in the AST because
|
||||||
// of the feature gate, so we fake them up here.
|
// of the feature gate, so we fake them up here.
|
||||||
|
|
||||||
// #![feature(prelude_import)]
|
// `#![feature(prelude_import)]`
|
||||||
let pi_nested = attr::mk_nested_word_item(ast::Ident::with_dummy_span(sym::prelude_import));
|
let pi_nested = attr::mk_nested_word_item(ast::Ident::with_dummy_span(sym::prelude_import));
|
||||||
let list = attr::mk_list_item(ast::Ident::with_dummy_span(sym::feature), vec![pi_nested]);
|
let list = attr::mk_list_item(ast::Ident::with_dummy_span(sym::feature), vec![pi_nested]);
|
||||||
let fake_attr = attr::mk_attr_inner(list);
|
let fake_attr = attr::mk_attr_inner(list);
|
||||||
s.print_attribute(&fake_attr);
|
s.print_attribute(&fake_attr);
|
||||||
|
|
||||||
// Currently on Rust 2018 we don't have `extern crate std;` at the crate
|
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
|
||||||
// root, so this is not needed, and actually breaks things.
|
// root, so this is not needed, and actually breaks things.
|
||||||
if sess.edition == syntax_pos::edition::Edition::Edition2015 {
|
if sess.edition == syntax_pos::edition::Edition::Edition2015 {
|
||||||
// #![no_std]
|
// `#![no_std]`
|
||||||
let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std));
|
let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std));
|
||||||
let fake_attr = attr::mk_attr_inner(no_std_meta);
|
let fake_attr = attr::mk_attr_inner(no_std_meta);
|
||||||
s.print_attribute(&fake_attr);
|
s.print_attribute(&fake_attr);
|
||||||
|
@ -398,9 +398,9 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
|
||||||
|
|
||||||
fn block_to_string(blk: &ast::Block) -> String {
|
fn block_to_string(blk: &ast::Block) -> String {
|
||||||
to_string(|s| {
|
to_string(|s| {
|
||||||
// containing cbox, will be closed by print-block at }
|
// Containing cbox, will be closed by `print_block` at `}`.
|
||||||
s.cbox(INDENT_UNIT);
|
s.cbox(INDENT_UNIT);
|
||||||
// head-ibox, will be closed by print-block after {
|
// Head-ibox, will be closed by `print_block` after `{`.
|
||||||
s.ibox(0);
|
s.ibox(0);
|
||||||
s.print_block(blk)
|
s.print_block(blk)
|
||||||
})
|
})
|
||||||
|
@ -443,7 +443,7 @@ impl std::ops::DerefMut for State<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefMut {
|
pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
|
||||||
fn comments(&mut self) -> &mut Option<Comments<'a>>;
|
fn comments(&mut self) -> &mut Option<Comments<'a>>;
|
||||||
fn print_ident(&mut self, ident: ast::Ident);
|
fn print_ident(&mut self, ident: ast::Ident);
|
||||||
fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
|
fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
|
||||||
|
@ -495,7 +495,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefM
|
||||||
self.hardbreak_if_not_bol();
|
self.hardbreak_if_not_bol();
|
||||||
for line in &cmnt.lines {
|
for line in &cmnt.lines {
|
||||||
// Don't print empty lines because they will end up as trailing
|
// Don't print empty lines because they will end up as trailing
|
||||||
// whitespace
|
// whitespace.
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
self.word(line.clone());
|
self.word(line.clone());
|
||||||
}
|
}
|
||||||
|
@ -783,11 +783,11 @@ pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefM
|
||||||
|
|
||||||
fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
|
fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
|
||||||
let w = w.into();
|
let w = w.into();
|
||||||
// outer-box is consistent
|
// Outer-box is consistent.
|
||||||
self.cbox(INDENT_UNIT);
|
self.cbox(INDENT_UNIT);
|
||||||
// head-box is inconsistent
|
// Head-box is inconsistent.
|
||||||
self.ibox(w.len() + 1);
|
self.ibox(w.len() + 1);
|
||||||
// keyword that starts the head
|
// Keyword that starts the head.
|
||||||
if !w.is_empty() {
|
if !w.is_empty() {
|
||||||
self.word_nbsp(w);
|
self.word_nbsp(w);
|
||||||
}
|
}
|
||||||
|
@ -795,7 +795,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefM
|
||||||
|
|
||||||
fn bopen(&mut self) {
|
fn bopen(&mut self) {
|
||||||
self.word("{");
|
self.word("{");
|
||||||
self.end(); // close the head-box
|
self.end(); // Close the head-box.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bclose_maybe_open(&mut self, span: syntax_pos::Span, close_box: bool) {
|
fn bclose_maybe_open(&mut self, span: syntax_pos::Span, close_box: bool) {
|
||||||
|
@ -803,7 +803,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefM
|
||||||
self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
|
self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
|
||||||
self.word("}");
|
self.word("}");
|
||||||
if close_box {
|
if close_box {
|
||||||
self.end(); // close the outer-box
|
self.end(); // Close the outer-box.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,8 +900,6 @@ impl<'a> State<'a> {
|
||||||
self.s.word("*/")
|
self.s.word("*/")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
crate fn commasep_cmnt<T, F, G>(&mut self,
|
crate fn commasep_cmnt<T, F, G>(&mut self,
|
||||||
b: Breaks,
|
b: Breaks,
|
||||||
elts: &[T],
|
elts: &[T],
|
||||||
|
@ -928,12 +926,12 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn commasep_exprs(&mut self, b: Breaks,
|
crate fn commasep_exprs(&mut self, b: Breaks,
|
||||||
exprs: &[P<ast::Expr>]) {
|
exprs: &[P<ast::Expr>]) {
|
||||||
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
|
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn print_mod(&mut self, _mod: &ast::Mod,
|
crate fn print_mod(&mut self, _mod: &ast::Mod,
|
||||||
attrs: &[ast::Attribute]) {
|
attrs: &[ast::Attribute]) {
|
||||||
self.print_inner_attributes(attrs);
|
self.print_inner_attributes(attrs);
|
||||||
for item in &_mod.items {
|
for item in &_mod.items {
|
||||||
self.print_item(item);
|
self.print_item(item);
|
||||||
|
@ -941,7 +939,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
|
crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
|
||||||
attrs: &[ast::Attribute]) {
|
attrs: &[ast::Attribute]) {
|
||||||
self.print_inner_attributes(attrs);
|
self.print_inner_attributes(attrs);
|
||||||
for item in &nmod.items {
|
for item in &nmod.items {
|
||||||
self.print_foreign_item(item);
|
self.print_foreign_item(item);
|
||||||
|
@ -1136,7 +1134,7 @@ impl<'a> State<'a> {
|
||||||
self.s.word(";")
|
self.s.word(";")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pretty-print an item
|
/// Pretty-prints an item.
|
||||||
crate fn print_item(&mut self, item: &ast::Item) {
|
crate fn print_item(&mut self, item: &ast::Item) {
|
||||||
self.hardbreak_if_not_bol();
|
self.hardbreak_if_not_bol();
|
||||||
self.maybe_print_comment(item.span.lo());
|
self.maybe_print_comment(item.span.lo());
|
||||||
|
@ -1489,7 +1487,7 @@ impl<'a> State<'a> {
|
||||||
self.s.word(";");
|
self.s.word(";");
|
||||||
}
|
}
|
||||||
self.end();
|
self.end();
|
||||||
self.end(); // close the outer-box
|
self.end(); // Close the outer-box.
|
||||||
}
|
}
|
||||||
ast::VariantData::Struct(..) => {
|
ast::VariantData::Struct(..) => {
|
||||||
self.print_where_clause(&generics.where_clause);
|
self.print_where_clause(&generics.where_clause);
|
||||||
|
@ -1793,7 +1791,7 @@ impl<'a> State<'a> {
|
||||||
self.print_expr_cond_paren(expr, expr.precedence().order() < prec)
|
self.print_expr_cond_paren(expr, expr.precedence().order() < prec)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
|
/// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
|
||||||
/// `if cond { ... }`.
|
/// `if cond { ... }`.
|
||||||
crate fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
|
crate fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
|
||||||
self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
|
self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
|
||||||
|
@ -1812,7 +1810,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print `expr` or `(expr)` when `needs_par` holds.
|
/// Prints `expr` or `(expr)` when `needs_par` holds.
|
||||||
fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
|
fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
|
||||||
if needs_par {
|
if needs_par {
|
||||||
self.popen();
|
self.popen();
|
||||||
|
@ -2456,7 +2454,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_arm(&mut self, arm: &ast::Arm) {
|
fn print_arm(&mut self, arm: &ast::Arm) {
|
||||||
// I have no idea why this check is necessary, but here it is :(
|
// Note, I have no idea why this check is necessary, but here it is.
|
||||||
if arm.attrs.is_empty() {
|
if arm.attrs.is_empty() {
|
||||||
self.s.space();
|
self.s.space();
|
||||||
}
|
}
|
||||||
|
@ -2480,21 +2478,21 @@ impl<'a> State<'a> {
|
||||||
self.word_space(":");
|
self.word_space(":");
|
||||||
}
|
}
|
||||||
|
|
||||||
// the block will close the pattern's ibox
|
// The block will close the pattern's ibox.
|
||||||
self.print_block_unclosed_indent(blk);
|
self.print_block_unclosed_indent(blk);
|
||||||
|
|
||||||
// If it is a user-provided unsafe block, print a comma after it
|
// If it is a user-provided unsafe block, print a comma after it.
|
||||||
if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
|
if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
|
||||||
self.s.word(",");
|
self.s.word(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.end(); // close the ibox for the pattern
|
self.end(); // Close the ibox for the pattern.
|
||||||
self.print_expr(&arm.body);
|
self.print_expr(&arm.body);
|
||||||
self.s.word(",");
|
self.s.word(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.end(); // close enclosing cbox
|
self.end(); // Close enclosing cbox.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) {
|
fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) {
|
||||||
|
|
|
@ -12,8 +12,8 @@ fn fun_to_string(
|
||||||
s.head("");
|
s.head("");
|
||||||
s.print_fn(decl, header, Some(name),
|
s.print_fn(decl, header, Some(name),
|
||||||
generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited));
|
generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited));
|
||||||
s.end(); // Close the head box
|
s.end(); // Close the head box.
|
||||||
s.end(); // Close the outer box
|
s.end(); // Close the outer box.
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ fn test_variant_to_string() {
|
||||||
ident,
|
ident,
|
||||||
attrs: Vec::new(),
|
attrs: Vec::new(),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
// making this up as I go.... ?
|
|
||||||
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
|
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
|
||||||
disr_expr: None,
|
disr_expr: None,
|
||||||
span: syntax_pos::DUMMY_SP,
|
span: syntax_pos::DUMMY_SP,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
//! The SourceMap tracks all the source code used within a single crate, mapping
|
//! The `SourceMap` tracks all the source code used within a single crate, mapping
|
||||||
//! from integer byte positions to the original source code location. Each bit
|
//! from integer byte positions to the original source code location. Each bit
|
||||||
//! of source parsed during crate parsing (typically files, in-memory strings,
|
//! of source parsed during crate parsing (typically files, in-memory strings,
|
||||||
//! or various bits of macro expansion) cover a continuous range of bytes in the
|
//! or various bits of macro expansion) cover a continuous range of bytes in the
|
||||||
//! SourceMap and are represented by SourceFiles. Byte positions are stored in
|
//! `SourceMap` and are represented by `SourceFile`s. Byte positions are stored in
|
||||||
//! `spans` and used pervasively in the compiler. They are absolute positions
|
//! `Span`` and used pervasively in the compiler. They are absolute positions
|
||||||
//! within the SourceMap, which upon request can be converted to line and column
|
//! within the `SourceMap`, which upon request can be converted to line and column
|
||||||
//! information, source code snippets, etc.
|
//! information, source code snippets, etc.
|
||||||
|
|
||||||
pub use syntax_pos::*;
|
pub use syntax_pos::*;
|
||||||
|
@ -94,7 +94,7 @@ impl FileLoader for RealFileLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a SourceFile identifier that is used to correlate SourceFiles between
|
// This is a `SourceFile` identifier that is used to correlate `SourceFile`s between
|
||||||
// subsequent compilation sessions (which is something we need to do during
|
// subsequent compilation sessions (which is something we need to do during
|
||||||
// incremental compilation).
|
// incremental compilation).
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
|
||||||
|
@ -103,8 +103,8 @@ pub struct StableSourceFileId(u128);
|
||||||
impl StableSourceFileId {
|
impl StableSourceFileId {
|
||||||
pub fn new(source_file: &SourceFile) -> StableSourceFileId {
|
pub fn new(source_file: &SourceFile) -> StableSourceFileId {
|
||||||
StableSourceFileId::new_from_pieces(&source_file.name,
|
StableSourceFileId::new_from_pieces(&source_file.name,
|
||||||
source_file.name_was_remapped,
|
source_file.name_was_remapped,
|
||||||
source_file.unmapped_path.as_ref())
|
source_file.unmapped_path.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_pieces(name: &FileName,
|
pub fn new_from_pieces(name: &FileName,
|
||||||
|
@ -134,7 +134,7 @@ pub struct SourceMap {
|
||||||
files: Lock<SourceMapFiles>,
|
files: Lock<SourceMapFiles>,
|
||||||
file_loader: Box<dyn FileLoader + Sync + Send>,
|
file_loader: Box<dyn FileLoader + Sync + Send>,
|
||||||
// This is used to apply the file path remapping as specified via
|
// This is used to apply the file path remapping as specified via
|
||||||
// --remap-path-prefix to all SourceFiles allocated within this SourceMap.
|
// `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
|
||||||
path_mapping: FilePathMapping,
|
path_mapping: FilePathMapping,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,14 +204,14 @@ impl SourceMap {
|
||||||
match self.files.borrow().source_files.last() {
|
match self.files.borrow().source_files.last() {
|
||||||
None => 0,
|
None => 0,
|
||||||
// Add one so there is some space between files. This lets us distinguish
|
// Add one so there is some space between files. This lets us distinguish
|
||||||
// positions in the source_map, even in the presence of zero-length files.
|
// positions in the `SourceMap`, even in the presence of zero-length files.
|
||||||
Some(last) => last.end_pos.to_usize() + 1,
|
Some(last) => last.end_pos.to_usize() + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new source_file.
|
/// Creates a new `SourceFile`.
|
||||||
/// If a file already exists in the source_map with the same id, that file is returned
|
/// If a file already exists in the `SourceMap` with the same ID, that file is returned
|
||||||
/// unmodified
|
/// unmodified.
|
||||||
pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile> {
|
pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile> {
|
||||||
self.try_new_source_file(filename, src)
|
self.try_new_source_file(filename, src)
|
||||||
.unwrap_or_else(|OffsetOverflowError| {
|
.unwrap_or_else(|OffsetOverflowError| {
|
||||||
|
@ -268,8 +268,8 @@ impl SourceMap {
|
||||||
Ok(lrc_sf)
|
Ok(lrc_sf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocates a new SourceFile representing a source file from an external
|
/// Allocates a new `SourceFile` representing a source file from an external
|
||||||
/// crate. The source code of such an "imported source_file" is not available,
|
/// crate. The source code of such an "imported `SourceFile`" is not available,
|
||||||
/// but we still know enough to generate accurate debuginfo location
|
/// but we still know enough to generate accurate debuginfo location
|
||||||
/// information for things inlined from other crates.
|
/// information for things inlined from other crates.
|
||||||
pub fn new_imported_source_file(
|
pub fn new_imported_source_file(
|
||||||
|
@ -334,7 +334,7 @@ impl SourceMap {
|
||||||
pos.col.to_usize() + 1)
|
pos.col.to_usize() + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a doctest_offset, apply it to the line
|
// If there is a doctest offset, applies it to the line.
|
||||||
pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize {
|
pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize {
|
||||||
return match file {
|
return match file {
|
||||||
FileName::DocTest(_, offset) => {
|
FileName::DocTest(_, offset) => {
|
||||||
|
@ -348,7 +348,7 @@ impl SourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup source information about a BytePos
|
/// Looks up source information about a `BytePos`.
|
||||||
pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
|
pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
|
||||||
let chpos = self.bytepos_to_file_charpos(pos);
|
let chpos = self.bytepos_to_file_charpos(pos);
|
||||||
match self.lookup_line(pos) {
|
match self.lookup_line(pos) {
|
||||||
|
@ -411,7 +411,7 @@ impl SourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the relevant source_file is empty, we don't return a line number.
|
// If the corresponding `SourceFile` is empty, does not return a line number.
|
||||||
pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceFile>> {
|
pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceFile>> {
|
||||||
let idx = self.lookup_source_file_idx(pos);
|
let idx = self.lookup_source_file_idx(pos);
|
||||||
|
|
||||||
|
@ -423,15 +423,15 @@ impl SourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `Some(span)`, a union of the lhs and rhs span. The lhs must precede the rhs. If
|
/// Returns `Some(span)`, a union of the LHS and RHS span. The LHS must precede the RHS. If
|
||||||
/// there are gaps between lhs and rhs, the resulting union will cross these gaps.
|
/// there are gaps between LHS and RHS, the resulting union will cross these gaps.
|
||||||
/// For this to work, the spans have to be:
|
/// For this to work,
|
||||||
///
|
///
|
||||||
/// * the ctxt of both spans much match
|
/// * the syntax contexts of both spans much match,
|
||||||
/// * the lhs span needs to end on the same line the rhs span begins
|
/// * the LHS span needs to end on the same line the RHS span begins,
|
||||||
/// * the lhs span must start at or before the rhs span
|
/// * the LHS span must start at or before the RHS span.
|
||||||
pub fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
|
pub fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
|
||||||
// make sure we're at the same expansion id
|
// Ensure we're at the same expansion ID.
|
||||||
if sp_lhs.ctxt() != sp_rhs.ctxt() {
|
if sp_lhs.ctxt() != sp_rhs.ctxt() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -445,12 +445,12 @@ impl SourceMap {
|
||||||
Err(_) => return None
|
Err(_) => return None
|
||||||
};
|
};
|
||||||
|
|
||||||
// if we must cross lines to merge, don't merge
|
// If we must cross lines to merge, don't merge.
|
||||||
if lhs_end.line != rhs_begin.line {
|
if lhs_end.line != rhs_begin.line {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure these follow the expected order and we don't overlap
|
// Ensure these follow the expected order and that we don't overlap.
|
||||||
if (sp_lhs.lo() <= sp_rhs.lo()) && (sp_lhs.hi() <= sp_rhs.lo()) {
|
if (sp_lhs.lo() <= sp_rhs.lo()) && (sp_lhs.hi() <= sp_rhs.lo()) {
|
||||||
Some(sp_lhs.to(sp_rhs))
|
Some(sp_lhs.to(sp_rhs))
|
||||||
} else {
|
} else {
|
||||||
|
@ -466,11 +466,12 @@ impl SourceMap {
|
||||||
let lo = self.lookup_char_pos(sp.lo());
|
let lo = self.lookup_char_pos(sp.lo());
|
||||||
let hi = self.lookup_char_pos(sp.hi());
|
let hi = self.lookup_char_pos(sp.hi());
|
||||||
format!("{}:{}:{}: {}:{}",
|
format!("{}:{}:{}: {}:{}",
|
||||||
lo.file.name,
|
lo.file.name,
|
||||||
lo.line,
|
lo.line,
|
||||||
lo.col.to_usize() + 1,
|
lo.col.to_usize() + 1,
|
||||||
hi.line,
|
hi.line,
|
||||||
hi.col.to_usize() + 1)
|
hi.col.to_usize() + 1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_to_filename(&self, sp: Span) -> FileName {
|
pub fn span_to_filename(&self, sp: Span) -> FileName {
|
||||||
|
@ -478,8 +479,8 @@ impl SourceMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_to_unmapped_path(&self, sp: Span) -> FileName {
|
pub fn span_to_unmapped_path(&self, sp: Span) -> FileName {
|
||||||
self.lookup_char_pos(sp.lo()).file.unmapped_path.clone()
|
let source_file = self.lookup_char_pos(sp.lo()).file;
|
||||||
.expect("SourceMap::span_to_unmapped_path called for imported SourceFile?")
|
source_file.unmapped_path.clone().unwrap_or(source_file.name.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_multiline(&self, sp: Span) -> bool {
|
pub fn is_multiline(&self, sp: Span) -> bool {
|
||||||
|
@ -586,7 +587,7 @@ impl SourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the source snippet as `String` corresponding to the given `Span`
|
/// Returns the source snippet as `String` corresponding to the given `Span`.
|
||||||
pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
||||||
self.span_to_source(sp, |src, start_index, end_index| src.get(start_index..end_index)
|
self.span_to_source(sp, |src, start_index, end_index| src.get(start_index..end_index)
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
|
@ -602,14 +603,14 @@ impl SourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the source snippet as `String` before the given `Span`
|
/// Returns the source snippet as `String` before the given `Span`.
|
||||||
pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> {
|
||||||
self.span_to_source(sp, |src, start_index, _| src.get(..start_index)
|
self.span_to_source(sp, |src, start_index, _| src.get(..start_index)
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.ok_or_else(|| SpanSnippetError::IllFormedSpan(sp)))
|
.ok_or_else(|| SpanSnippetError::IllFormedSpan(sp)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span
|
/// Extends the given `Span` to just after the previous occurrence of `c`. Return the same span
|
||||||
/// if no character could be found or if an error occurred while retrieving the code snippet.
|
/// 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 {
|
pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
|
||||||
if let Ok(prev_source) = self.span_to_prev_source(sp) {
|
if let Ok(prev_source) = self.span_to_prev_source(sp) {
|
||||||
|
@ -622,8 +623,8 @@ impl SourceMap {
|
||||||
sp
|
sp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend the given `Span` to just after the previous occurrence of `pat` when surrounded by
|
/// Extends the given `Span` to just after the previous occurrence of `pat` when surrounded by
|
||||||
/// whitespace. Return the same span if no character could be found or if an error occurred
|
/// whitespace. Returns the same span if no character could be found or if an error occurred
|
||||||
/// while retrieving the code snippet.
|
/// while retrieving the code snippet.
|
||||||
pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool) -> Span {
|
pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool) -> Span {
|
||||||
// assure that the pattern is delimited, to avoid the following
|
// assure that the pattern is delimited, to avoid the following
|
||||||
|
@ -643,7 +644,8 @@ impl SourceMap {
|
||||||
sp
|
sp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
|
/// Given a `Span`, tries to get a shorter span ending before the first occurrence of `char`
|
||||||
|
/// ``c`.
|
||||||
pub fn span_until_char(&self, sp: Span, c: char) -> Span {
|
pub fn span_until_char(&self, sp: Span, c: char) -> Span {
|
||||||
match self.span_to_snippet(sp) {
|
match self.span_to_snippet(sp) {
|
||||||
Ok(snippet) => {
|
Ok(snippet) => {
|
||||||
|
@ -658,7 +660,7 @@ impl SourceMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
|
/// Given a `Span`, tries to get a shorter span ending just after the first occurrence of `char`
|
||||||
/// `c`.
|
/// `c`.
|
||||||
pub fn span_through_char(&self, sp: Span, c: char) -> Span {
|
pub fn span_through_char(&self, sp: Span, c: char) -> Span {
|
||||||
if let Ok(snippet) = self.span_to_snippet(sp) {
|
if let Ok(snippet) = self.span_to_snippet(sp) {
|
||||||
|
@ -669,8 +671,8 @@ impl SourceMap {
|
||||||
sp
|
sp
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or
|
/// Given a `Span`, gets a new `Span` covering the first token and all its trailing whitespace
|
||||||
/// the original `Span`.
|
/// or the original `Span`.
|
||||||
///
|
///
|
||||||
/// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
|
/// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
|
||||||
pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
|
pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
|
||||||
|
@ -689,15 +691,15 @@ impl SourceMap {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or
|
/// Given a `Span`, gets a new `Span` covering the first token without its trailing whitespace
|
||||||
/// the original `Span` in case of error.
|
/// or the original `Span` in case of error.
|
||||||
///
|
///
|
||||||
/// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
|
/// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
|
||||||
pub fn span_until_whitespace(&self, sp: Span) -> Span {
|
pub fn span_until_whitespace(&self, sp: Span) -> Span {
|
||||||
self.span_take_while(sp, |c| !c.is_whitespace())
|
self.span_take_while(sp, |c| !c.is_whitespace())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `Span`, get a shorter one until `predicate` yields false.
|
/// Given a `Span`, gets a shorter one until `predicate` yields `false`.
|
||||||
pub fn span_take_while<P>(&self, sp: Span, predicate: P) -> Span
|
pub fn span_take_while<P>(&self, sp: Span, predicate: P) -> Span
|
||||||
where P: for <'r> FnMut(&'r char) -> bool
|
where P: for <'r> FnMut(&'r char) -> bool
|
||||||
{
|
{
|
||||||
|
@ -717,7 +719,7 @@ impl SourceMap {
|
||||||
self.span_until_char(sp, '{')
|
self.span_until_char(sp, '{')
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new span representing just the start-point of this span
|
/// Returns a new span representing just the start point of this span.
|
||||||
pub fn start_point(&self, sp: Span) -> Span {
|
pub fn start_point(&self, sp: Span) -> Span {
|
||||||
let pos = sp.lo().0;
|
let pos = sp.lo().0;
|
||||||
let width = self.find_width_of_character_at_span(sp, false);
|
let width = self.find_width_of_character_at_span(sp, false);
|
||||||
|
@ -726,7 +728,7 @@ impl SourceMap {
|
||||||
sp.with_hi(end_point)
|
sp.with_hi(end_point)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new span representing just the end-point of this span
|
/// Returns a new span representing just the end point of this span.
|
||||||
pub fn end_point(&self, sp: Span) -> Span {
|
pub fn end_point(&self, sp: Span) -> Span {
|
||||||
let pos = sp.hi().0;
|
let pos = sp.hi().0;
|
||||||
|
|
||||||
|
@ -737,7 +739,7 @@ impl SourceMap {
|
||||||
sp.with_lo(end_point)
|
sp.with_lo(end_point)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new span representing the next character after the end-point of this span
|
/// Returns a new span representing the next character after the end-point of this span.
|
||||||
pub fn next_point(&self, sp: Span) -> Span {
|
pub fn next_point(&self, sp: Span) -> Span {
|
||||||
let start_of_next_point = sp.hi().0;
|
let start_of_next_point = sp.hi().0;
|
||||||
|
|
||||||
|
@ -840,7 +842,7 @@ impl SourceMap {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For a global BytePos compute the local offset within the containing SourceFile
|
/// For a global `BytePos`, computes the local offset within the containing `SourceFile`.
|
||||||
pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos {
|
pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos {
|
||||||
let idx = self.lookup_source_file_idx(bpos);
|
let idx = self.lookup_source_file_idx(bpos);
|
||||||
let sf = (*self.files.borrow().source_files)[idx].clone();
|
let sf = (*self.files.borrow().source_files)[idx].clone();
|
||||||
|
@ -848,22 +850,22 @@ impl SourceMap {
|
||||||
SourceFileAndBytePos {sf, pos: offset}
|
SourceFileAndBytePos {sf, pos: offset}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an absolute BytePos to a CharPos relative to the source_file.
|
/// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`.
|
||||||
pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
|
pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
|
||||||
let idx = self.lookup_source_file_idx(bpos);
|
let idx = self.lookup_source_file_idx(bpos);
|
||||||
let map = &(*self.files.borrow().source_files)[idx];
|
let map = &(*self.files.borrow().source_files)[idx];
|
||||||
|
|
||||||
// The number of extra bytes due to multibyte chars in the SourceFile
|
// The number of extra bytes due to multibyte chars in the `SourceFile`.
|
||||||
let mut total_extra_bytes = 0;
|
let mut total_extra_bytes = 0;
|
||||||
|
|
||||||
for mbc in map.multibyte_chars.iter() {
|
for mbc in map.multibyte_chars.iter() {
|
||||||
debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
|
debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
|
||||||
if mbc.pos < bpos {
|
if mbc.pos < bpos {
|
||||||
// every character is at least one byte, so we only
|
// Every character is at least one byte, so we only
|
||||||
// count the actual extra bytes.
|
// count the actual extra bytes.
|
||||||
total_extra_bytes += mbc.bytes as u32 - 1;
|
total_extra_bytes += mbc.bytes as u32 - 1;
|
||||||
// We should never see a byte position in the middle of a
|
// We should never see a byte position in the middle of a
|
||||||
// character
|
// character.
|
||||||
assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
|
assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -874,13 +876,13 @@ impl SourceMap {
|
||||||
CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize)
|
CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the index of the source_file (in self.files) which contains pos.
|
// Returns the index of the `SourceFile` (in `self.files`) that contains `pos`.
|
||||||
pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
|
pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
|
||||||
let files = self.files.borrow();
|
let files = self.files.borrow();
|
||||||
let files = &files.source_files;
|
let files = &files.source_files;
|
||||||
let count = files.len();
|
let count = files.len();
|
||||||
|
|
||||||
// Binary search for the source_file.
|
// Binary search for the `SourceFile`.
|
||||||
let mut a = 0;
|
let mut a = 0;
|
||||||
let mut b = count;
|
let mut b = count;
|
||||||
while b - a > 1 {
|
while b - a > 1 {
|
||||||
|
@ -911,8 +913,8 @@ impl SourceMap {
|
||||||
}).ok()
|
}).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take the span of a type parameter in a function signature and try to generate a span for the
|
/// Takes the span of a type parameter in a function signature and try to generate a span for
|
||||||
/// function name (with generics) and a new snippet for this span with the pointed type
|
/// the function name (with generics) and a new snippet for this span with the pointed type
|
||||||
/// parameter as a new local type parameter.
|
/// parameter as a new local type parameter.
|
||||||
///
|
///
|
||||||
/// For instance:
|
/// For instance:
|
||||||
|
@ -928,18 +930,18 @@ impl SourceMap {
|
||||||
///
|
///
|
||||||
/// Attention: The method used is very fragile since it essentially duplicates the work of the
|
/// Attention: The method used is very fragile since it essentially duplicates the work of the
|
||||||
/// parser. If you need to use this function or something similar, please consider updating the
|
/// parser. If you need to use this function or something similar, please consider updating the
|
||||||
/// source_map functions and this function to something more robust.
|
/// `SourceMap` functions and this function to something more robust.
|
||||||
pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, String)> {
|
pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, String)> {
|
||||||
// Try to extend the span to the previous "fn" keyword to retrieve the function
|
// Try to extend the span to the previous "fn" keyword to retrieve the function
|
||||||
// signature
|
// signature.
|
||||||
let sugg_span = self.span_extend_to_prev_str(span, "fn", false);
|
let sugg_span = self.span_extend_to_prev_str(span, "fn", false);
|
||||||
if sugg_span != span {
|
if sugg_span != span {
|
||||||
if let Ok(snippet) = self.span_to_snippet(sugg_span) {
|
if let Ok(snippet) = self.span_to_snippet(sugg_span) {
|
||||||
// Consume the function name
|
// Consume the function name.
|
||||||
let mut offset = snippet.find(|c: char| !c.is_alphanumeric() && c != '_')
|
let mut offset = snippet.find(|c: char| !c.is_alphanumeric() && c != '_')
|
||||||
.expect("no label after fn");
|
.expect("no label after fn");
|
||||||
|
|
||||||
// Consume the generics part of the function signature
|
// Consume the generics part of the function signature.
|
||||||
let mut bracket_counter = 0;
|
let mut bracket_counter = 0;
|
||||||
let mut last_char = None;
|
let mut last_char = None;
|
||||||
for c in snippet[offset..].chars() {
|
for c in snippet[offset..].chars() {
|
||||||
|
@ -953,11 +955,11 @@ impl SourceMap {
|
||||||
last_char = Some(c);
|
last_char = Some(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the suggestion span to encompass the function name with its generics
|
// Adjust the suggestion span to encompass the function name with its generics.
|
||||||
let sugg_span = sugg_span.with_hi(BytePos(sugg_span.lo().0 + offset as u32));
|
let sugg_span = sugg_span.with_hi(BytePos(sugg_span.lo().0 + offset as u32));
|
||||||
|
|
||||||
// Prepare the new suggested snippet to append the type parameter that triggered
|
// Prepare the new suggested snippet to append the type parameter that triggered
|
||||||
// the error in the generics of the function signature
|
// the error in the generics of the function signature.
|
||||||
let mut new_snippet = if last_char == Some('>') {
|
let mut new_snippet = if last_char == Some('>') {
|
||||||
format!("{}, ", &snippet[..(offset - '>'.len_utf8())])
|
format!("{}, ", &snippet[..(offset - '>'.len_utf8())])
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,18 +4,24 @@ use rustc_data_structures::sync::Lrc;
|
||||||
|
|
||||||
fn init_source_map() -> SourceMap {
|
fn init_source_map() -> SourceMap {
|
||||||
let sm = SourceMap::new(FilePathMapping::empty());
|
let sm = SourceMap::new(FilePathMapping::empty());
|
||||||
sm.new_source_file(PathBuf::from("blork.rs").into(),
|
sm.new_source_file(
|
||||||
"first line.\nsecond line".to_string());
|
PathBuf::from("blork.rs").into(),
|
||||||
sm.new_source_file(PathBuf::from("empty.rs").into(),
|
"first line.\nsecond line".to_string(),
|
||||||
String::new());
|
);
|
||||||
sm.new_source_file(PathBuf::from("blork2.rs").into(),
|
sm.new_source_file(
|
||||||
"first line.\nsecond line".to_string());
|
PathBuf::from("empty.rs").into(),
|
||||||
|
String::new(),
|
||||||
|
);
|
||||||
|
sm.new_source_file(
|
||||||
|
PathBuf::from("blork2.rs").into(),
|
||||||
|
"first line.\nsecond line".to_string(),
|
||||||
|
);
|
||||||
sm
|
sm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tests `lookup_byte_offset`.
|
||||||
#[test]
|
#[test]
|
||||||
fn t3() {
|
fn t3() {
|
||||||
// Test lookup_byte_offset
|
|
||||||
let sm = init_source_map();
|
let sm = init_source_map();
|
||||||
|
|
||||||
let srcfbp1 = sm.lookup_byte_offset(BytePos(23));
|
let srcfbp1 = sm.lookup_byte_offset(BytePos(23));
|
||||||
|
@ -31,9 +37,9 @@ fn t3() {
|
||||||
assert_eq!(srcfbp2.pos, BytePos(0));
|
assert_eq!(srcfbp2.pos, BytePos(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tests `bytepos_to_file_charpos`.
|
||||||
#[test]
|
#[test]
|
||||||
fn t4() {
|
fn t4() {
|
||||||
// Test bytepos_to_file_charpos
|
|
||||||
let sm = init_source_map();
|
let sm = init_source_map();
|
||||||
|
|
||||||
let cp1 = sm.bytepos_to_file_charpos(BytePos(22));
|
let cp1 = sm.bytepos_to_file_charpos(BytePos(22));
|
||||||
|
@ -43,9 +49,9 @@ fn t4() {
|
||||||
assert_eq!(cp2, CharPos(0));
|
assert_eq!(cp2, CharPos(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tests zero-length `SourceFile`s.
|
||||||
#[test]
|
#[test]
|
||||||
fn t5() {
|
fn t5() {
|
||||||
// Test zero-length source_files.
|
|
||||||
let sm = init_source_map();
|
let sm = init_source_map();
|
||||||
|
|
||||||
let loc1 = sm.lookup_char_pos(BytePos(22));
|
let loc1 = sm.lookup_char_pos(BytePos(22));
|
||||||
|
@ -61,7 +67,7 @@ fn t5() {
|
||||||
|
|
||||||
fn init_source_map_mbc() -> SourceMap {
|
fn init_source_map_mbc() -> SourceMap {
|
||||||
let sm = SourceMap::new(FilePathMapping::empty());
|
let sm = SourceMap::new(FilePathMapping::empty());
|
||||||
// € is a three byte utf8 char.
|
// "€" is a three-byte UTF8 char.
|
||||||
sm.new_source_file(PathBuf::from("blork.rs").into(),
|
sm.new_source_file(PathBuf::from("blork.rs").into(),
|
||||||
"fir€st €€€€ line.\nsecond line".to_string());
|
"fir€st €€€€ line.\nsecond line".to_string());
|
||||||
sm.new_source_file(PathBuf::from("blork2.rs").into(),
|
sm.new_source_file(PathBuf::from("blork2.rs").into(),
|
||||||
|
@ -69,9 +75,9 @@ fn init_source_map_mbc() -> SourceMap {
|
||||||
sm
|
sm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tests `bytepos_to_file_charpos` in the presence of multi-byte chars.
|
||||||
#[test]
|
#[test]
|
||||||
fn t6() {
|
fn t6() {
|
||||||
// Test bytepos_to_file_charpos in the presence of multi-byte chars
|
|
||||||
let sm = init_source_map_mbc();
|
let sm = init_source_map_mbc();
|
||||||
|
|
||||||
let cp1 = sm.bytepos_to_file_charpos(BytePos(3));
|
let cp1 = sm.bytepos_to_file_charpos(BytePos(3));
|
||||||
|
@ -87,11 +93,11 @@ fn t6() {
|
||||||
assert_eq!(cp4, CharPos(15));
|
assert_eq!(cp4, CharPos(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test `span_to_lines` for a span ending at the end of a `SourceFile`.
|
||||||
#[test]
|
#[test]
|
||||||
fn t7() {
|
fn t7() {
|
||||||
// Test span_to_lines for a span ending at the end of source_file
|
|
||||||
let sm = init_source_map();
|
let sm = init_source_map();
|
||||||
let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
|
let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION);
|
||||||
let file_lines = sm.span_to_lines(span).unwrap();
|
let file_lines = sm.span_to_lines(span).unwrap();
|
||||||
|
|
||||||
assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into());
|
assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into());
|
||||||
|
@ -107,10 +113,10 @@ fn span_from_selection(input: &str, selection: &str) -> Span {
|
||||||
assert_eq!(input.len(), selection.len());
|
assert_eq!(input.len(), selection.len());
|
||||||
let left_index = selection.find('~').unwrap() as u32;
|
let left_index = selection.find('~').unwrap() as u32;
|
||||||
let right_index = selection.rfind('~').map(|x|x as u32).unwrap_or(left_index);
|
let right_index = selection.rfind('~').map(|x|x as u32).unwrap_or(left_index);
|
||||||
Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1))
|
Span::new(BytePos(left_index), BytePos(right_index + 1), NO_EXPANSION)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests span_to_snippet and span_to_lines for a span converting 3
|
/// Tests `span_to_snippet` and `span_to_lines` for a span converting 3
|
||||||
/// lines in the middle of a file.
|
/// lines in the middle of a file.
|
||||||
#[test]
|
#[test]
|
||||||
fn span_to_snippet_and_lines_spanning_multiple_lines() {
|
fn span_to_snippet_and_lines_spanning_multiple_lines() {
|
||||||
|
@ -120,10 +126,10 @@ fn span_to_snippet_and_lines_spanning_multiple_lines() {
|
||||||
sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string());
|
sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string());
|
||||||
let span = span_from_selection(inputtext, selection);
|
let span = span_from_selection(inputtext, selection);
|
||||||
|
|
||||||
// check that we are extracting the text we thought we were extracting
|
// Check that we are extracting the text we thought we were extracting.
|
||||||
assert_eq!(&sm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD");
|
assert_eq!(&sm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD");
|
||||||
|
|
||||||
// check that span_to_lines gives us the complete result with the lines/cols we expected
|
// Check that span_to_lines gives us the complete result with the lines/cols we expected.
|
||||||
let lines = sm.span_to_lines(span).unwrap();
|
let lines = sm.span_to_lines(span).unwrap();
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) },
|
LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) },
|
||||||
|
@ -133,27 +139,27 @@ fn span_to_snippet_and_lines_spanning_multiple_lines() {
|
||||||
assert_eq!(lines.lines, expected);
|
assert_eq!(lines.lines, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test span_to_snippet for a span ending at the end of a `SourceFile`.
|
||||||
#[test]
|
#[test]
|
||||||
fn t8() {
|
fn t8() {
|
||||||
// Test span_to_snippet for a span ending at the end of source_file
|
|
||||||
let sm = init_source_map();
|
let sm = init_source_map();
|
||||||
let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
|
let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION);
|
||||||
let snippet = sm.span_to_snippet(span);
|
let snippet = sm.span_to_snippet(span);
|
||||||
|
|
||||||
assert_eq!(snippet, Ok("second line".to_string()));
|
assert_eq!(snippet, Ok("second line".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test `span_to_str` for a span ending at the end of a `SourceFile`.
|
||||||
#[test]
|
#[test]
|
||||||
fn t9() {
|
fn t9() {
|
||||||
// Test span_to_str for a span ending at the end of source_file
|
|
||||||
let sm = init_source_map();
|
let sm = init_source_map();
|
||||||
let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
|
let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION);
|
||||||
let sstr = sm.span_to_string(span);
|
let sstr = sm.span_to_string(span);
|
||||||
|
|
||||||
assert_eq!(sstr, "blork.rs:2:1: 2:12");
|
assert_eq!(sstr, "blork.rs:2:1: 2:12");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests failing to merge two spans on different lines
|
/// Tests failing to merge two spans on different lines.
|
||||||
#[test]
|
#[test]
|
||||||
fn span_merging_fail() {
|
fn span_merging_fail() {
|
||||||
let sm = SourceMap::new(FilePathMapping::empty());
|
let sm = SourceMap::new(FilePathMapping::empty());
|
||||||
|
@ -167,43 +173,47 @@ fn span_merging_fail() {
|
||||||
assert!(sm.merge_spans(span1, span2).is_none());
|
assert!(sm.merge_spans(span1, span2).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the span corresponding to the `n`th occurrence of
|
/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`.
|
||||||
/// `substring` in `source_text`.
|
|
||||||
trait SourceMapExtension {
|
trait SourceMapExtension {
|
||||||
fn span_substr(&self,
|
fn span_substr(
|
||||||
file: &Lrc<SourceFile>,
|
self,
|
||||||
source_text: &str,
|
file: &Lrc<SourceFile>,
|
||||||
substring: &str,
|
source_text: &str,
|
||||||
n: usize)
|
substring: &str,
|
||||||
-> Span;
|
n: usize,
|
||||||
|
) -> Span;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceMapExtension for SourceMap {
|
impl SourceMapExtension for SourceMap {
|
||||||
fn span_substr(&self,
|
fn span_substr(
|
||||||
file: &Lrc<SourceFile>,
|
&self,
|
||||||
source_text: &str,
|
file: &Lrc<SourceFile>,
|
||||||
substring: &str,
|
source_text: &str,
|
||||||
n: usize)
|
substring: &str,
|
||||||
-> Span
|
n: usize,
|
||||||
{
|
) -> Span {
|
||||||
println!("span_substr(file={:?}/{:?}, substring={:?}, n={})",
|
println!(
|
||||||
file.name, file.start_pos, substring, n);
|
"span_substr(file={:?}/{:?}, substring={:?}, n={})",
|
||||||
|
file.name, file.start_pos, substring, n
|
||||||
|
);
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut hi = 0;
|
let mut hi = 0;
|
||||||
loop {
|
loop {
|
||||||
let offset = source_text[hi..].find(substring).unwrap_or_else(|| {
|
let offset = source_text[hi..].find(substring).unwrap_or_else(|| {
|
||||||
panic!("source_text `{}` does not have {} occurrences of `{}`, only {}",
|
panic!(
|
||||||
source_text, n, substring, i);
|
"source_text `{}` does not have {} occurrences of `{}`, only {}",
|
||||||
|
source_text, n, substring, i
|
||||||
|
);
|
||||||
});
|
});
|
||||||
let lo = hi + offset;
|
let lo = hi + offset;
|
||||||
hi = lo + substring.len();
|
hi = lo + substring.len();
|
||||||
if i == n {
|
if i == n {
|
||||||
let span = Span::with_root_ctxt(
|
let span = Span::new(
|
||||||
BytePos(lo as u32 + file.start_pos.0),
|
BytePos(lo as u32 + file.start_pos.0),
|
||||||
BytePos(hi as u32 + file.start_pos.0),
|
BytePos(hi as u32 + file.start_pos.0),
|
||||||
|
NO_EXPANSION,
|
||||||
);
|
);
|
||||||
assert_eq!(&self.span_to_snippet(span).unwrap()[..],
|
assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring);
|
||||||
substring);
|
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
|
@ -18,7 +18,7 @@ use std::path::{Path, PathBuf};
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
/// Map string to parser (via tts)
|
/// Map string to parser (via tts).
|
||||||
fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
|
fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
|
||||||
new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
|
new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ crate fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F)
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map a string to tts, using a made-up filename:
|
/// Maps a string to tts, using a made-up filename.
|
||||||
crate fn string_to_stream(source_str: String) -> TokenStream {
|
crate fn string_to_stream(source_str: String) -> TokenStream {
|
||||||
let ps = ParseSess::new(FilePathMapping::empty());
|
let ps = ParseSess::new(FilePathMapping::empty());
|
||||||
source_file_to_stream(
|
source_file_to_stream(
|
||||||
|
@ -42,7 +42,7 @@ crate fn string_to_stream(source_str: String) -> TokenStream {
|
||||||
), None).0
|
), None).0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string, return a crate.
|
/// Parses a string, returns a crate.
|
||||||
crate fn string_to_crate(source_str : String) -> ast::Crate {
|
crate fn string_to_crate(source_str : String) -> ast::Crate {
|
||||||
let ps = ParseSess::new(FilePathMapping::empty());
|
let ps = ParseSess::new(FilePathMapping::empty());
|
||||||
with_error_checking_parse(source_str, &ps, |p| {
|
with_error_checking_parse(source_str, &ps, |p| {
|
||||||
|
@ -64,7 +64,7 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool {
|
||||||
(None, _) => return false,
|
(None, _) => return false,
|
||||||
(Some(&a), None) => {
|
(Some(&a), None) => {
|
||||||
if rustc_lexer::is_whitespace(a) {
|
if rustc_lexer::is_whitespace(a) {
|
||||||
break // trailing whitespace check is out of loop for borrowck
|
break // Trailing whitespace check is out of loop for borrowck.
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,11 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool {
|
||||||
};
|
};
|
||||||
|
|
||||||
if rustc_lexer::is_whitespace(a) && rustc_lexer::is_whitespace(b) {
|
if rustc_lexer::is_whitespace(a) && rustc_lexer::is_whitespace(b) {
|
||||||
// skip whitespace for a and b
|
// Skip whitespace for `a` and `b`.
|
||||||
scan_for_non_ws_or_end(&mut a_iter);
|
scan_for_non_ws_or_end(&mut a_iter);
|
||||||
scan_for_non_ws_or_end(&mut b_iter);
|
scan_for_non_ws_or_end(&mut b_iter);
|
||||||
} else if rustc_lexer::is_whitespace(a) {
|
} else if rustc_lexer::is_whitespace(a) {
|
||||||
// skip whitespace for a
|
// Skip whitespace for `a`.
|
||||||
scan_for_non_ws_or_end(&mut a_iter);
|
scan_for_non_ws_or_end(&mut a_iter);
|
||||||
} else if a == b {
|
} else if a == b {
|
||||||
a_iter.next();
|
a_iter.next();
|
||||||
|
@ -87,18 +87,18 @@ crate fn matches_codepattern(a : &str, b : &str) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a has *only* trailing whitespace
|
// Check if a has *only* trailing whitespace.
|
||||||
a_iter.all(rustc_lexer::is_whitespace)
|
a_iter.all(rustc_lexer::is_whitespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advances the given peekable `Iterator` until it reaches a non-whitespace character
|
/// Advances the given peekable `Iterator` until it reaches a non-whitespace character.
|
||||||
fn scan_for_non_ws_or_end<I: Iterator<Item = char>>(iter: &mut Peekable<I>) {
|
fn scan_for_non_ws_or_end<I: Iterator<Item = char>>(iter: &mut Peekable<I>) {
|
||||||
while iter.peek().copied().map(|c| rustc_lexer::is_whitespace(c)) == Some(true) {
|
while iter.peek().copied().map(|c| rustc_lexer::is_whitespace(c)) == Some(true) {
|
||||||
iter.next();
|
iter.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identify a position in the text by the Nth occurrence of a string.
|
/// Identifies a position in the text by the n'th occurrence of a string.
|
||||||
struct Position {
|
struct Position {
|
||||||
string: &'static str,
|
string: &'static str,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
//!
|
//!
|
||||||
//! ## Ownership
|
//! ## Ownership
|
||||||
//!
|
//!
|
||||||
//! `TokenStreams` are persistent data structures constructed as ropes with reference
|
//! `TokenStream`s are persistent data structures constructed as ropes with reference
|
||||||
//! counted-children. In general, this means that calling an operation on a `TokenStream`
|
//! counted-children. In general, this means that calling an operation on a `TokenStream`
|
||||||
//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
|
//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
|
||||||
//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts,
|
//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts,
|
||||||
|
@ -147,9 +147,8 @@ impl TokenTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Token Streams
|
|
||||||
///
|
|
||||||
/// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s.
|
/// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s.
|
||||||
|
///
|
||||||
/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
|
/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
|
||||||
/// instead of a representation of the abstract syntax tree.
|
/// instead of a representation of the abstract syntax tree.
|
||||||
/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
|
/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
|
||||||
|
@ -304,7 +303,7 @@ impl TokenStream {
|
||||||
Cursor::new(self)
|
Cursor::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compares two TokenStreams, checking equality without regarding span information.
|
/// Compares two `TokenStream`s, checking equality without regarding span information.
|
||||||
pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
|
pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
|
||||||
let mut t1 = self.trees();
|
let mut t1 = self.trees();
|
||||||
let mut t2 = other.trees();
|
let mut t2 = other.trees();
|
||||||
|
|
|
@ -21,13 +21,13 @@ use syntax_pos::Span;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum FnKind<'a> {
|
pub enum FnKind<'a> {
|
||||||
/// fn foo() or extern "Abi" fn foo()
|
/// E.g., `fn foo()` or `extern "Abi" fn foo()`.
|
||||||
ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
|
ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
|
||||||
|
|
||||||
/// fn foo(&self)
|
/// E.g., `fn foo(&self)`.
|
||||||
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
|
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
|
||||||
|
|
||||||
/// |x, y| body
|
/// E.g., `|x, y| body`.
|
||||||
Closure(&'a Expr),
|
Closure(&'a Expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ impl<'a> FnKind<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Each method of the Visitor trait is a hook to be potentially
|
/// Each method of the `Visitor` trait is a hook to be potentially
|
||||||
/// overridden. Each method's default implementation recursively visits
|
/// overridden. Each method's default implementation recursively visits
|
||||||
/// the substructure of the input via the corresponding `walk` method;
|
/// 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`.
|
||||||
|
@ -302,10 +302,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
||||||
walk_list!(visitor, visit_attribute, &item.attrs);
|
walk_list!(visitor, visit_attribute, &item.attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V,
|
pub fn walk_enum_def<'a, V: Visitor<'a>>(
|
||||||
enum_definition: &'a EnumDef,
|
visitor: &mut V,
|
||||||
_: &'a Generics,
|
enum_definition: &'a EnumDef,
|
||||||
_: NodeId) {
|
_: &'a Generics,
|
||||||
|
_: NodeId,
|
||||||
|
) {
|
||||||
walk_list!(visitor, visit_variant, &enum_definition.variants);
|
walk_list!(visitor, visit_variant, &enum_definition.variants);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +344,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
||||||
walk_list!(visitor, visit_lifetime, opt_lifetime);
|
walk_list!(visitor, visit_lifetime, opt_lifetime);
|
||||||
visitor.visit_ty(&mutable_type.ty)
|
visitor.visit_ty(&mutable_type.ty)
|
||||||
}
|
}
|
||||||
TyKind::Never | TyKind::CVarArgs => {}
|
TyKind::Never => {}
|
||||||
TyKind::Tup(ref tuple_element_types) => {
|
TyKind::Tup(ref tuple_element_types) => {
|
||||||
walk_list!(visitor, visit_ty, tuple_element_types);
|
walk_list!(visitor, visit_ty, tuple_element_types);
|
||||||
}
|
}
|
||||||
|
@ -371,6 +373,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
||||||
TyKind::Mac(ref mac) => {
|
TyKind::Mac(ref mac) => {
|
||||||
visitor.visit_mac(mac)
|
visitor.visit_mac(mac)
|
||||||
}
|
}
|
||||||
|
TyKind::CVarArgs => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +389,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
|
||||||
visitor.visit_path(&use_tree.prefix, id);
|
visitor.visit_path(&use_tree.prefix, id);
|
||||||
match use_tree.kind {
|
match use_tree.kind {
|
||||||
UseTreeKind::Simple(rename, ..) => {
|
UseTreeKind::Simple(rename, ..) => {
|
||||||
// the extra IDs are handled during HIR lowering
|
// The extra IDs are handled during HIR lowering.
|
||||||
if let Some(rename) = rename {
|
if let Some(rename) = rename {
|
||||||
visitor.visit_ident(rename);
|
visitor.visit_ident(rename);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue