diff options
| author | Eduard Burtescu <edy.burt@gmail.com> | 2016-03-29 08:50:44 +0300 |
|---|---|---|
| committer | Eduard Burtescu <edy.burt@gmail.com> | 2016-04-06 09:01:55 +0300 |
| commit | 8b0937293bdb70ab4a5efed02b90a71af2b234f6 (patch) | |
| tree | 7db24b3a02e775cdce37e5373e2e08d56b23aaa5 /src/librustc_front | |
| parent | 772c600d4d6f39daa6d07d1a60ee0df3d3426978 (diff) | |
| download | rust-8b0937293bdb70ab4a5efed02b90a71af2b234f6.tar.gz rust-8b0937293bdb70ab4a5efed02b90a71af2b234f6.zip | |
rustc: move rustc_front to rustc::hir.
Diffstat (limited to 'src/librustc_front')
| -rw-r--r-- | src/librustc_front/Cargo.toml | 15 | ||||
| -rw-r--r-- | src/librustc_front/fold.rs | 1151 | ||||
| -rw-r--r-- | src/librustc_front/hir.rs | 1458 | ||||
| -rw-r--r-- | src/librustc_front/intravisit.rs | 837 | ||||
| -rw-r--r-- | src/librustc_front/lib.rs | 58 | ||||
| -rw-r--r-- | src/librustc_front/lowering.rs | 2149 | ||||
| -rw-r--r-- | src/librustc_front/print/pprust.rs | 2413 | ||||
| -rw-r--r-- | src/librustc_front/util.rs | 362 |
8 files changed, 0 insertions, 8443 deletions
diff --git a/src/librustc_front/Cargo.toml b/src/librustc_front/Cargo.toml deleted file mode 100644 index bf40cdbd330..00000000000 --- a/src/librustc_front/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "rustc_front" -version = "0.0.0" - -[lib] -name = "rustc_front" -path = "lib.rs" -crate-type = ["dylib"] - -[dependencies] -log = { path = "../liblog" } -syntax = { path = "../libsyntax" } -serialize = { path = "../libserialize" } -rustc_bitflags = { path = "../librustc_bitflags" } diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs deleted file mode 100644 index e65f2fc37de..00000000000 --- a/src/librustc_front/fold.rs +++ /dev/null @@ -1,1151 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A Folder represents an HIR->HIR fold; it accepts a HIR piece, -//! and returns a piece of the same type. - -use hir::*; -use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem}; -use syntax::ast::MetaItemKind; -use syntax::attr::ThinAttributesExt; -use hir; -use syntax::codemap::{respan, Span, Spanned}; -use syntax::ptr::P; -use syntax::parse::token; -use syntax::util::move_map::MoveMap; - -pub trait Folder : Sized { - // Any additions to this trait should happen in form - // of a call to a public `noop_*` function that only calls - // out to the folder again, not other `noop_*` functions. - // - // This is a necessary API workaround to the problem of not - // being able to call out to the super default method - // in an overridden default method. - - fn fold_crate(&mut self, c: Crate) -> Crate { - noop_fold_crate(c, self) - } - - fn fold_meta_items(&mut self, meta_items: HirVec<P<MetaItem>>) -> HirVec<P<MetaItem>> { - noop_fold_meta_items(meta_items, self) - } - - fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> { - noop_fold_meta_item(meta_item, self) - } - - fn fold_view_path(&mut self, view_path: P<ViewPath>) -> P<ViewPath> { - noop_fold_view_path(view_path, self) - } - - fn fold_foreign_item(&mut self, ni: ForeignItem) -> ForeignItem { - noop_fold_foreign_item(ni, self) - } - - fn fold_item(&mut self, i: Item) -> Item { - noop_fold_item(i, self) - } - - fn fold_item_id(&mut self, i: ItemId) -> ItemId { - noop_fold_item_id(i, self) - } - - fn fold_struct_field(&mut self, sf: StructField) -> StructField { - noop_fold_struct_field(sf, self) - } - - fn fold_item_underscore(&mut self, i: Item_) -> Item_ { - noop_fold_item_underscore(i, self) - } - - fn fold_trait_item(&mut self, i: TraitItem) -> TraitItem { - noop_fold_trait_item(i, self) - } - - fn fold_impl_item(&mut self, i: ImplItem) -> ImplItem { - noop_fold_impl_item(i, self) - } - - fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> { - noop_fold_fn_decl(d, self) - } - - fn fold_block(&mut self, b: P<Block>) -> P<Block> { - noop_fold_block(b, self) - } - - fn fold_stmt(&mut self, s: Stmt) -> Stmt { - noop_fold_stmt(s, self) - } - - fn fold_arm(&mut self, a: Arm) -> Arm { - noop_fold_arm(a, self) - } - - fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> { - noop_fold_pat(p, self) - } - - fn fold_decl(&mut self, d: P<Decl>) -> P<Decl> { - noop_fold_decl(d, self) - } - - fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> { - e.map(|e| noop_fold_expr(e, self)) - } - - fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> { - noop_fold_ty(t, self) - } - - fn fold_ty_binding(&mut self, t: TypeBinding) -> TypeBinding { - noop_fold_ty_binding(t, self) - } - - fn fold_mod(&mut self, m: Mod) -> Mod { - noop_fold_mod(m, self) - } - - fn fold_foreign_mod(&mut self, nm: ForeignMod) -> ForeignMod { - noop_fold_foreign_mod(nm, self) - } - - fn fold_variant(&mut self, v: Variant) -> Variant { - noop_fold_variant(v, self) - } - - fn fold_name(&mut self, n: Name) -> Name { - noop_fold_name(n, self) - } - - fn fold_ident(&mut self, i: Ident) -> Ident { - noop_fold_ident(i, self) - } - - fn fold_usize(&mut self, i: usize) -> usize { - noop_fold_usize(i, self) - } - - fn fold_path(&mut self, p: Path) -> Path { - noop_fold_path(p, self) - } - - fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters { - noop_fold_path_parameters(p, self) - } - - fn fold_angle_bracketed_parameter_data(&mut self, - p: AngleBracketedParameterData) - -> AngleBracketedParameterData { - noop_fold_angle_bracketed_parameter_data(p, self) - } - - fn fold_parenthesized_parameter_data(&mut self, - p: ParenthesizedParameterData) - -> ParenthesizedParameterData { - noop_fold_parenthesized_parameter_data(p, self) - } - - fn fold_local(&mut self, l: P<Local>) -> P<Local> { - noop_fold_local(l, self) - } - - fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf { - noop_fold_explicit_self(es, self) - } - - fn fold_explicit_self_underscore(&mut self, es: ExplicitSelf_) -> ExplicitSelf_ { - noop_fold_explicit_self_underscore(es, self) - } - - fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime { - noop_fold_lifetime(l, self) - } - - fn fold_lifetime_def(&mut self, l: LifetimeDef) -> LifetimeDef { - noop_fold_lifetime_def(l, self) - } - - fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> { - noop_fold_attribute(at, self) - } - - fn fold_arg(&mut self, a: Arg) -> Arg { - noop_fold_arg(a, self) - } - - fn fold_generics(&mut self, generics: Generics) -> Generics { - noop_fold_generics(generics, self) - } - - fn fold_trait_ref(&mut self, p: TraitRef) -> TraitRef { - noop_fold_trait_ref(p, self) - } - - fn fold_poly_trait_ref(&mut self, p: PolyTraitRef) -> PolyTraitRef { - noop_fold_poly_trait_ref(p, self) - } - - fn fold_variant_data(&mut self, vdata: VariantData) -> VariantData { - noop_fold_variant_data(vdata, self) - } - - fn fold_lifetimes(&mut self, lts: HirVec<Lifetime>) -> HirVec<Lifetime> { - noop_fold_lifetimes(lts, self) - } - - fn fold_lifetime_defs(&mut self, lts: HirVec<LifetimeDef>) -> HirVec<LifetimeDef> { - noop_fold_lifetime_defs(lts, self) - } - - fn fold_ty_param(&mut self, tp: TyParam) -> TyParam { - noop_fold_ty_param(tp, self) - } - - fn fold_ty_params(&mut self, tps: HirVec<TyParam>) -> HirVec<TyParam> { - noop_fold_ty_params(tps, self) - } - - fn fold_opt_lifetime(&mut self, o_lt: Option<Lifetime>) -> Option<Lifetime> { - noop_fold_opt_lifetime(o_lt, self) - } - - fn fold_opt_bounds(&mut self, - b: Option<TyParamBounds>) - -> Option<TyParamBounds> { - noop_fold_opt_bounds(b, self) - } - - fn fold_bounds(&mut self, b: TyParamBounds) -> TyParamBounds { - noop_fold_bounds(b, self) - } - - fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound { - noop_fold_ty_param_bound(tpb, self) - } - - fn fold_mt(&mut self, mt: MutTy) -> MutTy { - noop_fold_mt(mt, self) - } - - fn fold_field(&mut self, field: Field) -> Field { - noop_fold_field(field, self) - } - - fn fold_where_clause(&mut self, where_clause: WhereClause) -> WhereClause { - noop_fold_where_clause(where_clause, self) - } - - fn fold_where_predicate(&mut self, where_predicate: WherePredicate) -> WherePredicate { - noop_fold_where_predicate(where_predicate, self) - } - - /// called for the `id` on each declaration - fn new_id(&mut self, i: NodeId) -> NodeId { - i - } - - /// called for ids that are references (e.g., ItemDef) - fn map_id(&mut self, i: NodeId) -> NodeId { - i - } - - fn new_span(&mut self, sp: Span) -> Span { - sp - } -} - -pub fn noop_fold_meta_items<T: Folder>(meta_items: HirVec<P<MetaItem>>, - fld: &mut T) - -> HirVec<P<MetaItem>> { - meta_items.move_map(|x| fld.fold_meta_item(x)) -} - -pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> { - view_path.map(|Spanned { node, span }| { - Spanned { - node: match node { - ViewPathSimple(name, path) => { - ViewPathSimple(name, fld.fold_path(path)) - } - ViewPathGlob(path) => { - ViewPathGlob(fld.fold_path(path)) - } - ViewPathList(path, path_list_idents) => { - ViewPathList(fld.fold_path(path), - path_list_idents.move_map(|path_list_ident| { - Spanned { - node: match path_list_ident.node { - PathListIdent { id, name, rename } => PathListIdent { - id: fld.new_id(id), - name: name, - rename: rename, - }, - PathListMod { id, rename } => PathListMod { - id: fld.new_id(id), - rename: rename, - }, - }, - span: fld.new_span(path_list_ident.span), - } - })) - } - }, - span: fld.new_span(span), - } - }) -} - -pub fn fold_attrs<T: Folder>(attrs: HirVec<Attribute>, fld: &mut T) -> HirVec<Attribute> { - attrs.move_flat_map(|x| fld.fold_attribute(x)) -} - -pub fn noop_fold_arm<T: Folder>(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm { - Arm { - attrs: fold_attrs(attrs, fld), - pats: pats.move_map(|x| fld.fold_pat(x)), - guard: guard.map(|x| fld.fold_expr(x)), - body: fld.fold_expr(body), - } -} - -pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> P<Decl> { - d.map(|Spanned { node, span }| { - match node { - DeclLocal(l) => Spanned { - node: DeclLocal(fld.fold_local(l)), - span: fld.new_span(span), - }, - DeclItem(it) => Spanned { - node: DeclItem(fld.fold_item_id(it)), - span: fld.new_span(span), - }, - } - }) -} - -pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding { - TypeBinding { - id: fld.new_id(b.id), - name: b.name, - ty: fld.fold_ty(b.ty), - span: fld.new_span(b.span), - } -} - -pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { - t.map(|Ty { id, node, span }| { - Ty { - id: fld.new_id(id), - node: match node { - TyInfer => node, - TyVec(ty) => TyVec(fld.fold_ty(ty)), - TyPtr(mt) => TyPtr(fld.fold_mt(mt)), - TyRptr(region, mt) => { - TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt)) - } - TyBareFn(f) => { - TyBareFn(f.map(|BareFnTy { lifetimes, unsafety, abi, decl }| { - BareFnTy { - lifetimes: fld.fold_lifetime_defs(lifetimes), - unsafety: unsafety, - abi: abi, - decl: fld.fold_fn_decl(decl), - } - })) - } - TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), - TyPath(qself, path) => { - let qself = qself.map(|QSelf { ty, position }| { - QSelf { - ty: fld.fold_ty(ty), - position: position, - } - }); - TyPath(qself, fld.fold_path(path)) - } - TyObjectSum(ty, bounds) => { - TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds)) - } - TyFixedLengthVec(ty, e) => { - TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e)) - } - TyTypeof(expr) => { - TyTypeof(fld.fold_expr(expr)) - } - TyPolyTraitRef(bounds) => { - TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b))) - } - }, - span: fld.new_span(span), - } - }) -} - -pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod { abi, items }: ForeignMod, - fld: &mut T) - -> ForeignMod { - ForeignMod { - abi: abi, - items: items.move_map(|x| fld.fold_foreign_item(x)), - } -} - -pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant { - Spanned { - node: Variant_ { - name: v.node.name, - attrs: fold_attrs(v.node.attrs, fld), - data: fld.fold_variant_data(v.node.data), - disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)), - }, - span: fld.new_span(v.span), - } -} - -pub fn noop_fold_name<T: Folder>(n: Name, _: &mut T) -> Name { - n -} - -pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident { - i -} - -pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize { - i -} - -pub fn noop_fold_path<T: Folder>(Path { global, segments, span }: Path, fld: &mut T) -> Path { - Path { - global: global, - segments: segments.move_map(|PathSegment { identifier, parameters }| { - PathSegment { - identifier: fld.fold_ident(identifier), - parameters: fld.fold_path_parameters(parameters), - } - }), - span: fld.new_span(span), - } -} - -pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, - fld: &mut T) - -> PathParameters { - match path_parameters { - AngleBracketedParameters(data) => - AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)), - ParenthesizedParameters(data) => - ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)), - } -} - -pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData, - fld: &mut T) - -> AngleBracketedParameterData { - let AngleBracketedParameterData { lifetimes, types, bindings } = data; - AngleBracketedParameterData { - lifetimes: fld.fold_lifetimes(lifetimes), - types: types.move_map(|ty| fld.fold_ty(ty)), - bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), - } -} - -pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData, - fld: &mut T) - -> ParenthesizedParameterData { - let ParenthesizedParameterData { inputs, output, span } = data; - ParenthesizedParameterData { - inputs: inputs.move_map(|ty| fld.fold_ty(ty)), - output: output.map(|ty| fld.fold_ty(ty)), - span: fld.new_span(span), - } -} - -pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> { - l.map(|Local { id, pat, ty, init, span, attrs }| { - Local { - id: fld.new_id(id), - ty: ty.map(|t| fld.fold_ty(t)), - pat: fld.fold_pat(pat), - init: init.map(|e| fld.fold_expr(e)), - span: fld.new_span(span), - attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs.into(), fld).into()), - } - }) -} - -pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> { - let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at; - Some(Spanned { - node: Attribute_ { - id: id, - style: style, - value: fld.fold_meta_item(value), - is_sugared_doc: is_sugared_doc, - }, - span: fld.new_span(span), - }) -} - -pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_, - fld: &mut T) - -> ExplicitSelf_ { - match es { - SelfStatic | SelfValue(_) => es, - SelfRegion(lifetime, m, name) => { - SelfRegion(fld.fold_opt_lifetime(lifetime), m, name) - } - SelfExplicit(typ, name) => { - SelfExplicit(fld.fold_ty(typ), name) - } - } -} - -pub fn noop_fold_explicit_self<T: Folder>(Spanned { span, node }: ExplicitSelf, - fld: &mut T) - -> ExplicitSelf { - Spanned { - node: fld.fold_explicit_self_underscore(node), - span: fld.new_span(span), - } -} - -pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> { - mi.map(|Spanned { node, span }| { - Spanned { - node: match node { - MetaItemKind::Word(id) => MetaItemKind::Word(id), - MetaItemKind::List(id, mis) => { - MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_item(e))) - } - MetaItemKind::NameValue(id, s) => MetaItemKind::NameValue(id, s), - }, - span: fld.new_span(span), - } - }) -} - -pub fn noop_fold_arg<T: Folder>(Arg { id, pat, ty }: Arg, fld: &mut T) -> Arg { - Arg { - id: fld.new_id(id), - pat: fld.fold_pat(pat), - ty: fld.fold_ty(ty), - } -} - -pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> { - decl.map(|FnDecl { inputs, output, variadic }| { - FnDecl { - inputs: inputs.move_map(|x| fld.fold_arg(x)), - output: match output { - Return(ty) => Return(fld.fold_ty(ty)), - DefaultReturn(span) => DefaultReturn(span), - NoReturn(span) => NoReturn(span), - }, - variadic: variadic, - } - }) -} - -pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T) -> TyParamBound - where T: Folder -{ - match tpb { - TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier), - RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)), - } -} - -pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam { - let TyParam {id, name, bounds, default, span} = tp; - TyParam { - id: fld.new_id(id), - name: name, - bounds: fld.fold_bounds(bounds), - default: default.map(|x| fld.fold_ty(x)), - span: span, - } -} - -pub fn noop_fold_ty_params<T: Folder>(tps: HirVec<TyParam>, - fld: &mut T) - -> HirVec<TyParam> { - tps.move_map(|tp| fld.fold_ty_param(tp)) -} - -pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime { - Lifetime { - id: fld.new_id(l.id), - name: l.name, - span: fld.new_span(l.span), - } -} - -pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T) -> LifetimeDef { - LifetimeDef { - lifetime: fld.fold_lifetime(l.lifetime), - bounds: fld.fold_lifetimes(l.bounds), - } -} - -pub fn noop_fold_lifetimes<T: Folder>(lts: HirVec<Lifetime>, fld: &mut T) -> HirVec<Lifetime> { - lts.move_map(|l| fld.fold_lifetime(l)) -} - -pub fn noop_fold_lifetime_defs<T: Folder>(lts: HirVec<LifetimeDef>, - fld: &mut T) - -> HirVec<LifetimeDef> { - lts.move_map(|l| fld.fold_lifetime_def(l)) -} - -pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T) -> Option<Lifetime> { - o_lt.map(|lt| fld.fold_lifetime(lt)) -} - -pub fn noop_fold_generics<T: Folder>(Generics { ty_params, lifetimes, where_clause }: Generics, - fld: &mut T) - -> Generics { - Generics { - ty_params: fld.fold_ty_params(ty_params), - lifetimes: fld.fold_lifetime_defs(lifetimes), - where_clause: fld.fold_where_clause(where_clause), - } -} - -pub fn noop_fold_where_clause<T: Folder>(WhereClause { id, predicates }: WhereClause, - fld: &mut T) - -> WhereClause { - WhereClause { - id: fld.new_id(id), - predicates: predicates.move_map(|predicate| fld.fold_where_predicate(predicate)), - } -} - -pub fn noop_fold_where_predicate<T: Folder>(pred: WherePredicate, fld: &mut T) -> WherePredicate { - match pred { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{bound_lifetimes, - bounded_ty, - bounds, - span}) => { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes), - bounded_ty: fld.fold_ty(bounded_ty), - bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), - span: fld.new_span(span), - }) - } - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{lifetime, - bounds, - span}) => { - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - span: fld.new_span(span), - lifetime: fld.fold_lifetime(lifetime), - bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)), - }) - } - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id, - path, - ty, - span}) => { - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - id: fld.new_id(id), - path: fld.fold_path(path), - ty: fld.fold_ty(ty), - span: fld.new_span(span), - }) - } - } -} - -pub fn noop_fold_variant_data<T: Folder>(vdata: VariantData, fld: &mut T) -> VariantData { - match vdata { - VariantData::Struct(fields, id) => { - VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)), - fld.new_id(id)) - } - VariantData::Tuple(fields, id) => { - VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)), - fld.new_id(id)) - } - VariantData::Unit(id) => VariantData::Unit(fld.new_id(id)), - } -} - -pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef { - let id = fld.new_id(p.ref_id); - let TraitRef { - path, - ref_id: _, - } = p; - hir::TraitRef { - path: fld.fold_path(path), - ref_id: id, - } -} - -pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef { - hir::PolyTraitRef { - bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes), - trait_ref: fld.fold_trait_ref(p.trait_ref), - span: fld.new_span(p.span), - } -} - -pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructField { - StructField { - span: fld.new_span(f.span), - id: fld.new_id(f.id), - name: f.name, - vis: f.vis, - ty: fld.fold_ty(f.ty), - attrs: fold_attrs(f.attrs, fld), - } -} - -pub fn noop_fold_field<T: Folder>(Field { name, expr, span }: Field, folder: &mut T) -> Field { - Field { - name: respan(folder.new_span(name.span), folder.fold_name(name.node)), - expr: folder.fold_expr(expr), - span: folder.new_span(span), - } -} - -pub fn noop_fold_mt<T: Folder>(MutTy { ty, mutbl }: MutTy, folder: &mut T) -> MutTy { - MutTy { - ty: folder.fold_ty(ty), - mutbl: mutbl, - } -} - -pub fn noop_fold_opt_bounds<T: Folder>(b: Option<TyParamBounds>, - folder: &mut T) - -> Option<TyParamBounds> { - b.map(|bounds| folder.fold_bounds(bounds)) -} - -fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T) -> TyParamBounds { - bounds.move_map(|bound| folder.fold_ty_param_bound(bound)) -} - -pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> { - b.map(|Block { id, stmts, expr, rules, span }| { - Block { - id: folder.new_id(id), - stmts: stmts.move_map(|s| folder.fold_stmt(s)), - expr: expr.map(|x| folder.fold_expr(x)), - rules: rules, - span: folder.new_span(span), - } - }) -} - -pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ { - match i { - ItemExternCrate(string) => ItemExternCrate(string), - ItemUse(view_path) => { - ItemUse(folder.fold_view_path(view_path)) - } - ItemStatic(t, m, e) => { - ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e)) - } - ItemConst(t, e) => { - ItemConst(folder.fold_ty(t), folder.fold_expr(e)) - } - ItemFn(decl, unsafety, constness, abi, generics, body) => { - ItemFn(folder.fold_fn_decl(decl), - unsafety, - constness, - abi, - folder.fold_generics(generics), - folder.fold_block(body)) - } - ItemMod(m) => ItemMod(folder.fold_mod(m)), - ItemForeignMod(nm) => ItemForeignMod(folder.fold_foreign_mod(nm)), - ItemTy(t, generics) => { - ItemTy(folder.fold_ty(t), folder.fold_generics(generics)) - } - ItemEnum(enum_definition, generics) => { - ItemEnum(hir::EnumDef { - variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)), - }, - folder.fold_generics(generics)) - } - ItemStruct(struct_def, generics) => { - let struct_def = folder.fold_variant_data(struct_def); - ItemStruct(struct_def, folder.fold_generics(generics)) - } - ItemDefaultImpl(unsafety, ref trait_ref) => { - ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone())) - } - ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => { - let new_impl_items = impl_items - .move_map(|item| folder.fold_impl_item(item)); - let ifce = match ifce { - None => None, - Some(ref trait_ref) => { - Some(folder.fold_trait_ref((*trait_ref).clone())) - } - }; - ItemImpl(unsafety, - polarity, - folder.fold_generics(generics), - ifce, - folder.fold_ty(ty), - new_impl_items) - } - ItemTrait(unsafety, generics, bounds, items) => { - let bounds = folder.fold_bounds(bounds); - let items = items.move_map(|item| folder.fold_trait_item(item)); - ItemTrait(unsafety, folder.fold_generics(generics), bounds, items) - } - } -} - -pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, - folder: &mut T) - -> TraitItem { - TraitItem { - id: folder.new_id(i.id), - name: folder.fold_name(i.name), - attrs: fold_attrs(i.attrs, folder), - node: match i.node { - ConstTraitItem(ty, default) => { - ConstTraitItem(folder.fold_ty(ty), default.map(|x| folder.fold_expr(x))) - } - MethodTraitItem(sig, body) => { - MethodTraitItem(noop_fold_method_sig(sig, folder), - body.map(|x| folder.fold_block(x))) - } - TypeTraitItem(bounds, default) => { - TypeTraitItem(folder.fold_bounds(bounds), - default.map(|x| folder.fold_ty(x))) - } - }, - span: folder.new_span(i.span), - } -} - -pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T) -> ImplItem { - ImplItem { - id: folder.new_id(i.id), - name: folder.fold_name(i.name), - attrs: fold_attrs(i.attrs, folder), - vis: i.vis, - defaultness: i.defaultness, - node: match i.node { - ImplItemKind::Const(ty, expr) => { - ImplItemKind::Const(folder.fold_ty(ty), folder.fold_expr(expr)) - } - ImplItemKind::Method(sig, body) => { - ImplItemKind::Method(noop_fold_method_sig(sig, folder), folder.fold_block(body)) - } - ImplItemKind::Type(ty) => ImplItemKind::Type(folder.fold_ty(ty)), - }, - span: folder.new_span(i.span), - } -} - -pub fn noop_fold_mod<T: Folder>(Mod { inner, item_ids }: Mod, folder: &mut T) -> Mod { - Mod { - inner: folder.new_span(inner), - item_ids: item_ids.move_map(|x| folder.fold_item_id(x)), - } -} - -pub fn noop_fold_crate<T: Folder>(Crate { module, attrs, config, span, - exported_macros, items }: Crate, - folder: &mut T) - -> Crate { - let config = folder.fold_meta_items(config); - - let crate_mod = folder.fold_item(hir::Item { - name: token::special_idents::invalid.name, - attrs: attrs, - id: DUMMY_NODE_ID, - vis: hir::Public, - span: span, - node: hir::ItemMod(module), - }); - - let (module, attrs, span) = match crate_mod { - hir::Item { attrs, span, node, .. } => { - match node { - hir::ItemMod(m) => (m, attrs, span), - _ => panic!("fold converted a module to not a module"), - } - } - }; - - let items = items.into_iter() - .map(|(id, item)| (id, folder.fold_item(item))) - .collect(); - - Crate { - module: module, - attrs: attrs, - config: config, - span: span, - exported_macros: exported_macros, - items: items, - } -} - -pub fn noop_fold_item_id<T: Folder>(i: ItemId, folder: &mut T) -> ItemId { - let id = folder.map_id(i.id); - ItemId { id: id } -} - -// fold one item into one item -pub fn noop_fold_item<T: Folder>(item: Item, folder: &mut T) -> Item { - let Item { id, name, attrs, node, vis, span } = item; - let id = folder.new_id(id); - let node = folder.fold_item_underscore(node); - // FIXME: we should update the impl_pretty_name, but it uses pretty printing. - // let ident = match node { - // // The node may have changed, recompute the "pretty" impl name. - // ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => { - // impl_pretty_name(maybe_trait, Some(&**ty)) - // } - // _ => ident - // }; - - Item { - id: id, - name: folder.fold_name(name), - attrs: fold_attrs(attrs, folder), - node: node, - vis: vis, - span: folder.new_span(span), - } -} - -pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem { - ForeignItem { - id: folder.new_id(ni.id), - name: folder.fold_name(ni.name), - attrs: fold_attrs(ni.attrs, folder), - node: match ni.node { - ForeignItemFn(fdec, generics) => { - ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics)) - } - ForeignItemStatic(t, m) => { - ForeignItemStatic(folder.fold_ty(t), m) - } - }, - vis: ni.vis, - span: folder.new_span(ni.span), - } -} - -pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig { - MethodSig { - generics: folder.fold_generics(sig.generics), - abi: sig.abi, - explicit_self: folder.fold_explicit_self(sig.explicit_self), - unsafety: sig.unsafety, - constness: sig.constness, - decl: folder.fold_fn_decl(sig.decl), - } -} - -pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> { - p.map(|Pat { id, node, span }| { - Pat { - id: folder.new_id(id), - node: match node { - PatKind::Wild => PatKind::Wild, - PatKind::Ident(binding_mode, pth1, sub) => { - PatKind::Ident(binding_mode, - Spanned { - span: folder.new_span(pth1.span), - node: folder.fold_ident(pth1.node), - }, - sub.map(|x| folder.fold_pat(x))) - } - PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)), - PatKind::TupleStruct(pth, pats) => { - PatKind::TupleStruct(folder.fold_path(pth), - pats.map(|pats| pats.move_map(|x| folder.fold_pat(x)))) - } - PatKind::Path(pth) => { - PatKind::Path(folder.fold_path(pth)) - } - PatKind::QPath(qself, pth) => { - let qself = QSelf { ty: folder.fold_ty(qself.ty), ..qself }; - PatKind::QPath(qself, folder.fold_path(pth)) - } - PatKind::Struct(pth, fields, etc) => { - let pth = folder.fold_path(pth); - let fs = fields.move_map(|f| { - Spanned { - span: folder.new_span(f.span), - node: hir::FieldPat { - name: f.node.name, - pat: folder.fold_pat(f.node.pat), - is_shorthand: f.node.is_shorthand, - }, - } - }); - PatKind::Struct(pth, fs, etc) - } - PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))), - PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)), - PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl), - PatKind::Range(e1, e2) => { - PatKind::Range(folder.fold_expr(e1), folder.fold_expr(e2)) - } - PatKind::Vec(before, slice, after) => { - PatKind::Vec(before.move_map(|x| folder.fold_pat(x)), - slice.map(|x| folder.fold_pat(x)), - after.move_map(|x| folder.fold_pat(x))) - } - }, - span: folder.new_span(span), - } - }) -} - -pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &mut T) -> Expr { - Expr { - id: folder.new_id(id), - node: match node { - ExprBox(e) => { - ExprBox(folder.fold_expr(e)) - } - ExprVec(exprs) => { - ExprVec(exprs.move_map(|x| folder.fold_expr(x))) - } - ExprRepeat(expr, count) => { - ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count)) - } - ExprTup(elts) => ExprTup(elts.move_map(|x| folder.fold_expr(x))), - ExprCall(f, args) => { - ExprCall(folder.fold_expr(f), args.move_map(|x| folder.fold_expr(x))) - } - ExprMethodCall(name, tps, args) => { - ExprMethodCall(respan(folder.new_span(name.span), folder.fold_name(name.node)), - tps.move_map(|x| folder.fold_ty(x)), - args.move_map(|x| folder.fold_expr(x))) - } - ExprBinary(binop, lhs, rhs) => { - ExprBinary(binop, folder.fold_expr(lhs), folder.fold_expr(rhs)) - } - ExprUnary(binop, ohs) => { - ExprUnary(binop, folder.fold_expr(ohs)) - } - ExprLit(l) => ExprLit(l), - ExprCast(expr, ty) => { - ExprCast(folder.fold_expr(expr), folder.fold_ty(ty)) - } - ExprType(expr, ty) => { - ExprType(folder.fold_expr(expr), folder.fold_ty(ty)) - } - ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)), - ExprIf(cond, tr, fl) => { - ExprIf(folder.fold_expr(cond), - folder.fold_block(tr), - fl.map(|x| folder.fold_expr(x))) - } - ExprWhile(cond, body, opt_ident) => { - ExprWhile(folder.fold_expr(cond), - folder.fold_block(body), - opt_ident.map(|i| folder.fold_ident(i))) - } - ExprLoop(body, opt_ident) => { - ExprLoop(folder.fold_block(body), - opt_ident.map(|i| folder.fold_ident(i))) - } - ExprMatch(expr, arms, source) => { - ExprMatch(folder.fold_expr(expr), - arms.move_map(|x| folder.fold_arm(x)), - source) - } - ExprClosure(capture_clause, decl, body) => { - ExprClosure(capture_clause, - folder.fold_fn_decl(decl), - folder.fold_block(body)) - } - ExprBlock(blk) => ExprBlock(folder.fold_block(blk)), - ExprAssign(el, er) => { - ExprAssign(folder.fold_expr(el), folder.fold_expr(er)) - } - ExprAssignOp(op, el, er) => { - ExprAssignOp(op, folder.fold_expr(el), folder.fold_expr(er)) - } - ExprField(el, name) => { - ExprField(folder.fold_expr(el), - respan(folder.new_span(name.span), folder.fold_name(name.node))) - } - ExprTupField(el, index) => { - ExprTupField(folder.fold_expr(el), - respan(folder.new_span(index.span), folder.fold_usize(index.node))) - } - ExprIndex(el, er) => { - ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) - } - ExprPath(qself, path) => { - let qself = qself.map(|QSelf { ty, position }| { - QSelf { - ty: folder.fold_ty(ty), - position: position, - } - }); - ExprPath(qself, folder.fold_path(path)) - } - ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|label| { - respan(folder.new_span(label.span), folder.fold_ident(label.node)) - })), - ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|label| { - respan(folder.new_span(label.span), folder.fold_ident(label.node)) - })), - ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), - ExprInlineAsm(asm, outputs, inputs) => { - ExprInlineAsm(asm, - outputs.move_map(|x| folder.fold_expr(x)), - inputs.move_map(|x| folder.fold_expr(x))) - } - ExprStruct(path, fields, maybe_expr) => { - ExprStruct(folder.fold_path(path), - fields.move_map(|x| folder.fold_field(x)), - maybe_expr.map(|x| folder.fold_expr(x))) - } - }, - span: folder.new_span(span), - attrs: attrs.map_thin_attrs(|attrs| fold_attrs(attrs.into(), folder).into()), - } -} - -pub fn noop_fold_stmt<T: Folder>(stmt: Stmt, folder: &mut T) -> Stmt { - let span = folder.new_span(stmt.span); - match stmt.node { - StmtDecl(d, id) => { - let id = folder.new_id(id); - Spanned { - node: StmtDecl(folder.fold_decl(d), id), - span: span - } - } - StmtExpr(e, id) => { - let id = folder.new_id(id); - Spanned { - node: StmtExpr(folder.fold_expr(e), id), - span: span, - } - } - StmtSemi(e, id) => { - let id = folder.new_id(id); - Spanned { - node: StmtSemi(folder.fold_expr(e), id), - span: span, - } - } - } -} diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs deleted file mode 100644 index 86f8635f58d..00000000000 --- a/src/librustc_front/hir.rs +++ /dev/null @@ -1,1458 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// The Rust HIR. - -pub use self::BindingMode::*; -pub use self::BinOp_::*; -pub use self::BlockCheckMode::*; -pub use self::CaptureClause::*; -pub use self::Decl_::*; -pub use self::ExplicitSelf_::*; -pub use self::Expr_::*; -pub use self::FunctionRetTy::*; -pub use self::ForeignItem_::*; -pub use self::Item_::*; -pub use self::Mutability::*; -pub use self::PathListItem_::*; -pub use self::PrimTy::*; -pub use self::Stmt_::*; -pub use self::TraitItem_::*; -pub use self::Ty_::*; -pub use self::TyParamBound::*; -pub use self::UnOp::*; -pub use self::UnsafeSource::*; -pub use self::ViewPath_::*; -pub use self::Visibility::*; -pub use self::PathParameters::*; - -use intravisit::Visitor; -use std::collections::BTreeMap; -use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId}; -use syntax::abi::Abi; -use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect}; -use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; -use syntax::attr::{ThinAttributes, ThinAttributesExt}; -use syntax::parse::token::InternedString; -use syntax::ptr::P; - -use print::pprust; -use util; - -use std::fmt; -use std::hash::{Hash, Hasher}; -use serialize::{Encodable, Decodable, Encoder, Decoder}; - -/// HIR doesn't commit to a concrete storage type and have its own alias for a vector. -/// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar -/// behavior. Unlike AST, HIR is mostly a static structure, so we can use an owned slice instead -/// of `Vec` to avoid keeping extra capacity. -pub type HirVec<T> = P<[T]>; - -macro_rules! hir_vec { - ($elem:expr; $n:expr) => ( - $crate::hir::HirVec::from(vec![$elem; $n]) - ); - ($($x:expr),*) => ( - $crate::hir::HirVec::from(vec![$($x),*]) - ); - ($($x:expr,)*) => (vec![$($x),*]) -} - -/// Identifier in HIR -#[derive(Clone, Copy, Eq)] -pub struct Ident { - /// Hygienic name (renamed), should be used by default - pub name: Name, - /// Unhygienic name (original, not renamed), needed in few places in name resolution - pub unhygienic_name: Name, -} - -impl Ident { - /// Creates a HIR identifier with both `name` and `unhygienic_name` initialized with - /// the argument. Hygiene properties of the created identifier depend entirely on this - /// argument. If the argument is a plain interned string `intern("iter")`, then the result - /// is unhygienic and can interfere with other entities named "iter". If the argument is - /// a "fresh" name created with `gensym("iter")`, then the result is hygienic and can't - /// interfere with other entities having the same string as a name. - pub fn from_name(name: Name) -> Ident { - Ident { name: name, unhygienic_name: name } - } -} - -impl PartialEq for Ident { - fn eq(&self, other: &Ident) -> bool { - self.name == other.name - } -} - -impl Hash for Ident { - fn hash<H: Hasher>(&self, state: &mut H) { - self.name.hash(state) - } -} - -impl fmt::Debug for Ident { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.name, f) - } -} - -impl fmt::Display for Ident { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.name, f) - } -} - -impl Encodable for Ident { - fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { - self.name.encode(s) - } -} - -impl Decodable for Ident { - fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> { - Ok(Ident::from_name(Name::decode(d)?)) - } -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] -pub struct Lifetime { - pub id: NodeId, - pub span: Span, - pub name: Name, -} - -impl fmt::Debug for Lifetime { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "lifetime({}: {})", - self.id, - pprust::lifetime_to_string(self)) - } -} - -/// A lifetime definition, eg `'a: 'b+'c+'d` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct LifetimeDef { - pub lifetime: Lifetime, - pub bounds: HirVec<Lifetime>, -} - -/// A "Path" is essentially Rust's notion of a name; for instance: -/// std::cmp::PartialEq . It's represented as a sequence of identifiers, -/// along with a bunch of supporting information. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] -pub struct Path { - pub span: Span, - /// A `::foo` path, is relative to the crate root rather than current - /// module (like paths in an import). - pub global: bool, - /// The segments in the path: the things separated by `::`. - pub segments: HirVec<PathSegment>, -} - -impl fmt::Debug for Path { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "path({})", pprust::path_to_string(self)) - } -} - -impl fmt::Display for Path { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", pprust::path_to_string(self)) - } -} - -/// A segment of a path: an identifier, an optional lifetime, and a set of -/// types. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct PathSegment { - /// The identifier portion of this path segment. - /// - /// Hygiene properties of this identifier are worth noting. - /// Most path segments are not hygienic and they are not renamed during - /// lowering from AST to HIR (see comments to `fn lower_path`). However segments from - /// unqualified paths with one segment originating from `ExprPath` (local-variable-like paths) - /// can be hygienic, so they are renamed. You should not normally care about this peculiarity - /// and just use `identifier.name` unless you modify identifier resolution code - /// (`fn resolve_identifier` and other functions called by it in `rustc_resolve`). - pub identifier: Ident, - - /// Type/lifetime parameters attached to this path. They come in - /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that - /// this is more than just simple syntactic sugar; the use of - /// parens affects the region binding rules, so we preserve the - /// distinction. - pub parameters: PathParameters, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum PathParameters { - /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` - AngleBracketedParameters(AngleBracketedParameterData), - /// The `(A,B)` and `C` in `Foo(A,B) -> C` - ParenthesizedParameters(ParenthesizedParameterData), -} - -impl PathParameters { - pub fn none() -> PathParameters { - AngleBracketedParameters(AngleBracketedParameterData { - lifetimes: HirVec::new(), - types: HirVec::new(), - bindings: HirVec::new(), - }) - } - - pub fn is_empty(&self) -> bool { - match *self { - AngleBracketedParameters(ref data) => data.is_empty(), - - // Even if the user supplied no types, something like - // `X()` is equivalent to `X<(),()>`. - ParenthesizedParameters(..) => false, - } - } - - pub fn has_lifetimes(&self) -> bool { - match *self { - AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(), - ParenthesizedParameters(_) => false, - } - } - - pub fn has_types(&self) -> bool { - match *self { - AngleBracketedParameters(ref data) => !data.types.is_empty(), - ParenthesizedParameters(..) => true, - } - } - - /// Returns the types that the user wrote. Note that these do not necessarily map to the type - /// parameters in the parenthesized case. - pub fn types(&self) -> HirVec<&P<Ty>> { - match *self { - AngleBracketedParameters(ref data) => { - data.types.iter().collect() - } - ParenthesizedParameters(ref data) => { - data.inputs - .iter() - .chain(data.output.iter()) - .collect() - } - } - } - - pub fn lifetimes(&self) -> HirVec<&Lifetime> { - match *self { - AngleBracketedParameters(ref data) => { - data.lifetimes.iter().collect() - } - ParenthesizedParameters(_) => { - HirVec::new() - } - } - } - - pub fn bindings(&self) -> HirVec<&TypeBinding> { - match *self { - AngleBracketedParameters(ref data) => { - data.bindings.iter().collect() - } - ParenthesizedParameters(_) => { - HirVec::new() - } - } - } -} - -/// A path like `Foo<'a, T>` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct AngleBracketedParameterData { - /// The lifetime parameters for this path segment. - pub lifetimes: HirVec<Lifetime>, - /// The type parameters for this path segment, if present. - pub types: HirVec<P<Ty>>, - /// Bindings (equality constraints) on associated types, if present. - /// E.g., `Foo<A=Bar>`. - pub bindings: HirVec<TypeBinding>, -} - -impl AngleBracketedParameterData { - fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty() - } -} - -/// A path like `Foo(A,B) -> C` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ParenthesizedParameterData { - /// Overall span - pub span: Span, - - /// `(A,B)` - pub inputs: HirVec<P<Ty>>, - - /// `C` - pub output: Option<P<Ty>>, -} - -/// The AST represents all type param bounds as types. -/// typeck::collect::compute_bounds matches these against -/// the "special" built-in traits (see middle::lang_items) and -/// detects Copy, Send and Sync. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TyParamBound { - TraitTyParamBound(PolyTraitRef, TraitBoundModifier), - RegionTyParamBound(Lifetime), -} - -/// A modifier on a bound, currently this is only used for `?Sized`, where the -/// modifier is `Maybe`. Negative bounds should also be handled here. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitBoundModifier { - None, - Maybe, -} - -pub type TyParamBounds = HirVec<TyParamBound>; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TyParam { - pub name: Name, - pub id: NodeId, - pub bounds: TyParamBounds, - pub default: Option<P<Ty>>, - pub span: Span, -} - -/// Represents lifetimes and type parameters attached to a declaration -/// of a function, enum, trait, etc. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Generics { - pub lifetimes: HirVec<LifetimeDef>, - pub ty_params: HirVec<TyParam>, - pub where_clause: WhereClause, -} - -impl Generics { - pub fn is_lt_parameterized(&self) -> bool { - !self.lifetimes.is_empty() - } - pub fn is_type_parameterized(&self) -> bool { - !self.ty_params.is_empty() - } - pub fn is_parameterized(&self) -> bool { - self.is_lt_parameterized() || self.is_type_parameterized() - } -} - -/// A `where` clause in a definition -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct WhereClause { - pub id: NodeId, - pub predicates: HirVec<WherePredicate>, -} - -/// A single predicate in a `where` clause -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum WherePredicate { - /// A type binding, eg `for<'c> Foo: Send+Clone+'c` - BoundPredicate(WhereBoundPredicate), - /// A lifetime predicate, e.g. `'a: 'b+'c` - RegionPredicate(WhereRegionPredicate), - /// An equality predicate (unsupported) - EqPredicate(WhereEqPredicate), -} - -/// A type bound, eg `for<'c> Foo: Send+Clone+'c` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct WhereBoundPredicate { - pub span: Span, - /// Any lifetimes from a `for` binding - pub bound_lifetimes: HirVec<LifetimeDef>, - /// The type being bounded - pub bounded_ty: P<Ty>, - /// Trait and lifetime bounds (`Clone+Send+'static`) - pub bounds: TyParamBounds, -} - -/// A lifetime predicate, e.g. `'a: 'b+'c` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct WhereRegionPredicate { - pub span: Span, - pub lifetime: Lifetime, - pub bounds: HirVec<Lifetime>, -} - -/// An equality predicate (unsupported), e.g. `T=int` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct WhereEqPredicate { - pub id: NodeId, - pub span: Span, - pub path: Path, - pub ty: P<Ty>, -} - -pub type CrateConfig = HirVec<P<MetaItem>>; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] -pub struct Crate { - pub module: Mod, - pub attrs: HirVec<Attribute>, - pub config: CrateConfig, - pub span: Span, - pub exported_macros: HirVec<MacroDef>, - - // NB: We use a BTreeMap here so that `visit_all_items` iterates - // over the ids in increasing order. In principle it should not - // matter what order we visit things in, but in *practice* it - // does, because it can affect the order in which errors are - // detected, which in turn can make compile-fail tests yield - // slightly different results. - pub items: BTreeMap<NodeId, Item>, -} - -impl Crate { - pub fn item(&self, id: NodeId) -> &Item { - &self.items[&id] - } - - /// Visits all items in the crate in some determinstic (but - /// unspecified) order. If you just need to process every item, - /// but don't care about nesting, this method is the best choice. - /// - /// If you do care about nesting -- usually because your algorithm - /// follows lexical scoping rules -- then you want a different - /// approach. You should override `visit_nested_item` in your - /// visitor and then call `intravisit::walk_crate` instead. - pub fn visit_all_items<'hir, V:Visitor<'hir>>(&'hir self, visitor: &mut V) { - for (_, item) in &self.items { - visitor.visit_item(item); - } - } -} - -/// A macro definition, in this crate or imported from another. -/// -/// Not parsed directly, but created on macro import or `macro_rules!` expansion. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct MacroDef { - pub name: Name, - pub attrs: HirVec<Attribute>, - pub id: NodeId, - pub span: Span, - pub imported_from: Option<Name>, - pub export: bool, - pub use_locally: bool, - pub allow_internal_unstable: bool, - pub body: HirVec<TokenTree>, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Block { - /// Statements in a block - pub stmts: HirVec<Stmt>, - /// An expression at the end of the block - /// without a semicolon, if any - pub expr: Option<P<Expr>>, - pub id: NodeId, - /// Distinguishes between `unsafe { ... }` and `{ ... }` - pub rules: BlockCheckMode, - pub span: Span, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] -pub struct Pat { - pub id: NodeId, - pub node: PatKind, - pub span: Span, -} - -impl fmt::Debug for Pat { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "pat({}: {})", self.id, pprust::pat_to_string(self)) - } -} - -/// A single field in a struct pattern -/// -/// Patterns like the fields of Foo `{ x, ref y, ref mut z }` -/// are treated the same as` x: x, y: ref y, z: ref mut z`, -/// except is_shorthand is true -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct FieldPat { - /// The identifier for the field - pub name: Name, - /// The pattern the field is destructured to - pub pat: P<Pat>, - pub is_shorthand: bool, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum BindingMode { - BindByRef(Mutability), - BindByValue(Mutability), -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum PatKind { - /// Represents a wildcard pattern (`_`) - Wild, - - /// A `PatKind::Ident` may either be a new bound variable, - /// or a unit struct/variant pattern, or a const pattern (in the last two cases - /// the third field must be `None`). - /// - /// In the unit or const pattern case, the parser can't determine - /// which it is. The resolver determines this, and - /// records this pattern's `NodeId` in an auxiliary - /// set (of "PatIdents that refer to unit patterns or constants"). - Ident(BindingMode, Spanned<Ident>, Option<P<Pat>>), - - /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. - /// The `bool` is `true` in the presence of a `..`. - Struct(Path, HirVec<Spanned<FieldPat>>, bool), - - /// A tuple struct/variant pattern `Variant(x, y, z)`. - /// "None" means a `Variant(..)` pattern where we don't bind the fields to names. - TupleStruct(Path, Option<HirVec<P<Pat>>>), - - /// A path pattern. - /// Such pattern can be resolved to a unit struct/variant or a constant. - Path(Path), - - /// An associated const named using the qualified path `<T>::CONST` or - /// `<T as Trait>::CONST`. Associated consts from inherent impls can be - /// referred to as simply `T::CONST`, in which case they will end up as - /// PatKind::Path, and the resolver will have to sort that out. - QPath(QSelf, Path), - - /// A tuple pattern `(a, b)` - Tup(HirVec<P<Pat>>), - /// A `box` pattern - Box(P<Pat>), - /// A reference pattern, e.g. `&mut (a, b)` - Ref(P<Pat>, Mutability), - /// A literal - Lit(P<Expr>), - /// A range pattern, e.g. `1...2` - Range(P<Expr>, P<Expr>), - /// `[a, b, ..i, y, z]` is represented as: - /// `PatKind::Vec(box [a, b], Some(i), box [y, z])` - Vec(HirVec<P<Pat>>, Option<P<Pat>>, HirVec<P<Pat>>), -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum Mutability { - MutMutable, - MutImmutable, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum BinOp_ { - /// The `+` operator (addition) - BiAdd, - /// The `-` operator (subtraction) - BiSub, - /// The `*` operator (multiplication) - BiMul, - /// The `/` operator (division) - BiDiv, - /// The `%` operator (modulus) - BiRem, - /// The `&&` operator (logical and) - BiAnd, - /// The `||` operator (logical or) - BiOr, - /// The `^` operator (bitwise xor) - BiBitXor, - /// The `&` operator (bitwise and) - BiBitAnd, - /// The `|` operator (bitwise or) - BiBitOr, - /// The `<<` operator (shift left) - BiShl, - /// The `>>` operator (shift right) - BiShr, - /// The `==` operator (equality) - BiEq, - /// The `<` operator (less than) - BiLt, - /// The `<=` operator (less than or equal to) - BiLe, - /// The `!=` operator (not equal to) - BiNe, - /// The `>=` operator (greater than or equal to) - BiGe, - /// The `>` operator (greater than) - BiGt, -} - -pub type BinOp = Spanned<BinOp_>; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum UnOp { - /// The `*` operator for dereferencing - UnDeref, - /// The `!` operator for logical inversion - UnNot, - /// The `-` operator for negation - UnNeg, -} - -/// A statement -pub type Stmt = Spanned<Stmt_>; - -impl fmt::Debug for Stmt_ { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // Sadness. - let spanned = codemap::dummy_spanned(self.clone()); - write!(f, - "stmt({}: {})", - util::stmt_id(&spanned), - pprust::stmt_to_string(&spanned)) - } -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] -pub enum Stmt_ { - /// Could be an item or a local (let) binding: - StmtDecl(P<Decl>, NodeId), - - /// Expr without trailing semi-colon (must have unit type): - StmtExpr(P<Expr>, NodeId), - - /// Expr with trailing semi-colon (may have any type): - StmtSemi(P<Expr>, NodeId), -} - -impl Stmt_ { - pub fn attrs(&self) -> &[Attribute] { - match *self { - StmtDecl(ref d, _) => d.node.attrs(), - StmtExpr(ref e, _) | - StmtSemi(ref e, _) => e.attrs.as_attr_slice(), - } - } -} - -// FIXME (pending discussion of #1697, #2178...): local should really be -// a refinement on pat. -/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Local { - pub pat: P<Pat>, - pub ty: Option<P<Ty>>, - /// Initializer expression to set the value, if any - pub init: Option<P<Expr>>, - pub id: NodeId, - pub span: Span, - pub attrs: ThinAttributes, -} - -pub type Decl = Spanned<Decl_>; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Decl_ { - /// A local (let) binding: - DeclLocal(P<Local>), - /// An item binding: - DeclItem(ItemId), -} - -impl Decl_ { - pub fn attrs(&self) -> &[Attribute] { - match *self { - DeclLocal(ref l) => l.attrs.as_attr_slice(), - DeclItem(_) => &[] - } - } -} - -/// represents one arm of a 'match' -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Arm { - pub attrs: HirVec<Attribute>, - pub pats: HirVec<P<Pat>>, - pub guard: Option<P<Expr>>, - pub body: P<Expr>, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Field { - pub name: Spanned<Name>, - pub expr: P<Expr>, - pub span: Span, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum BlockCheckMode { - DefaultBlock, - UnsafeBlock(UnsafeSource), - PushUnsafeBlock(UnsafeSource), - PopUnsafeBlock(UnsafeSource), - // Within this block (but outside a PopUnstableBlock), we suspend checking of stability. - PushUnstableBlock, - PopUnstableBlock, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum UnsafeSource { - CompilerGenerated, - UserProvided, -} - -/// An expression -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] -pub struct Expr { - pub id: NodeId, - pub node: Expr_, - pub span: Span, - pub attrs: ThinAttributes, -} - -impl fmt::Debug for Expr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self)) - } -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Expr_ { - /// A `box x` expression. - ExprBox(P<Expr>), - /// An array (`[a, b, c, d]`) - ExprVec(HirVec<P<Expr>>), - /// A function call - /// - /// The first field resolves to the function itself, - /// and the second field is the list of arguments - ExprCall(P<Expr>, HirVec<P<Expr>>), - /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`) - /// - /// The `Spanned<Name>` is the identifier for the method name. - /// The vector of `Ty`s are the ascripted type parameters for the method - /// (within the angle brackets). - /// - /// The first element of the vector of `Expr`s is the expression that evaluates - /// to the object on which the method is being called on (the receiver), - /// and the remaining elements are the rest of the arguments. - /// - /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as - /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. - ExprMethodCall(Spanned<Name>, HirVec<P<Ty>>, HirVec<P<Expr>>), - /// A tuple (`(a, b, c ,d)`) - ExprTup(HirVec<P<Expr>>), - /// A binary operation (For example: `a + b`, `a * b`) - ExprBinary(BinOp, P<Expr>, P<Expr>), - /// A unary operation (For example: `!x`, `*x`) - ExprUnary(UnOp, P<Expr>), - /// A literal (For example: `1`, `"foo"`) - ExprLit(P<Lit>), - /// A cast (`foo as f64`) - ExprCast(P<Expr>, P<Ty>), - ExprType(P<Expr>, P<Ty>), - /// An `if` block, with an optional else block - /// - /// `if expr { block } else { expr }` - ExprIf(P<Expr>, P<Block>, Option<P<Expr>>), - /// A while loop, with an optional label - /// - /// `'label: while expr { block }` - ExprWhile(P<Expr>, P<Block>, Option<Ident>), - /// Conditionless loop (can be exited with break, continue, or return) - /// - /// `'label: loop { block }` - ExprLoop(P<Block>, Option<Ident>), - /// A `match` block, with a source that indicates whether or not it is - /// the result of a desugaring, and if so, which kind. - ExprMatch(P<Expr>, HirVec<Arm>, MatchSource), - /// A closure (for example, `move |a, b, c| {a + b + c}`) - ExprClosure(CaptureClause, P<FnDecl>, P<Block>), - /// A block (`{ ... }`) - ExprBlock(P<Block>), - - /// An assignment (`a = foo()`) - ExprAssign(P<Expr>, P<Expr>), - /// An assignment with an operator - /// - /// For example, `a += 1`. - ExprAssignOp(BinOp, P<Expr>, P<Expr>), - /// Access of a named struct field (`obj.foo`) - ExprField(P<Expr>, Spanned<Name>), - /// Access of an unnamed field of a struct or tuple-struct - /// - /// For example, `foo.0`. - ExprTupField(P<Expr>, Spanned<usize>), - /// An indexing operation (`foo[2]`) - ExprIndex(P<Expr>, P<Expr>), - - /// Variable reference, possibly containing `::` and/or type - /// parameters, e.g. foo::bar::<baz>. - /// - /// Optionally "qualified", - /// e.g. `<HirVec<T> as SomeTrait>::SomeType`. - ExprPath(Option<QSelf>, Path), - - /// A referencing operation (`&a` or `&mut a`) - ExprAddrOf(Mutability, P<Expr>), - /// A `break`, with an optional label to break - ExprBreak(Option<Spanned<Ident>>), - /// A `continue`, with an optional label - ExprAgain(Option<Spanned<Ident>>), - /// A `return`, with an optional value to be returned - ExprRet(Option<P<Expr>>), - - /// Inline assembly (from `asm!`), with its outputs and inputs. - ExprInlineAsm(InlineAsm, Vec<P<Expr>>, Vec<P<Expr>>), - - /// A struct literal expression. - /// - /// For example, `Foo {x: 1, y: 2}`, or - /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`. - ExprStruct(Path, HirVec<Field>, Option<P<Expr>>), - - /// A vector literal constructed from one repeated element. - /// - /// For example, `[1; 5]`. The first expression is the element - /// to be repeated; the second is the number of times to repeat it. - ExprRepeat(P<Expr>, P<Expr>), -} - -/// The explicit Self type in a "qualified path". The actual -/// path, including the trait and the associated item, is stored -/// separately. `position` represents the index of the associated -/// item qualified with this Self type. -/// -/// <HirVec<T> as a::b::Trait>::AssociatedItem -/// ^~~~~ ~~~~~~~~~~~~~~^ -/// ty position = 3 -/// -/// <HirVec<T>>::AssociatedItem -/// ^~~~~ ^ -/// ty position = 0 -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct QSelf { - pub ty: P<Ty>, - pub position: usize, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum MatchSource { - Normal, - IfLetDesugar { - contains_else_clause: bool, - }, - WhileLetDesugar, - ForLoopDesugar, - TryDesugar, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum CaptureClause { - CaptureByValue, - CaptureByRef, -} - -// NB: If you change this, you'll probably want to change the corresponding -// type structure in middle/ty.rs as well. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct MutTy { - pub ty: P<Ty>, - pub mutbl: Mutability, -} - -/// Represents a method's signature in a trait declaration, -/// or in an implementation. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct MethodSig { - pub unsafety: Unsafety, - pub constness: Constness, - pub abi: Abi, - pub decl: P<FnDecl>, - pub generics: Generics, - pub explicit_self: ExplicitSelf, -} - -/// Represents an item declaration within a trait declaration, -/// possibly including a default implementation. A trait item is -/// either required (meaning it doesn't have an implementation, just a -/// signature) or provided (meaning it has a default implementation). -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TraitItem { - pub id: NodeId, - pub name: Name, - pub attrs: HirVec<Attribute>, - pub node: TraitItem_, - pub span: Span, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitItem_ { - ConstTraitItem(P<Ty>, Option<P<Expr>>), - MethodTraitItem(MethodSig, Option<P<Block>>), - TypeTraitItem(TyParamBounds, Option<P<Ty>>), -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ImplItem { - pub id: NodeId, - pub name: Name, - pub vis: Visibility, - pub defaultness: Defaultness, - pub attrs: HirVec<Attribute>, - pub node: ImplItemKind, - pub span: Span, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ImplItemKind { - Const(P<Ty>, P<Expr>), - Method(MethodSig, P<Block>), - Type(P<Ty>), -} - -// Bind a type to an associated type: `A=Foo`. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TypeBinding { - pub id: NodeId, - pub name: Name, - pub ty: P<Ty>, - pub span: Span, -} - - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] -pub struct Ty { - pub id: NodeId, - pub node: Ty_, - pub span: Span, -} - -impl fmt::Debug for Ty { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "type({})", pprust::ty_to_string(self)) - } -} - -/// Not represented directly in the AST, referred to by name through a ty_path. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum PrimTy { - TyInt(IntTy), - TyUint(UintTy), - TyFloat(FloatTy), - TyStr, - TyBool, - TyChar, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct BareFnTy { - pub unsafety: Unsafety, - pub abi: Abi, - pub lifetimes: HirVec<LifetimeDef>, - pub decl: P<FnDecl>, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -/// The different kinds of types recognized by the compiler -pub enum Ty_ { - TyVec(P<Ty>), - /// A fixed length array (`[T; n]`) - TyFixedLengthVec(P<Ty>, P<Expr>), - /// A raw pointer (`*const T` or `*mut T`) - TyPtr(MutTy), - /// A reference (`&'a T` or `&'a mut T`) - TyRptr(Option<Lifetime>, MutTy), - /// A bare function (e.g. `fn(usize) -> bool`) - TyBareFn(P<BareFnTy>), - /// A tuple (`(A, B, C, D,...)`) - TyTup(HirVec<P<Ty>>), - /// A path (`module::module::...::Type`), optionally - /// "qualified", e.g. `<HirVec<T> as SomeTrait>::SomeType`. - /// - /// Type parameters are stored in the Path itself - TyPath(Option<QSelf>, Path), - /// Something like `A+B`. Note that `B` must always be a path. - TyObjectSum(P<Ty>, TyParamBounds), - /// A type like `for<'a> Foo<&'a Bar>` - TyPolyTraitRef(TyParamBounds), - /// Unused for now - TyTypeof(P<Expr>), - /// TyInfer means the type should be inferred instead of it having been - /// specified. This can appear anywhere in a type. - TyInfer, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct InlineAsmOutput { - pub constraint: InternedString, - pub is_rw: bool, - pub is_indirect: bool, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct InlineAsm { - pub asm: InternedString, - pub asm_str_style: StrStyle, - pub outputs: HirVec<InlineAsmOutput>, - pub inputs: HirVec<InternedString>, - pub clobbers: HirVec<InternedString>, - pub volatile: bool, - pub alignstack: bool, - pub dialect: AsmDialect, - pub expn_id: ExpnId, -} - -/// represents an argument in a function header -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Arg { - pub ty: P<Ty>, - pub pat: P<Pat>, - pub id: NodeId, -} - -impl Arg { - pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg { - let path = Spanned { - span: span, - node: self_ident, - }; - Arg { - // HACK(eddyb) fake type for the self argument. - ty: P(Ty { - id: DUMMY_NODE_ID, - node: TyInfer, - span: DUMMY_SP, - }), - pat: P(Pat { - id: DUMMY_NODE_ID, - node: PatKind::Ident(BindByValue(mutability), path, None), - span: span, - }), - id: DUMMY_NODE_ID, - } - } -} - -/// Represents the header (not the body) of a function declaration -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct FnDecl { - pub inputs: HirVec<Arg>, - pub output: FunctionRetTy, - pub variadic: bool, -} - -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Unsafety { - Unsafe, - Normal, -} - -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Constness { - Const, - NotConst, -} - -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Defaultness { - Default, - Final, -} - -impl Defaultness { - pub fn is_final(&self) -> bool { - *self == Defaultness::Final - } - - pub fn is_default(&self) -> bool { - *self == Defaultness::Default - } -} - -impl fmt::Display for Unsafety { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(match *self { - Unsafety::Normal => "normal", - Unsafety::Unsafe => "unsafe", - }, - f) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] -pub enum ImplPolarity { - /// `impl Trait for Type` - Positive, - /// `impl !Trait for Type` - Negative, -} - -impl fmt::Debug for ImplPolarity { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ImplPolarity::Positive => "positive".fmt(f), - ImplPolarity::Negative => "negative".fmt(f), - } - } -} - - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum FunctionRetTy { - /// Functions with return type `!`that always - /// raise an error or exit (i.e. never return to the caller) - NoReturn(Span), - /// Return type is not specified. - /// - /// Functions default to `()` and - /// closures default to inference. Span points to where return - /// type would be inserted. - DefaultReturn(Span), - /// Everything else - Return(P<Ty>), -} - -impl FunctionRetTy { - pub fn span(&self) -> Span { - match *self { - NoReturn(span) => span, - DefaultReturn(span) => span, - Return(ref ty) => ty.span, - } - } -} - -/// Represents the kind of 'self' associated with a method -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ExplicitSelf_ { - /// No self - SelfStatic, - /// `self` - SelfValue(Name), - /// `&'lt self`, `&'lt mut self` - SelfRegion(Option<Lifetime>, Mutability, Name), - /// `self: TYPE` - SelfExplicit(P<Ty>, Name), -} - -pub type ExplicitSelf = Spanned<ExplicitSelf_>; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Mod { - /// A span from the first token past `{` to the last token until `}`. - /// For `mod foo;`, the inner span ranges from the first token - /// to the last token in the external file. - pub inner: Span, - pub item_ids: HirVec<ItemId>, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ForeignMod { - pub abi: Abi, - pub items: HirVec<ForeignItem>, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct EnumDef { - pub variants: HirVec<Variant>, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Variant_ { - pub name: Name, - pub attrs: HirVec<Attribute>, - pub data: VariantData, - /// Explicit discriminant, eg `Foo = 1` - pub disr_expr: Option<P<Expr>>, -} - -pub type Variant = Spanned<Variant_>; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum PathListItem_ { - PathListIdent { - name: Name, - /// renamed in list, eg `use foo::{bar as baz};` - rename: Option<Name>, - id: NodeId, - }, - PathListMod { - /// renamed in list, eg `use foo::{self as baz};` - rename: Option<Name>, - id: NodeId, - }, -} - -impl PathListItem_ { - pub fn id(&self) -> NodeId { - match *self { - PathListIdent { id, .. } | PathListMod { id, .. } => id, - } - } - - pub fn name(&self) -> Option<Name> { - match *self { - PathListIdent { name, .. } => Some(name), - PathListMod { .. } => None, - } - } - - pub fn rename(&self) -> Option<Name> { - match *self { - PathListIdent { rename, .. } | PathListMod { rename, .. } => rename, - } - } -} - -pub type PathListItem = Spanned<PathListItem_>; - -pub type ViewPath = Spanned<ViewPath_>; - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ViewPath_ { - /// `foo::bar::baz as quux` - /// - /// or just - /// - /// `foo::bar::baz` (with `as baz` implicitly on the right) - ViewPathSimple(Name, Path), - - /// `foo::bar::*` - ViewPathGlob(Path), - - /// `foo::bar::{a,b,c}` - ViewPathList(Path, HirVec<PathListItem>), -} - -/// TraitRef's appear in impls. -/// -/// resolve maps each TraitRef's ref_id to its defining trait; that's all -/// that the ref_id is for. The impl_id maps to the "self type" of this impl. -/// If this impl is an ItemImpl, the impl_id is redundant (it could be the -/// same as the impl's node id). -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TraitRef { - pub path: Path, - pub ref_id: NodeId, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct PolyTraitRef { - /// The `'a` in `<'a> Foo<&'a T>` - pub bound_lifetimes: HirVec<LifetimeDef>, - - /// The `Foo<&'a T>` in `<'a> Foo<&'a T>` - pub trait_ref: TraitRef, - - pub span: Span, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum Visibility { - Public, - Inherited, -} - -impl Visibility { - pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility { - match self { - &Inherited => parent_visibility, - &Public => *self, - } - } -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct StructField { - pub span: Span, - pub name: Name, - pub vis: Visibility, - pub id: NodeId, - pub ty: P<Ty>, - pub attrs: HirVec<Attribute>, -} - -impl StructField { - // Still necessary in couple of places - pub fn is_positional(&self) -> bool { - let first = self.name.as_str().as_bytes()[0]; - first >= b'0' && first <= b'9' - } -} - -/// Fields and Ids of enum variants and structs -/// -/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all -/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants). -/// One shared Id can be successfully used for these two purposes. -/// Id of the whole enum lives in `Item`. -/// -/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually -/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of -/// the variant itself" from enum variants. -/// Id of the whole struct lives in `Item`. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum VariantData { - Struct(HirVec<StructField>, NodeId), - Tuple(HirVec<StructField>, NodeId), - Unit(NodeId), -} - -impl VariantData { - pub fn fields(&self) -> &[StructField] { - match *self { - VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => fields, - _ => &[], - } - } - pub fn id(&self) -> NodeId { - match *self { - VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id, - } - } - pub fn is_struct(&self) -> bool { - if let VariantData::Struct(..) = *self { - true - } else { - false - } - } - pub fn is_tuple(&self) -> bool { - if let VariantData::Tuple(..) = *self { - true - } else { - false - } - } - pub fn is_unit(&self) -> bool { - if let VariantData::Unit(..) = *self { - true - } else { - false - } - } -} - -// The bodies for items are stored "out of line", in a separate -// hashmap in the `Crate`. Here we just record the node-id of the item -// so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ItemId { - pub id: NodeId, -} - -// FIXME (#3300): Should allow items to be anonymous. Right now -// we just use dummy names for anon items. -/// An item -/// -/// The name might be a dummy name in case of anonymous items -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Item { - pub name: Name, - pub attrs: HirVec<Attribute>, - pub id: NodeId, - pub node: Item_, - pub vis: Visibility, - pub span: Span, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Item_ { - /// An`extern crate` item, with optional original crate name, - /// - /// e.g. `extern crate foo` or `extern crate foo_bar as foo` - ItemExternCrate(Option<Name>), - /// A `use` or `pub use` item - ItemUse(P<ViewPath>), - - /// A `static` item - ItemStatic(P<Ty>, Mutability, P<Expr>), - /// A `const` item - ItemConst(P<Ty>, P<Expr>), - /// A function declaration - ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>), - /// A module - ItemMod(Mod), - /// An external module - ItemForeignMod(ForeignMod), - /// A type alias, e.g. `type Foo = Bar<u8>` - ItemTy(P<Ty>, Generics), - /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}` - ItemEnum(EnumDef, Generics), - /// A struct definition, e.g. `struct Foo<A> {x: A}` - ItemStruct(VariantData, Generics), - /// Represents a Trait Declaration - ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItem>), - - // Default trait implementations - /// - /// `impl Trait for .. {}` - ItemDefaultImpl(Unsafety, TraitRef), - /// An implementation, eg `impl<A> Trait for Foo { .. }` - ItemImpl(Unsafety, - ImplPolarity, - Generics, - Option<TraitRef>, // (optional) trait this impl implements - P<Ty>, // self - HirVec<ImplItem>), -} - -impl Item_ { - pub fn descriptive_variant(&self) -> &str { - match *self { - ItemExternCrate(..) => "extern crate", - ItemUse(..) => "use", - ItemStatic(..) => "static item", - ItemConst(..) => "constant item", - ItemFn(..) => "function", - ItemMod(..) => "module", - ItemForeignMod(..) => "foreign module", - ItemTy(..) => "type alias", - ItemEnum(..) => "enum", - ItemStruct(..) => "struct", - ItemTrait(..) => "trait", - ItemImpl(..) | - ItemDefaultImpl(..) => "item", - } - } -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ForeignItem { - pub name: Name, - pub attrs: HirVec<Attribute>, - pub node: ForeignItem_, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, -} - -/// An item within an `extern` block -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ForeignItem_ { - /// A foreign function - ForeignItemFn(P<FnDecl>, Generics), - /// A foreign static item (`static ext: u8`), with optional mutability - /// (the boolean is true when mutable) - ForeignItemStatic(P<Ty>, bool), -} - -impl ForeignItem_ { - pub fn descriptive_variant(&self) -> &str { - match *self { - ForeignItemFn(..) => "foreign function", - ForeignItemStatic(..) => "foreign static item", - } - } -} diff --git a/src/librustc_front/intravisit.rs b/src/librustc_front/intravisit.rs deleted file mode 100644 index be1cc528d88..00000000000 --- a/src/librustc_front/intravisit.rs +++ /dev/null @@ -1,837 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! HIR walker. Each overridden visit method has full control over what -//! happens with its node, it can do its own traversal of the node's children, -//! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent -//! deeper traversal by doing nothing. -//! -//! When visiting the HIR, the contents of nested items are NOT visited -//! by default. This is different from the AST visitor, which does a deep walk. -//! Hence this module is called `intravisit`; see the method `visit_nested_item` -//! for more details. -//! -//! Note: it is an important invariant that the default visitor walks -//! the body of a function in "execution order" (more concretely, -//! reverse post-order with respect to the CFG implied by the AST), -//! meaning that if AST node A may execute before AST node B, then A -//! is visited first. The borrow checker in particular relies on this -//! property. - -use syntax::abi::Abi; -use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute}; -use syntax::attr::ThinAttributesExt; -use syntax::codemap::Span; -use hir::*; - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum FnKind<'a> { - /// fn foo() or extern "Abi" fn foo() - ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, Visibility, &'a [Attribute]), - - /// fn foo(&self) - Method(Name, &'a MethodSig, Option<Visibility>, &'a [Attribute]), - - /// |x, y| {} - Closure(&'a [Attribute]), -} - -impl<'a> FnKind<'a> { - pub fn attrs(&self) -> &'a [Attribute] { - match *self { - FnKind::ItemFn(_, _, _, _, _, _, attrs) => attrs, - FnKind::Method(_, _, _, attrs) => attrs, - FnKind::Closure(attrs) => attrs, - } - } -} - -/// Each method of the Visitor trait is a hook to be potentially -/// overridden. Each method's default implementation recursively visits -/// the substructure of the input via the corresponding `walk` method; -/// e.g. the `visit_mod` method by default calls `intravisit::walk_mod`. -/// -/// Note that this visitor does NOT visit nested items by default -/// (this is why the module is called `intravisit`, to distinguish it -/// from the AST's `visit` module, which acts differently). If you -/// simply want to visit all items in the crate in some order, you -/// should call `Crate::visit_all_items`. Otherwise, see the comment -/// on `visit_nested_item` for details on how to visit nested items. -/// -/// If you want to ensure that your code handles every variant -/// explicitly, you need to override each method. (And you also need -/// to monitor future changes to `Visitor` in case a new method with a -/// new default implementation gets introduced.) -pub trait Visitor<'v> : Sized { - /////////////////////////////////////////////////////////////////////////// - // Nested items. - - /// Invoked when a nested item is encountered. By default, does - /// nothing. If you want a deep walk, you need to override to - /// fetch the item contents. But most of the time, it is easier - /// (and better) to invoke `Crate::visit_all_items`, which visits - /// all items in the crate in some order (but doesn't respect - /// nesting). - #[allow(unused_variables)] - fn visit_nested_item(&mut self, id: ItemId) { - } - - /// Visit the top-level item and (optionally) nested items. See - /// `visit_nested_item` for details. - fn visit_item(&mut self, i: &'v Item) { - walk_item(self, i) - } - - /////////////////////////////////////////////////////////////////////////// - - fn visit_name(&mut self, _span: Span, _name: Name) { - // Nothing to do. - } - fn visit_ident(&mut self, span: Span, ident: Ident) { - walk_ident(self, span, ident); - } - fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { - walk_mod(self, m) - } - fn visit_foreign_item(&mut self, i: &'v ForeignItem) { - walk_foreign_item(self, i) - } - fn visit_local(&mut self, l: &'v Local) { - walk_local(self, l) - } - fn visit_block(&mut self, b: &'v Block) { - walk_block(self, b) - } - fn visit_stmt(&mut self, s: &'v Stmt) { - walk_stmt(self, s) - } - fn visit_arm(&mut self, a: &'v Arm) { - walk_arm(self, a) - } - fn visit_pat(&mut self, p: &'v Pat) { - walk_pat(self, p) - } - fn visit_decl(&mut self, d: &'v Decl) { - walk_decl(self, d) - } - fn visit_expr(&mut self, ex: &'v Expr) { - walk_expr(self, ex) - } - fn visit_expr_post(&mut self, _ex: &'v Expr) { - } - fn visit_ty(&mut self, t: &'v Ty) { - walk_ty(self, t) - } - fn visit_generics(&mut self, g: &'v Generics) { - walk_generics(self, g) - } - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) { - walk_fn(self, fk, fd, b, s) - } - fn visit_trait_item(&mut self, ti: &'v TraitItem) { - walk_trait_item(self, ti) - } - fn visit_impl_item(&mut self, ii: &'v ImplItem) { - walk_impl_item(self, ii) - } - fn visit_trait_ref(&mut self, t: &'v TraitRef) { - walk_trait_ref(self, t) - } - fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { - walk_ty_param_bound(self, bounds) - } - fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) { - walk_poly_trait_ref(self, t, m) - } - fn visit_variant_data(&mut self, - s: &'v VariantData, - _: Name, - _: &'v Generics, - _: NodeId, - _: Span) { - walk_struct_def(self, s) - } - fn visit_struct_field(&mut self, s: &'v StructField) { - walk_struct_field(self, s) - } - fn visit_enum_def(&mut self, - enum_definition: &'v EnumDef, - generics: &'v Generics, - item_id: NodeId, - _: Span) { - walk_enum_def(self, enum_definition, generics, item_id) - } - fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) { - walk_variant(self, v, g, item_id) - } - fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { - walk_lifetime(self, lifetime) - } - fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { - walk_lifetime_def(self, lifetime) - } - fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) { - walk_explicit_self(self, es) - } - fn visit_path(&mut self, path: &'v Path, _id: NodeId) { - walk_path(self, path) - } - fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) { - walk_path_list_item(self, prefix, item) - } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { - walk_path_segment(self, path_span, path_segment) - } - fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) { - walk_path_parameters(self, path_span, path_parameters) - } - fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) { - walk_assoc_type_binding(self, type_binding) - } - fn visit_attribute(&mut self, _attr: &'v Attribute) { - } - fn visit_macro_def(&mut self, macro_def: &'v MacroDef) { - walk_macro_def(self, macro_def) - } -} - -pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) { - for name in opt_name { - visitor.visit_name(span, name); - } -} - -pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) { - for ident in opt_ident { - visitor.visit_ident(span, ident); - } -} - -pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) { - visitor.visit_name(span, ident.name); -} - -/// Walks the contents of a crate. See also `Crate::visit_all_items`. -pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { - visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID); - walk_list!(visitor, visit_attribute, &krate.attrs); - walk_list!(visitor, visit_macro_def, &krate.exported_macros); -} - -pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) { - visitor.visit_name(macro_def.span, macro_def.name); - walk_opt_name(visitor, macro_def.span, macro_def.imported_from); - walk_list!(visitor, visit_attribute, ¯o_def.attrs); -} - -pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) { - for &item_id in &module.item_ids { - visitor.visit_nested_item(item_id); - } -} - -pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { - visitor.visit_pat(&local.pat); - walk_list!(visitor, visit_ty, &local.ty); - walk_list!(visitor, visit_expr, &local.init); -} - -pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { - visitor.visit_name(lifetime.span, lifetime.name); -} - -pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) { - visitor.visit_lifetime(&lifetime_def.lifetime); - walk_list!(visitor, visit_lifetime, &lifetime_def.bounds); -} - -pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, explicit_self: &'v ExplicitSelf) { - match explicit_self.node { - SelfStatic => {} - SelfValue(name) => { - visitor.visit_name(explicit_self.span, name) - } - SelfRegion(ref opt_lifetime, _, name) => { - visitor.visit_name(explicit_self.span, name); - walk_list!(visitor, visit_lifetime, opt_lifetime); - } - SelfExplicit(ref typ, name) => { - visitor.visit_name(explicit_self.span, name); - visitor.visit_ty(typ) - } - } -} - -pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, - trait_ref: &'v PolyTraitRef, - _modifier: &'v TraitBoundModifier) - where V: Visitor<'v> -{ - walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); - visitor.visit_trait_ref(&trait_ref.trait_ref); -} - -pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) - where V: Visitor<'v> -{ - visitor.visit_path(&trait_ref.path, trait_ref.ref_id) -} - -pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { - visitor.visit_name(item.span, item.name); - match item.node { - ItemExternCrate(opt_name) => { - walk_opt_name(visitor, item.span, opt_name) - } - ItemUse(ref vp) => { - match vp.node { - ViewPathSimple(name, ref path) => { - visitor.visit_name(vp.span, name); - visitor.visit_path(path, item.id); - } - ViewPathGlob(ref path) => { - visitor.visit_path(path, item.id); - } - ViewPathList(ref prefix, ref list) => { - if !list.is_empty() { - for item in list { - visitor.visit_path_list_item(prefix, item) - } - } else { - visitor.visit_path(prefix, item.id); - } - } - } - } - ItemStatic(ref typ, _, ref expr) | - ItemConst(ref typ, ref expr) => { - visitor.visit_ty(typ); - visitor.visit_expr(expr); - } - ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => { - visitor.visit_fn(FnKind::ItemFn(item.name, - generics, - unsafety, - constness, - abi, - item.vis, - &item.attrs), - declaration, - body, - item.span, - item.id) - } - ItemMod(ref module) => { - visitor.visit_mod(module, item.span, item.id) - } - ItemForeignMod(ref foreign_module) => { - walk_list!(visitor, visit_foreign_item, &foreign_module.items); - } - ItemTy(ref typ, ref type_parameters) => { - visitor.visit_ty(typ); - visitor.visit_generics(type_parameters) - } - ItemEnum(ref enum_definition, ref type_parameters) => { - visitor.visit_generics(type_parameters); - visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span) - } - ItemDefaultImpl(_, ref trait_ref) => { - visitor.visit_trait_ref(trait_ref) - } - ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => { - visitor.visit_generics(type_parameters); - walk_list!(visitor, visit_trait_ref, opt_trait_reference); - visitor.visit_ty(typ); - walk_list!(visitor, visit_impl_item, impl_items); - } - ItemStruct(ref struct_definition, ref generics) => { - visitor.visit_generics(generics); - visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span); - } - ItemTrait(_, ref generics, ref bounds, ref methods) => { - visitor.visit_generics(generics); - walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_trait_item, methods); - } - } - walk_list!(visitor, visit_attribute, &item.attrs); -} - -pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V, - enum_definition: &'v EnumDef, - generics: &'v Generics, - item_id: NodeId) { - walk_list!(visitor, - visit_variant, - &enum_definition.variants, - generics, - item_id); -} - -pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, - variant: &'v Variant, - generics: &'v Generics, - item_id: NodeId) { - visitor.visit_name(variant.span, variant.node.name); - visitor.visit_variant_data(&variant.node.data, - variant.node.name, - generics, - item_id, - variant.span); - walk_list!(visitor, visit_expr, &variant.node.disr_expr); - walk_list!(visitor, visit_attribute, &variant.node.attrs); -} - -pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { - match typ.node { - TyVec(ref ty) => { - visitor.visit_ty(ty) - } - TyPtr(ref mutable_type) => { - visitor.visit_ty(&mutable_type.ty) - } - TyRptr(ref opt_lifetime, ref mutable_type) => { - walk_list!(visitor, visit_lifetime, opt_lifetime); - visitor.visit_ty(&mutable_type.ty) - } - TyTup(ref tuple_element_types) => { - walk_list!(visitor, visit_ty, tuple_element_types); - } - TyBareFn(ref function_declaration) => { - walk_fn_decl(visitor, &function_declaration.decl); - walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); - } - TyPath(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, typ.id); - } - TyObjectSum(ref ty, ref bounds) => { - visitor.visit_ty(ty); - walk_list!(visitor, visit_ty_param_bound, bounds); - } - TyFixedLengthVec(ref ty, ref expression) => { - visitor.visit_ty(ty); - visitor.visit_expr(expression) - } - TyPolyTraitRef(ref bounds) => { - walk_list!(visitor, visit_ty_param_bound, bounds); - } - TyTypeof(ref expression) => { - visitor.visit_expr(expression) - } - TyInfer => {} - } -} - -pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { - for segment in &path.segments { - visitor.visit_path_segment(path.span, segment); - } -} - -pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, - prefix: &'v Path, - item: &'v PathListItem) { - for segment in &prefix.segments { - visitor.visit_path_segment(prefix.span, segment); - } - - walk_opt_name(visitor, item.span, item.node.name()); - walk_opt_name(visitor, item.span, item.node.rename()); -} - -pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, - path_span: Span, - segment: &'v PathSegment) { - visitor.visit_ident(path_span, segment.identifier); - visitor.visit_path_parameters(path_span, &segment.parameters); -} - -pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, - _path_span: Span, - path_parameters: &'v PathParameters) { - match *path_parameters { - AngleBracketedParameters(ref data) => { - walk_list!(visitor, visit_ty, &data.types); - walk_list!(visitor, visit_lifetime, &data.lifetimes); - walk_list!(visitor, visit_assoc_type_binding, &data.bindings); - } - ParenthesizedParameters(ref data) => { - walk_list!(visitor, visit_ty, &data.inputs); - walk_list!(visitor, visit_ty, &data.output); - } - } -} - -pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, - type_binding: &'v TypeBinding) { - visitor.visit_name(type_binding.span, type_binding.name); - visitor.visit_ty(&type_binding.ty); -} - -pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { - match pattern.node { - PatKind::TupleStruct(ref path, ref opt_children) => { - visitor.visit_path(path, pattern.id); - if let Some(ref children) = *opt_children { - walk_list!(visitor, visit_pat, children); - } - } - PatKind::Path(ref path) => { - visitor.visit_path(path, pattern.id); - } - PatKind::QPath(ref qself, ref path) => { - visitor.visit_ty(&qself.ty); - visitor.visit_path(path, pattern.id) - } - PatKind::Struct(ref path, ref fields, _) => { - visitor.visit_path(path, pattern.id); - for field in fields { - visitor.visit_name(field.span, field.node.name); - visitor.visit_pat(&field.node.pat) - } - } - PatKind::Tup(ref tuple_elements) => { - walk_list!(visitor, visit_pat, tuple_elements); - } - PatKind::Box(ref subpattern) | - PatKind::Ref(ref subpattern, _) => { - visitor.visit_pat(subpattern) - } - PatKind::Ident(_, ref pth1, ref optional_subpattern) => { - visitor.visit_ident(pth1.span, pth1.node); - walk_list!(visitor, visit_pat, optional_subpattern); - } - PatKind::Lit(ref expression) => visitor.visit_expr(expression), - PatKind::Range(ref lower_bound, ref upper_bound) => { - visitor.visit_expr(lower_bound); - visitor.visit_expr(upper_bound) - } - PatKind::Wild => (), - PatKind::Vec(ref prepatterns, ref slice_pattern, ref postpatterns) => { - walk_list!(visitor, visit_pat, prepatterns); - walk_list!(visitor, visit_pat, slice_pattern); - walk_list!(visitor, visit_pat, postpatterns); - } - } -} - -pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) { - visitor.visit_name(foreign_item.span, foreign_item.name); - - match foreign_item.node { - ForeignItemFn(ref function_declaration, ref generics) => { - walk_fn_decl(visitor, function_declaration); - visitor.visit_generics(generics) - } - ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ), - } - - walk_list!(visitor, visit_attribute, &foreign_item.attrs); -} - -pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) { - match *bound { - TraitTyParamBound(ref typ, ref modifier) => { - visitor.visit_poly_trait_ref(typ, modifier); - } - RegionTyParamBound(ref lifetime) => { - visitor.visit_lifetime(lifetime); - } - } -} - -pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { - for param in &generics.ty_params { - visitor.visit_name(param.span, param.name); - walk_list!(visitor, visit_ty_param_bound, ¶m.bounds); - walk_list!(visitor, visit_ty, ¶m.default); - } - walk_list!(visitor, visit_lifetime_def, &generics.lifetimes); - for predicate in &generics.where_clause.predicates { - match predicate { - &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, - ref bounds, - ref bound_lifetimes, - ..}) => { - visitor.visit_ty(bounded_ty); - walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_lifetime_def, bound_lifetimes); - } - &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, - ref bounds, - ..}) => { - visitor.visit_lifetime(lifetime); - walk_list!(visitor, visit_lifetime, bounds); - } - &WherePredicate::EqPredicate(WhereEqPredicate{id, - ref path, - ref ty, - ..}) => { - visitor.visit_path(path, id); - visitor.visit_ty(ty); - } - } - } -} - -pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) { - if let Return(ref output_ty) = *ret_ty { - visitor.visit_ty(output_ty) - } -} - -pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { - for argument in &function_declaration.inputs { - visitor.visit_pat(&argument.pat); - visitor.visit_ty(&argument.ty) - } - walk_fn_ret_ty(visitor, &function_declaration.output) -} - -pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { - for argument in &function_declaration.inputs { - visitor.visit_ty(&argument.ty) - } - walk_fn_ret_ty(visitor, &function_declaration.output) -} - -pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) { - match function_kind { - FnKind::ItemFn(_, generics, _, _, _, _, _) => { - visitor.visit_generics(generics); - } - FnKind::Method(_, sig, _, _) => { - visitor.visit_generics(&sig.generics); - visitor.visit_explicit_self(&sig.explicit_self); - } - FnKind::Closure(_) => {} - } -} - -pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, - function_kind: FnKind<'v>, - function_declaration: &'v FnDecl, - function_body: &'v Block, - _span: Span) { - walk_fn_decl(visitor, function_declaration); - walk_fn_kind(visitor, function_kind); - visitor.visit_block(function_body) -} - -pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { - visitor.visit_name(trait_item.span, trait_item.name); - walk_list!(visitor, visit_attribute, &trait_item.attrs); - match trait_item.node { - ConstTraitItem(ref ty, ref default) => { - visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, default); - } - MethodTraitItem(ref sig, None) => { - visitor.visit_explicit_self(&sig.explicit_self); - visitor.visit_generics(&sig.generics); - walk_fn_decl(visitor, &sig.decl); - } - MethodTraitItem(ref sig, Some(ref body)) => { - visitor.visit_fn(FnKind::Method(trait_item.name, - sig, - None, - &trait_item.attrs), - &sig.decl, - body, - trait_item.span, - trait_item.id); - } - TypeTraitItem(ref bounds, ref default) => { - walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_ty, default); - } - } -} - -pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { - visitor.visit_name(impl_item.span, impl_item.name); - walk_list!(visitor, visit_attribute, &impl_item.attrs); - match impl_item.node { - ImplItemKind::Const(ref ty, ref expr) => { - visitor.visit_ty(ty); - visitor.visit_expr(expr); - } - ImplItemKind::Method(ref sig, ref body) => { - visitor.visit_fn(FnKind::Method(impl_item.name, - sig, - Some(impl_item.vis), - &impl_item.attrs), - &sig.decl, - body, - impl_item.span, - impl_item.id); - } - ImplItemKind::Type(ref ty) => { - visitor.visit_ty(ty); - } - } -} - -pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) { - walk_list!(visitor, visit_struct_field, struct_definition.fields()); -} - -pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) { - visitor.visit_name(struct_field.span, struct_field.name); - visitor.visit_ty(&struct_field.ty); - walk_list!(visitor, visit_attribute, &struct_field.attrs); -} - -pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) { - walk_list!(visitor, visit_stmt, &block.stmts); - walk_list!(visitor, visit_expr, &block.expr); -} - -pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) { - match statement.node { - StmtDecl(ref declaration, _) => visitor.visit_decl(declaration), - StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => { - visitor.visit_expr(expression) - } - } -} - -pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) { - match declaration.node { - DeclLocal(ref local) => visitor.visit_local(local), - DeclItem(item) => visitor.visit_nested_item(item), - } -} - -pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { - match expression.node { - ExprBox(ref subexpression) => { - visitor.visit_expr(subexpression) - } - ExprVec(ref subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprRepeat(ref element, ref count) => { - visitor.visit_expr(element); - visitor.visit_expr(count) - } - ExprStruct(ref path, ref fields, ref optional_base) => { - visitor.visit_path(path, expression.id); - for field in fields { - visitor.visit_name(field.name.span, field.name.node); - visitor.visit_expr(&field.expr) - } - walk_list!(visitor, visit_expr, optional_base); - } - ExprTup(ref subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprCall(ref callee_expression, ref arguments) => { - walk_list!(visitor, visit_expr, arguments); - visitor.visit_expr(callee_expression) - } - ExprMethodCall(ref name, ref types, ref arguments) => { - visitor.visit_name(name.span, name.node); - walk_list!(visitor, visit_expr, arguments); - walk_list!(visitor, visit_ty, types); - } - ExprBinary(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(left_expression); - visitor.visit_expr(right_expression) - } - ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => { - visitor.visit_expr(subexpression) - } - ExprLit(_) => {} - ExprCast(ref subexpression, ref typ) | ExprType(ref subexpression, ref typ) => { - visitor.visit_expr(subexpression); - visitor.visit_ty(typ) - } - ExprIf(ref head_expression, ref if_block, ref optional_else) => { - visitor.visit_expr(head_expression); - visitor.visit_block(if_block); - walk_list!(visitor, visit_expr, optional_else); - } - ExprWhile(ref subexpression, ref block, opt_ident) => { - visitor.visit_expr(subexpression); - visitor.visit_block(block); - walk_opt_ident(visitor, expression.span, opt_ident) - } - ExprLoop(ref block, opt_ident) => { - visitor.visit_block(block); - walk_opt_ident(visitor, expression.span, opt_ident) - } - ExprMatch(ref subexpression, ref arms, _) => { - visitor.visit_expr(subexpression); - walk_list!(visitor, visit_arm, arms); - } - ExprClosure(_, ref function_declaration, ref body) => { - visitor.visit_fn(FnKind::Closure(expression.attrs.as_attr_slice()), - function_declaration, - body, - expression.span, - expression.id) - } - ExprBlock(ref block) => visitor.visit_block(block), - ExprAssign(ref left_hand_expression, ref right_hand_expression) => { - visitor.visit_expr(right_hand_expression); - visitor.visit_expr(left_hand_expression) - } - ExprAssignOp(_, ref left_expression, ref right_expression) => { - visitor.visit_expr(right_expression); - visitor.visit_expr(left_expression) - } - ExprField(ref subexpression, ref name) => { - visitor.visit_expr(subexpression); - visitor.visit_name(name.span, name.node); - } - ExprTupField(ref subexpression, _) => { - visitor.visit_expr(subexpression); - } - ExprIndex(ref main_expression, ref index_expression) => { - visitor.visit_expr(main_expression); - visitor.visit_expr(index_expression) - } - ExprPath(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, expression.id) - } - ExprBreak(ref opt_sp_ident) | ExprAgain(ref opt_sp_ident) => { - for sp_ident in opt_sp_ident { - visitor.visit_ident(sp_ident.span, sp_ident.node); - } - } - ExprRet(ref optional_expression) => { - walk_list!(visitor, visit_expr, optional_expression); - } - ExprInlineAsm(_, ref outputs, ref inputs) => { - for output in outputs { - visitor.visit_expr(output) - } - for input in inputs { - visitor.visit_expr(input) - } - } - } - - visitor.visit_expr_post(expression) -} - -pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { - walk_list!(visitor, visit_pat, &arm.pats); - walk_list!(visitor, visit_expr, &arm.guard); - visitor.visit_expr(&arm.body); - walk_list!(visitor, visit_attribute, &arm.attrs); -} diff --git a/src/librustc_front/lib.rs b/src/librustc_front/lib.rs deleted file mode 100644 index b9e3b71cf1a..00000000000 --- a/src/librustc_front/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The Rust compiler. -//! -//! # Note -//! -//! This API is completely unstable and subject to change. - -#![crate_name = "rustc_front"] -#![unstable(feature = "rustc_private", issue = "27812")] -#![crate_type = "dylib"] -#![crate_type = "rlib"] -#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] - -#![feature(associated_consts)] -#![feature(box_patterns)] -#![feature(box_syntax)] -#![feature(const_fn)] -#![feature(quote)] -#![feature(rustc_diagnostic_macros)] -#![feature(rustc_private)] -#![feature(slice_patterns)] -#![feature(staged_api)] -#![feature(str_char)] -#![feature(question_mark)] - -extern crate serialize; -#[macro_use] -extern crate log; -#[macro_use] -extern crate syntax; -#[macro_use] -#[no_link] -extern crate rustc_bitflags; - -extern crate serialize as rustc_serialize; // used by deriving - -#[macro_use] -pub mod hir; -pub mod lowering; -pub mod fold; -pub mod intravisit; -pub mod util; - -pub mod print { - pub mod pprust; -} diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs deleted file mode 100644 index 66b9e217bd3..00000000000 --- a/src/librustc_front/lowering.rs +++ /dev/null @@ -1,2149 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Lowers the AST to the HIR. -// -// Since the AST and HIR are fairly similar, this is mostly a simple procedure, -// much like a fold. Where lowering involves a bit more work things get more -// interesting and there are some invariants you should know about. These mostly -// concern spans and ids. -// -// Spans are assigned to AST nodes during parsing and then are modified during -// expansion to indicate the origin of a node and the process it went through -// being expanded. Ids are assigned to AST nodes just before lowering. -// -// For the simpler lowering steps, ids and spans should be preserved. Unlike -// expansion we do not preserve the process of lowering in the spans, so spans -// should not be modified here. When creating a new node (as opposed to -// 'folding' an existing one), then you create a new id using `next_id()`. -// -// You must ensure that ids are unique. That means that you should only use the -// id from an AST node in a single HIR node (you can assume that AST node ids -// are unique). Every new node must have a unique id. Avoid cloning HIR nodes. -// If you do, you must then set the new node's id to a fresh one. -// -// Lowering must be reproducable (the compiler only lowers once, but tools and -// custom lints may lower an AST node to a HIR node to interact with the -// compiler). The most interesting bit of this is ids - if you lower an AST node -// and create new HIR nodes with fresh ids, when re-lowering the same node, you -// must ensure you get the same ids! To do this, we keep track of the next id -// when we translate a node which requires new ids. By checking this cache and -// using node ids starting with the cached id, we ensure ids are reproducible. -// To use this system, you just need to hold on to a CachedIdSetter object -// whilst lowering. This is an RAII object that takes care of setting and -// restoring the cached id, etc. -// -// This whole system relies on node ids being incremented one at a time and -// all increments being for lowering. This means that you should not call any -// non-lowering function which will use new node ids. -// -// We must also cache gensym'ed Idents to ensure that we get the same Ident -// every time we lower a node with gensym'ed names. One consequence of this is -// that you can only gensym a name once in a lowering (you don't need to worry -// about nested lowering though). That's because we cache based on the name and -// the currently cached node id, which is unique per lowered node. -// -// Spans are used for error messages and for tools to map semantics back to -// source code. It is therefore not as important with spans as ids to be strict -// about use (you can't break the compiler by screwing up a span). Obviously, a -// HIR node can only have a single span. But multiple nodes can have the same -// span and spans don't need to be kept in order, etc. Where code is preserved -// by lowering, it should have the same span as in the AST. Where HIR nodes are -// new it is probably best to give a span for the whole AST node being lowered. -// All nodes should have real spans, don't use dummy spans. Tools are likely to -// get confused if the spans from leaf AST nodes occur in multiple places -// in the HIR, especially for multiple identifiers. - -use hir; - -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::iter; -use syntax::ast::*; -use syntax::attr::{ThinAttributes, ThinAttributesExt}; -use syntax::errors::Handler; -use syntax::ext::mtwt; -use syntax::ptr::P; -use syntax::codemap::{respan, Spanned, Span}; -use syntax::parse::token; -use syntax::std_inject; -use syntax::visit::{self, Visitor}; - -use std::cell::{Cell, RefCell}; - -pub struct LoweringContext<'a> { - crate_root: Option<&'static str>, - // Map AST ids to ids used for expanded nodes. - id_cache: RefCell<HashMap<NodeId, NodeId>>, - // Use if there are no cached ids for the current node. - id_assigner: &'a NodeIdAssigner, - // 0 == no cached id. Must be incremented to align with previous id - // incrementing. - cached_id: Cell<u32>, - // Keep track of gensym'ed idents. - gensym_cache: RefCell<HashMap<(NodeId, &'static str), hir::Ident>>, - // A copy of cached_id, but is also set to an id while a node is lowered for - // the first time. - gensym_key: Cell<u32>, -} - -impl<'a, 'hir> LoweringContext<'a> { - pub fn new(id_assigner: &'a NodeIdAssigner, c: Option<&Crate>) -> LoweringContext<'a> { - let crate_root = c.and_then(|c| { - if std_inject::no_core(c) { - None - } else if std_inject::no_std(c) { - Some("core") - } else { - Some("std") - } - }); - - LoweringContext { - crate_root: crate_root, - id_cache: RefCell::new(HashMap::new()), - id_assigner: id_assigner, - cached_id: Cell::new(0), - gensym_cache: RefCell::new(HashMap::new()), - gensym_key: Cell::new(0), - } - } - - fn next_id(&self) -> NodeId { - let cached_id = self.cached_id.get(); - if cached_id == 0 { - return self.id_assigner.next_node_id(); - } - - self.cached_id.set(cached_id + 1); - cached_id - } - - fn str_to_ident(&self, s: &'static str) -> hir::Ident { - let gensym_key = self.gensym_key.get(); - if gensym_key == 0 { - return hir::Ident::from_name(token::gensym(s)); - } - - let cached = self.gensym_cache.borrow().contains_key(&(gensym_key, s)); - if cached { - self.gensym_cache.borrow()[&(gensym_key, s)] - } else { - let result = hir::Ident::from_name(token::gensym(s)); - self.gensym_cache.borrow_mut().insert((gensym_key, s), result); - result - } - } - - // Panics if this LoweringContext's NodeIdAssigner is not able to emit diagnostics. - fn diagnostic(&self) -> &Handler { - self.id_assigner.diagnostic() - } -} - -// Utility fn for setting and unsetting the cached id. -fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R - where OP: FnOnce(&LoweringContext) -> R -{ - // Only reset the id if it was previously 0, i.e., was not cached. - // If it was cached, we are in a nested node, but our id count will - // still count towards the parent's count. - let reset_cached_id = lctx.cached_id.get() == 0; - // We always reset gensym_key so that if we use the same name in a nested - // node and after that node, they get different values. - let old_gensym_key = lctx.gensym_key.get(); - - { - let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut(); - - if id_cache.contains_key(&expr_id) { - let cached_id = lctx.cached_id.get(); - if cached_id == 0 { - // We're entering a node where we need to track ids, but are not - // yet tracking. - lctx.cached_id.set(id_cache[&expr_id]); - } else { - // We're already tracking - check that the tracked id is the same - // as the expected id. - assert!(cached_id == id_cache[&expr_id], "id mismatch"); - } - lctx.gensym_key.set(id_cache[&expr_id]); - } else { - // We've never lowered this node before, remember it for next time. - let next_id = lctx.id_assigner.peek_node_id(); - id_cache.insert(expr_id, next_id); - lctx.gensym_key.set(next_id); - // self.cached_id is not set when we lower a node for the first time, - // only on re-lowering. - } - } - - let result = op(lctx); - - if reset_cached_id { - lctx.cached_id.set(0); - } - lctx.gensym_key.set(old_gensym_key); - - result -} - -pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident { - hir::Ident { - name: mtwt::resolve(ident), - unhygienic_name: ident.name, - } -} - -pub fn lower_attrs(_lctx: &LoweringContext, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> { - attrs.clone().into() -} - -pub fn lower_view_path(lctx: &LoweringContext, view_path: &ViewPath) -> P<hir::ViewPath> { - P(Spanned { - node: match view_path.node { - ViewPathSimple(ident, ref path) => { - hir::ViewPathSimple(ident.name, lower_path(lctx, path)) - } - ViewPathGlob(ref path) => { - hir::ViewPathGlob(lower_path(lctx, path)) - } - ViewPathList(ref path, ref path_list_idents) => { - hir::ViewPathList(lower_path(lctx, path), - path_list_idents.iter() - .map(lower_path_list_item) - .collect()) - } - }, - span: view_path.span, - }) -} - -fn lower_path_list_item(path_list_ident: &PathListItem) -> hir::PathListItem { - Spanned { - node: match path_list_ident.node { - PathListItemKind::Ident { id, name, rename } => hir::PathListIdent { - id: id, - name: name.name, - rename: rename.map(|x| x.name), - }, - PathListItemKind::Mod { id, rename } => hir::PathListMod { - id: id, - rename: rename.map(|x| x.name), - }, - }, - span: path_list_ident.span, - } -} - -pub fn lower_arm(lctx: &LoweringContext, arm: &Arm) -> hir::Arm { - hir::Arm { - attrs: lower_attrs(lctx, &arm.attrs), - pats: arm.pats.iter().map(|x| lower_pat(lctx, x)).collect(), - guard: arm.guard.as_ref().map(|ref x| lower_expr(lctx, x)), - body: lower_expr(lctx, &arm.body), - } -} - -pub fn lower_decl(lctx: &LoweringContext, d: &Decl) -> P<hir::Decl> { - match d.node { - DeclKind::Local(ref l) => P(Spanned { - node: hir::DeclLocal(lower_local(lctx, l)), - span: d.span, - }), - DeclKind::Item(ref it) => P(Spanned { - node: hir::DeclItem(lower_item_id(lctx, it)), - span: d.span, - }), - } -} - -pub fn lower_ty_binding(lctx: &LoweringContext, b: &TypeBinding) -> hir::TypeBinding { - hir::TypeBinding { - id: b.id, - name: b.ident.name, - ty: lower_ty(lctx, &b.ty), - span: b.span, - } -} - -pub fn lower_ty(lctx: &LoweringContext, t: &Ty) -> P<hir::Ty> { - use syntax::ast::TyKind::*; - P(hir::Ty { - id: t.id, - node: match t.node { - Infer => hir::TyInfer, - Vec(ref ty) => hir::TyVec(lower_ty(lctx, ty)), - Ptr(ref mt) => hir::TyPtr(lower_mt(lctx, mt)), - Rptr(ref region, ref mt) => { - hir::TyRptr(lower_opt_lifetime(lctx, region), lower_mt(lctx, mt)) - } - BareFn(ref f) => { - hir::TyBareFn(P(hir::BareFnTy { - lifetimes: lower_lifetime_defs(lctx, &f.lifetimes), - unsafety: lower_unsafety(lctx, f.unsafety), - abi: f.abi, - decl: lower_fn_decl(lctx, &f.decl), - })) - } - Tup(ref tys) => hir::TyTup(tys.iter().map(|ty| lower_ty(lctx, ty)).collect()), - Paren(ref ty) => { - return lower_ty(lctx, ty); - } - Path(ref qself, ref path) => { - let qself = qself.as_ref().map(|&QSelf { ref ty, position }| { - hir::QSelf { - ty: lower_ty(lctx, ty), - position: position, - } - }); - hir::TyPath(qself, lower_path(lctx, path)) - } - ObjectSum(ref ty, ref bounds) => { - hir::TyObjectSum(lower_ty(lctx, ty), lower_bounds(lctx, bounds)) - } - FixedLengthVec(ref ty, ref e) => { - hir::TyFixedLengthVec(lower_ty(lctx, ty), lower_expr(lctx, e)) - } - Typeof(ref expr) => { - hir::TyTypeof(lower_expr(lctx, expr)) - } - PolyTraitRef(ref bounds) => { - hir::TyPolyTraitRef(bounds.iter().map(|b| lower_ty_param_bound(lctx, b)).collect()) - } - Mac(_) => panic!("TyMac should have been expanded by now."), - }, - span: t.span, - }) -} - -pub fn lower_foreign_mod(lctx: &LoweringContext, fm: &ForeignMod) -> hir::ForeignMod { - hir::ForeignMod { - abi: fm.abi, - items: fm.items.iter().map(|x| lower_foreign_item(lctx, x)).collect(), - } -} - -pub fn lower_variant(lctx: &LoweringContext, v: &Variant) -> hir::Variant { - Spanned { - node: hir::Variant_ { - name: v.node.name.name, - attrs: lower_attrs(lctx, &v.node.attrs), - data: lower_variant_data(lctx, &v.node.data), - disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(lctx, e)), - }, - span: v.span, - } -} - -// Path segments are usually unhygienic, hygienic path segments can occur only in -// identifier-like paths originating from `ExprPath`. -// Make life simpler for rustc_resolve by renaming only such segments. -pub fn lower_path_full(lctx: &LoweringContext, p: &Path, maybe_hygienic: bool) -> hir::Path { - let maybe_hygienic = maybe_hygienic && !p.global && p.segments.len() == 1; - hir::Path { - global: p.global, - segments: p.segments - .iter() - .map(|&PathSegment { identifier, ref parameters }| { - hir::PathSegment { - identifier: if maybe_hygienic { - lower_ident(lctx, identifier) - } else { - hir::Ident::from_name(identifier.name) - }, - parameters: lower_path_parameters(lctx, parameters), - } - }) - .collect(), - span: p.span, - } -} - -pub fn lower_path(lctx: &LoweringContext, p: &Path) -> hir::Path { - lower_path_full(lctx, p, false) -} - -pub fn lower_path_parameters(lctx: &LoweringContext, - path_parameters: &PathParameters) - -> hir::PathParameters { - match *path_parameters { - PathParameters::AngleBracketed(ref data) => - hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(lctx, data)), - PathParameters::Parenthesized(ref data) => - hir::ParenthesizedParameters(lower_parenthesized_parameter_data(lctx, data)), - } -} - -pub fn lower_angle_bracketed_parameter_data(lctx: &LoweringContext, - data: &AngleBracketedParameterData) - -> hir::AngleBracketedParameterData { - let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; - hir::AngleBracketedParameterData { - lifetimes: lower_lifetimes(lctx, lifetimes), - types: types.iter().map(|ty| lower_ty(lctx, ty)).collect(), - bindings: bindings.iter().map(|b| lower_ty_binding(lctx, b)).collect(), - } -} - -pub fn lower_parenthesized_parameter_data(lctx: &LoweringContext, - data: &ParenthesizedParameterData) - -> hir::ParenthesizedParameterData { - let &ParenthesizedParameterData { ref inputs, ref output, span } = data; - hir::ParenthesizedParameterData { - inputs: inputs.iter().map(|ty| lower_ty(lctx, ty)).collect(), - output: output.as_ref().map(|ty| lower_ty(lctx, ty)), - span: span, - } -} - -pub fn lower_local(lctx: &LoweringContext, l: &Local) -> P<hir::Local> { - P(hir::Local { - id: l.id, - ty: l.ty.as_ref().map(|t| lower_ty(lctx, t)), - pat: lower_pat(lctx, &l.pat), - init: l.init.as_ref().map(|e| lower_expr(lctx, e)), - span: l.span, - attrs: l.attrs.clone(), - }) -} - -pub fn lower_explicit_self_underscore(lctx: &LoweringContext, - es: &SelfKind) - -> hir::ExplicitSelf_ { - match *es { - SelfKind::Static => hir::SelfStatic, - SelfKind::Value(v) => hir::SelfValue(v.name), - SelfKind::Region(ref lifetime, m, ident) => { - hir::SelfRegion(lower_opt_lifetime(lctx, lifetime), - lower_mutability(lctx, m), - ident.name) - } - SelfKind::Explicit(ref typ, ident) => { - hir::SelfExplicit(lower_ty(lctx, typ), ident.name) - } - } -} - -pub fn lower_mutability(_lctx: &LoweringContext, m: Mutability) -> hir::Mutability { - match m { - Mutability::Mutable => hir::MutMutable, - Mutability::Immutable => hir::MutImmutable, - } -} - -pub fn lower_explicit_self(lctx: &LoweringContext, s: &ExplicitSelf) -> hir::ExplicitSelf { - Spanned { - node: lower_explicit_self_underscore(lctx, &s.node), - span: s.span, - } -} - -pub fn lower_arg(lctx: &LoweringContext, arg: &Arg) -> hir::Arg { - hir::Arg { - id: arg.id, - pat: lower_pat(lctx, &arg.pat), - ty: lower_ty(lctx, &arg.ty), - } -} - -pub fn lower_fn_decl(lctx: &LoweringContext, decl: &FnDecl) -> P<hir::FnDecl> { - P(hir::FnDecl { - inputs: decl.inputs.iter().map(|x| lower_arg(lctx, x)).collect(), - output: match decl.output { - FunctionRetTy::Ty(ref ty) => hir::Return(lower_ty(lctx, ty)), - FunctionRetTy::Default(span) => hir::DefaultReturn(span), - FunctionRetTy::None(span) => hir::NoReturn(span), - }, - variadic: decl.variadic, - }) -} - -pub fn lower_ty_param_bound(lctx: &LoweringContext, tpb: &TyParamBound) -> hir::TyParamBound { - match *tpb { - TraitTyParamBound(ref ty, modifier) => { - hir::TraitTyParamBound(lower_poly_trait_ref(lctx, ty), - lower_trait_bound_modifier(lctx, modifier)) - } - RegionTyParamBound(ref lifetime) => { - hir::RegionTyParamBound(lower_lifetime(lctx, lifetime)) - } - } -} - -pub fn lower_ty_param(lctx: &LoweringContext, tp: &TyParam) -> hir::TyParam { - hir::TyParam { - id: tp.id, - name: tp.ident.name, - bounds: lower_bounds(lctx, &tp.bounds), - default: tp.default.as_ref().map(|x| lower_ty(lctx, x)), - span: tp.span, - } -} - -pub fn lower_ty_params(lctx: &LoweringContext, - tps: &P<[TyParam]>) - -> hir::HirVec<hir::TyParam> { - tps.iter().map(|tp| lower_ty_param(lctx, tp)).collect() -} - -pub fn lower_lifetime(_lctx: &LoweringContext, l: &Lifetime) -> hir::Lifetime { - hir::Lifetime { - id: l.id, - name: l.name, - span: l.span, - } -} - -pub fn lower_lifetime_def(lctx: &LoweringContext, l: &LifetimeDef) -> hir::LifetimeDef { - hir::LifetimeDef { - lifetime: lower_lifetime(lctx, &l.lifetime), - bounds: lower_lifetimes(lctx, &l.bounds), - } -} - -pub fn lower_lifetimes(lctx: &LoweringContext, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> { - lts.iter().map(|l| lower_lifetime(lctx, l)).collect() -} - -pub fn lower_lifetime_defs(lctx: &LoweringContext, - lts: &Vec<LifetimeDef>) - -> hir::HirVec<hir::LifetimeDef> { - lts.iter().map(|l| lower_lifetime_def(lctx, l)).collect() -} - -pub fn lower_opt_lifetime(lctx: &LoweringContext, - o_lt: &Option<Lifetime>) - -> Option<hir::Lifetime> { - o_lt.as_ref().map(|lt| lower_lifetime(lctx, lt)) -} - -pub fn lower_generics(lctx: &LoweringContext, g: &Generics) -> hir::Generics { - hir::Generics { - ty_params: lower_ty_params(lctx, &g.ty_params), - lifetimes: lower_lifetime_defs(lctx, &g.lifetimes), - where_clause: lower_where_clause(lctx, &g.where_clause), - } -} - -pub fn lower_where_clause(lctx: &LoweringContext, wc: &WhereClause) -> hir::WhereClause { - hir::WhereClause { - id: wc.id, - predicates: wc.predicates - .iter() - .map(|predicate| lower_where_predicate(lctx, predicate)) - .collect(), - } -} - -pub fn lower_where_predicate(lctx: &LoweringContext, - pred: &WherePredicate) - -> hir::WherePredicate { - match *pred { - WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes, - ref bounded_ty, - ref bounds, - span}) => { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_lifetimes: lower_lifetime_defs(lctx, bound_lifetimes), - bounded_ty: lower_ty(lctx, bounded_ty), - bounds: bounds.iter().map(|x| lower_ty_param_bound(lctx, x)).collect(), - span: span, - }) - } - WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime, - ref bounds, - span}) => { - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - span: span, - lifetime: lower_lifetime(lctx, lifetime), - bounds: bounds.iter().map(|bound| lower_lifetime(lctx, bound)).collect(), - }) - } - WherePredicate::EqPredicate(WhereEqPredicate{ id, - ref path, - ref ty, - span}) => { - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - id: id, - path: lower_path(lctx, path), - ty: lower_ty(lctx, ty), - span: span, - }) - } - } -} - -pub fn lower_variant_data(lctx: &LoweringContext, vdata: &VariantData) -> hir::VariantData { - match *vdata { - VariantData::Struct(ref fields, id) => { - hir::VariantData::Struct(fields.iter() - .enumerate() - .map(|f| lower_struct_field(lctx, f)) - .collect(), - id) - } - VariantData::Tuple(ref fields, id) => { - hir::VariantData::Tuple(fields.iter() - .enumerate() - .map(|f| lower_struct_field(lctx, f)) - .collect(), - id) - } - VariantData::Unit(id) => hir::VariantData::Unit(id), - } -} - -pub fn lower_trait_ref(lctx: &LoweringContext, p: &TraitRef) -> hir::TraitRef { - hir::TraitRef { - path: lower_path(lctx, &p.path), - ref_id: p.ref_id, - } -} - -pub fn lower_poly_trait_ref(lctx: &LoweringContext, p: &PolyTraitRef) -> hir::PolyTraitRef { - hir::PolyTraitRef { - bound_lifetimes: lower_lifetime_defs(lctx, &p.bound_lifetimes), - trait_ref: lower_trait_ref(lctx, &p.trait_ref), - span: p.span, - } -} - -pub fn lower_struct_field(lctx: &LoweringContext, - (index, f): (usize, &StructField)) - -> hir::StructField { - hir::StructField { - span: f.span, - id: f.node.id, - name: f.node.ident().map(|ident| ident.name) - .unwrap_or(token::intern(&index.to_string())), - vis: lower_visibility(lctx, f.node.kind.visibility()), - ty: lower_ty(lctx, &f.node.ty), - attrs: lower_attrs(lctx, &f.node.attrs), - } -} - -pub fn lower_field(lctx: &LoweringContext, f: &Field) -> hir::Field { - hir::Field { - name: respan(f.ident.span, f.ident.node.name), - expr: lower_expr(lctx, &f.expr), - span: f.span, - } -} - -pub fn lower_mt(lctx: &LoweringContext, mt: &MutTy) -> hir::MutTy { - hir::MutTy { - ty: lower_ty(lctx, &mt.ty), - mutbl: lower_mutability(lctx, mt.mutbl), - } -} - -pub fn lower_opt_bounds(lctx: &LoweringContext, - b: &Option<TyParamBounds>) - -> Option<hir::TyParamBounds> { - b.as_ref().map(|ref bounds| lower_bounds(lctx, bounds)) -} - -fn lower_bounds(lctx: &LoweringContext, bounds: &TyParamBounds) -> hir::TyParamBounds { - bounds.iter().map(|bound| lower_ty_param_bound(lctx, bound)).collect() -} - -pub fn lower_block(lctx: &LoweringContext, b: &Block) -> P<hir::Block> { - P(hir::Block { - id: b.id, - stmts: b.stmts.iter().map(|s| lower_stmt(lctx, s)).collect(), - expr: b.expr.as_ref().map(|ref x| lower_expr(lctx, x)), - rules: lower_block_check_mode(lctx, &b.rules), - span: b.span, - }) -} - -pub fn lower_item_kind(lctx: &LoweringContext, i: &ItemKind) -> hir::Item_ { - match *i { - ItemKind::ExternCrate(string) => hir::ItemExternCrate(string), - ItemKind::Use(ref view_path) => { - hir::ItemUse(lower_view_path(lctx, view_path)) - } - ItemKind::Static(ref t, m, ref e) => { - hir::ItemStatic(lower_ty(lctx, t), - lower_mutability(lctx, m), - lower_expr(lctx, e)) - } - ItemKind::Const(ref t, ref e) => { - hir::ItemConst(lower_ty(lctx, t), lower_expr(lctx, e)) - } - ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { - hir::ItemFn(lower_fn_decl(lctx, decl), - lower_unsafety(lctx, unsafety), - lower_constness(lctx, constness), - abi, - lower_generics(lctx, generics), - lower_block(lctx, body)) - } - ItemKind::Mod(ref m) => hir::ItemMod(lower_mod(lctx, m)), - ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(lower_foreign_mod(lctx, nm)), - ItemKind::Ty(ref t, ref generics) => { - hir::ItemTy(lower_ty(lctx, t), lower_generics(lctx, generics)) - } - ItemKind::Enum(ref enum_definition, ref generics) => { - hir::ItemEnum(hir::EnumDef { - variants: enum_definition.variants - .iter() - .map(|x| lower_variant(lctx, x)) - .collect(), - }, - lower_generics(lctx, generics)) - } - ItemKind::Struct(ref struct_def, ref generics) => { - let struct_def = lower_variant_data(lctx, struct_def); - hir::ItemStruct(struct_def, lower_generics(lctx, generics)) - } - ItemKind::DefaultImpl(unsafety, ref trait_ref) => { - hir::ItemDefaultImpl(lower_unsafety(lctx, unsafety), - lower_trait_ref(lctx, trait_ref)) - } - ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => { - let new_impl_items = impl_items.iter() - .map(|item| lower_impl_item(lctx, item)) - .collect(); - let ifce = ifce.as_ref().map(|trait_ref| lower_trait_ref(lctx, trait_ref)); - hir::ItemImpl(lower_unsafety(lctx, unsafety), - lower_impl_polarity(lctx, polarity), - lower_generics(lctx, generics), - ifce, - lower_ty(lctx, ty), - new_impl_items) - } - ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => { - let bounds = lower_bounds(lctx, bounds); - let items = items.iter().map(|item| lower_trait_item(lctx, item)).collect(); - hir::ItemTrait(lower_unsafety(lctx, unsafety), - lower_generics(lctx, generics), - bounds, - items) - } - ItemKind::Mac(_) => panic!("Shouldn't still be around"), - } -} - -pub fn lower_trait_item(lctx: &LoweringContext, i: &TraitItem) -> hir::TraitItem { - hir::TraitItem { - id: i.id, - name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - node: match i.node { - TraitItemKind::Const(ref ty, ref default) => { - hir::ConstTraitItem(lower_ty(lctx, ty), - default.as_ref().map(|x| lower_expr(lctx, x))) - } - TraitItemKind::Method(ref sig, ref body) => { - hir::MethodTraitItem(lower_method_sig(lctx, sig), - body.as_ref().map(|x| lower_block(lctx, x))) - } - TraitItemKind::Type(ref bounds, ref default) => { - hir::TypeTraitItem(lower_bounds(lctx, bounds), - default.as_ref().map(|x| lower_ty(lctx, x))) - } - }, - span: i.span, - } -} - -pub fn lower_impl_item(lctx: &LoweringContext, i: &ImplItem) -> hir::ImplItem { - hir::ImplItem { - id: i.id, - name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - vis: lower_visibility(lctx, &i.vis), - defaultness: lower_defaultness(lctx, i.defaultness), - node: match i.node { - ImplItemKind::Const(ref ty, ref expr) => { - hir::ImplItemKind::Const(lower_ty(lctx, ty), lower_expr(lctx, expr)) - } - ImplItemKind::Method(ref sig, ref body) => { - hir::ImplItemKind::Method(lower_method_sig(lctx, sig), lower_block(lctx, body)) - } - ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(lower_ty(lctx, ty)), - ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), - }, - span: i.span, - } -} - -pub fn lower_mod(lctx: &LoweringContext, m: &Mod) -> hir::Mod { - hir::Mod { - inner: m.inner, - item_ids: m.items.iter().map(|x| lower_item_id(lctx, x)).collect(), - } -} - -struct ItemLowerer<'lcx, 'interner: 'lcx> { - items: BTreeMap<NodeId, hir::Item>, - lctx: &'lcx LoweringContext<'interner>, -} - -impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> { - fn visit_item(&mut self, item: &'lcx Item) { - self.items.insert(item.id, lower_item(self.lctx, item)); - visit::walk_item(self, item); - } -} - -pub fn lower_crate(lctx: &LoweringContext, c: &Crate) -> hir::Crate { - let items = { - let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), lctx: lctx }; - visit::walk_crate(&mut item_lowerer, c); - item_lowerer.items - }; - - hir::Crate { - module: lower_mod(lctx, &c.module), - attrs: lower_attrs(lctx, &c.attrs), - config: c.config.clone().into(), - span: c.span, - exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(lctx, m)).collect(), - items: items, - } -} - -pub fn lower_macro_def(lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef { - hir::MacroDef { - name: m.ident.name, - attrs: lower_attrs(lctx, &m.attrs), - id: m.id, - span: m.span, - imported_from: m.imported_from.map(|x| x.name), - export: m.export, - use_locally: m.use_locally, - allow_internal_unstable: m.allow_internal_unstable, - body: m.body.clone().into(), - } -} - -pub fn lower_item_id(_lctx: &LoweringContext, i: &Item) -> hir::ItemId { - hir::ItemId { id: i.id } -} - -pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item { - let node = lower_item_kind(lctx, &i.node); - - hir::Item { - id: i.id, - name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - node: node, - vis: lower_visibility(lctx, &i.vis), - span: i.span, - } -} - -pub fn lower_foreign_item(lctx: &LoweringContext, i: &ForeignItem) -> hir::ForeignItem { - hir::ForeignItem { - id: i.id, - name: i.ident.name, - attrs: lower_attrs(lctx, &i.attrs), - node: match i.node { - ForeignItemKind::Fn(ref fdec, ref generics) => { - hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics)) - } - ForeignItemKind::Static(ref t, m) => { - hir::ForeignItemStatic(lower_ty(lctx, t), m) - } - }, - vis: lower_visibility(lctx, &i.vis), - span: i.span, - } -} - -pub fn lower_method_sig(lctx: &LoweringContext, sig: &MethodSig) -> hir::MethodSig { - hir::MethodSig { - generics: lower_generics(lctx, &sig.generics), - abi: sig.abi, - explicit_self: lower_explicit_self(lctx, &sig.explicit_self), - unsafety: lower_unsafety(lctx, sig.unsafety), - constness: lower_constness(lctx, sig.constness), - decl: lower_fn_decl(lctx, &sig.decl), - } -} - -pub fn lower_unsafety(_lctx: &LoweringContext, u: Unsafety) -> hir::Unsafety { - match u { - Unsafety::Unsafe => hir::Unsafety::Unsafe, - Unsafety::Normal => hir::Unsafety::Normal, - } -} - -pub fn lower_constness(_lctx: &LoweringContext, c: Constness) -> hir::Constness { - match c { - Constness::Const => hir::Constness::Const, - Constness::NotConst => hir::Constness::NotConst, - } -} - -pub fn lower_unop(_lctx: &LoweringContext, u: UnOp) -> hir::UnOp { - match u { - UnOp::Deref => hir::UnDeref, - UnOp::Not => hir::UnNot, - UnOp::Neg => hir::UnNeg, - } -} - -pub fn lower_binop(_lctx: &LoweringContext, b: BinOp) -> hir::BinOp { - Spanned { - node: match b.node { - BinOpKind::Add => hir::BiAdd, - BinOpKind::Sub => hir::BiSub, - BinOpKind::Mul => hir::BiMul, - BinOpKind::Div => hir::BiDiv, - BinOpKind::Rem => hir::BiRem, - BinOpKind::And => hir::BiAnd, - BinOpKind::Or => hir::BiOr, - BinOpKind::BitXor => hir::BiBitXor, - BinOpKind::BitAnd => hir::BiBitAnd, - BinOpKind::BitOr => hir::BiBitOr, - BinOpKind::Shl => hir::BiShl, - BinOpKind::Shr => hir::BiShr, - BinOpKind::Eq => hir::BiEq, - BinOpKind::Lt => hir::BiLt, - BinOpKind::Le => hir::BiLe, - BinOpKind::Ne => hir::BiNe, - BinOpKind::Ge => hir::BiGe, - BinOpKind::Gt => hir::BiGt, - }, - span: b.span, - } -} - -pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> { - P(hir::Pat { - id: p.id, - node: match p.node { - PatKind::Wild => hir::PatKind::Wild, - PatKind::Ident(ref binding_mode, pth1, ref sub) => { - hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode), - respan(pth1.span, lower_ident(lctx, pth1.node)), - sub.as_ref().map(|x| lower_pat(lctx, x))) - } - PatKind::Lit(ref e) => hir::PatKind::Lit(lower_expr(lctx, e)), - PatKind::TupleStruct(ref pth, ref pats) => { - hir::PatKind::TupleStruct(lower_path(lctx, pth), - pats.as_ref() - .map(|pats| pats.iter().map(|x| lower_pat(lctx, x)).collect())) - } - PatKind::Path(ref pth) => { - hir::PatKind::Path(lower_path(lctx, pth)) - } - PatKind::QPath(ref qself, ref pth) => { - let qself = hir::QSelf { - ty: lower_ty(lctx, &qself.ty), - position: qself.position, - }; - hir::PatKind::QPath(qself, lower_path(lctx, pth)) - } - PatKind::Struct(ref pth, ref fields, etc) => { - let pth = lower_path(lctx, pth); - let fs = fields.iter() - .map(|f| { - Spanned { - span: f.span, - node: hir::FieldPat { - name: f.node.ident.name, - pat: lower_pat(lctx, &f.node.pat), - is_shorthand: f.node.is_shorthand, - }, - } - }) - .collect(); - hir::PatKind::Struct(pth, fs, etc) - } - PatKind::Tup(ref elts) => { - hir::PatKind::Tup(elts.iter().map(|x| lower_pat(lctx, x)).collect()) - } - PatKind::Box(ref inner) => hir::PatKind::Box(lower_pat(lctx, inner)), - PatKind::Ref(ref inner, mutbl) => { - hir::PatKind::Ref(lower_pat(lctx, inner), lower_mutability(lctx, mutbl)) - } - PatKind::Range(ref e1, ref e2) => { - hir::PatKind::Range(lower_expr(lctx, e1), lower_expr(lctx, e2)) - } - PatKind::Vec(ref before, ref slice, ref after) => { - hir::PatKind::Vec(before.iter().map(|x| lower_pat(lctx, x)).collect(), - slice.as_ref().map(|x| lower_pat(lctx, x)), - after.iter().map(|x| lower_pat(lctx, x)).collect()) - } - PatKind::Mac(_) => panic!("Shouldn't exist here"), - }, - span: p.span, - }) -} - -pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> { - P(hir::Expr { - id: e.id, - node: match e.node { - // Issue #22181: - // Eventually a desugaring for `box EXPR` - // (similar to the desugaring above for `in PLACE BLOCK`) - // should go here, desugaring - // - // to: - // - // let mut place = BoxPlace::make_place(); - // let raw_place = Place::pointer(&mut place); - // let value = $value; - // unsafe { - // ::std::ptr::write(raw_place, value); - // Boxed::finalize(place) - // } - // - // But for now there are type-inference issues doing that. - ExprKind::Box(ref e) => { - hir::ExprBox(lower_expr(lctx, e)) - } - - // Desugar ExprBox: `in (PLACE) EXPR` - ExprKind::InPlace(ref placer, ref value_expr) => { - // to: - // - // let p = PLACE; - // let mut place = Placer::make_place(p); - // let raw_place = Place::pointer(&mut place); - // push_unsafe!({ - // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); - // InPlace::finalize(place) - // }) - return cache_ids(lctx, e.id, |lctx| { - let placer_expr = lower_expr(lctx, placer); - let value_expr = lower_expr(lctx, value_expr); - - let placer_ident = lctx.str_to_ident("placer"); - let place_ident = lctx.str_to_ident("place"); - let p_ptr_ident = lctx.str_to_ident("p_ptr"); - - let make_place = ["ops", "Placer", "make_place"]; - let place_pointer = ["ops", "Place", "pointer"]; - let move_val_init = ["intrinsics", "move_val_init"]; - let inplace_finalize = ["ops", "InPlace", "finalize"]; - - let make_call = |lctx: &LoweringContext, p, args| { - let path = core_path(lctx, e.span, p); - let path = expr_path(lctx, path, None); - expr_call(lctx, e.span, path, args, None) - }; - - let mk_stmt_let = |lctx: &LoweringContext, bind, expr| { - stmt_let(lctx, e.span, false, bind, expr, None) - }; - - let mk_stmt_let_mut = |lctx: &LoweringContext, bind, expr| { - stmt_let(lctx, e.span, true, bind, expr, None) - }; - - // let placer = <placer_expr> ; - let s1 = { - let placer_expr = signal_block_expr(lctx, - hir_vec![], - placer_expr, - e.span, - hir::PopUnstableBlock, - None); - mk_stmt_let(lctx, placer_ident, placer_expr) - }; - - // let mut place = Placer::make_place(placer); - let s2 = { - let placer = expr_ident(lctx, e.span, placer_ident, None); - let call = make_call(lctx, &make_place, hir_vec![placer]); - mk_stmt_let_mut(lctx, place_ident, call) - }; - - // let p_ptr = Place::pointer(&mut place); - let s3 = { - let agent = expr_ident(lctx, e.span, place_ident, None); - let args = hir_vec![expr_mut_addr_of(lctx, e.span, agent, None)]; - let call = make_call(lctx, &place_pointer, args); - mk_stmt_let(lctx, p_ptr_ident, call) - }; - - // pop_unsafe!(EXPR)); - let pop_unsafe_expr = { - let value_expr = signal_block_expr(lctx, - hir_vec![], - value_expr, - e.span, - hir::PopUnstableBlock, - None); - signal_block_expr(lctx, - hir_vec![], - value_expr, - e.span, - hir::PopUnsafeBlock(hir::CompilerGenerated), None) - }; - - // push_unsafe!({ - // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); - // InPlace::finalize(place) - // }) - let expr = { - let ptr = expr_ident(lctx, e.span, p_ptr_ident, None); - let call_move_val_init = - hir::StmtSemi( - make_call(lctx, &move_val_init, hir_vec![ptr, pop_unsafe_expr]), - lctx.next_id()); - let call_move_val_init = respan(e.span, call_move_val_init); - - let place = expr_ident(lctx, e.span, place_ident, None); - let call = make_call(lctx, &inplace_finalize, hir_vec![place]); - signal_block_expr(lctx, - hir_vec![call_move_val_init], - call, - e.span, - hir::PushUnsafeBlock(hir::CompilerGenerated), None) - }; - - signal_block_expr(lctx, - hir_vec![s1, s2, s3], - expr, - e.span, - hir::PushUnstableBlock, - e.attrs.clone()) - }); - } - - ExprKind::Vec(ref exprs) => { - hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect()) - } - ExprKind::Repeat(ref expr, ref count) => { - let expr = lower_expr(lctx, expr); - let count = lower_expr(lctx, count); - hir::ExprRepeat(expr, count) - } - ExprKind::Tup(ref elts) => { - hir::ExprTup(elts.iter().map(|x| lower_expr(lctx, x)).collect()) - } - ExprKind::Call(ref f, ref args) => { - let f = lower_expr(lctx, f); - hir::ExprCall(f, args.iter().map(|x| lower_expr(lctx, x)).collect()) - } - ExprKind::MethodCall(i, ref tps, ref args) => { - let tps = tps.iter().map(|x| lower_ty(lctx, x)).collect(); - let args = args.iter().map(|x| lower_expr(lctx, x)).collect(); - hir::ExprMethodCall(respan(i.span, i.node.name), tps, args) - } - ExprKind::Binary(binop, ref lhs, ref rhs) => { - let binop = lower_binop(lctx, binop); - let lhs = lower_expr(lctx, lhs); - let rhs = lower_expr(lctx, rhs); - hir::ExprBinary(binop, lhs, rhs) - } - ExprKind::Unary(op, ref ohs) => { - let op = lower_unop(lctx, op); - let ohs = lower_expr(lctx, ohs); - hir::ExprUnary(op, ohs) - } - ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())), - ExprKind::Cast(ref expr, ref ty) => { - let expr = lower_expr(lctx, expr); - hir::ExprCast(expr, lower_ty(lctx, ty)) - } - ExprKind::Type(ref expr, ref ty) => { - let expr = lower_expr(lctx, expr); - hir::ExprType(expr, lower_ty(lctx, ty)) - } - ExprKind::AddrOf(m, ref ohs) => { - let m = lower_mutability(lctx, m); - let ohs = lower_expr(lctx, ohs); - hir::ExprAddrOf(m, ohs) - } - // More complicated than you might expect because the else branch - // might be `if let`. - ExprKind::If(ref cond, ref blk, ref else_opt) => { - let else_opt = else_opt.as_ref().map(|els| { - match els.node { - ExprKind::IfLet(..) => { - cache_ids(lctx, e.id, |lctx| { - // wrap the if-let expr in a block - let span = els.span; - let els = lower_expr(lctx, els); - let id = lctx.next_id(); - let blk = P(hir::Block { - stmts: hir_vec![], - expr: Some(els), - id: id, - rules: hir::DefaultBlock, - span: span, - }); - expr_block(lctx, blk, None) - }) - } - _ => lower_expr(lctx, els), - } - }); - - hir::ExprIf(lower_expr(lctx, cond), lower_block(lctx, blk), else_opt) - } - ExprKind::While(ref cond, ref body, opt_ident) => { - hir::ExprWhile(lower_expr(lctx, cond), lower_block(lctx, body), - opt_ident.map(|ident| lower_ident(lctx, ident))) - } - ExprKind::Loop(ref body, opt_ident) => { - hir::ExprLoop(lower_block(lctx, body), - opt_ident.map(|ident| lower_ident(lctx, ident))) - } - ExprKind::Match(ref expr, ref arms) => { - hir::ExprMatch(lower_expr(lctx, expr), - arms.iter().map(|x| lower_arm(lctx, x)).collect(), - hir::MatchSource::Normal) - } - ExprKind::Closure(capture_clause, ref decl, ref body) => { - hir::ExprClosure(lower_capture_clause(lctx, capture_clause), - lower_fn_decl(lctx, decl), - lower_block(lctx, body)) - } - ExprKind::Block(ref blk) => hir::ExprBlock(lower_block(lctx, blk)), - ExprKind::Assign(ref el, ref er) => { - hir::ExprAssign(lower_expr(lctx, el), lower_expr(lctx, er)) - } - ExprKind::AssignOp(op, ref el, ref er) => { - hir::ExprAssignOp(lower_binop(lctx, op), - lower_expr(lctx, el), - lower_expr(lctx, er)) - } - ExprKind::Field(ref el, ident) => { - hir::ExprField(lower_expr(lctx, el), respan(ident.span, ident.node.name)) - } - ExprKind::TupField(ref el, ident) => { - hir::ExprTupField(lower_expr(lctx, el), ident) - } - ExprKind::Index(ref el, ref er) => { - hir::ExprIndex(lower_expr(lctx, el), lower_expr(lctx, er)) - } - ExprKind::Range(ref e1, ref e2, lims) => { - fn make_struct(lctx: &LoweringContext, - ast_expr: &Expr, - path: &[&str], - fields: &[(&str, &P<Expr>)]) -> P<hir::Expr> { - let strs = std_path(lctx, &iter::once(&"ops") - .chain(path) - .map(|s| *s) - .collect::<Vec<_>>()); - - let structpath = path_global(ast_expr.span, strs); - - let hir_expr = if fields.len() == 0 { - expr_path(lctx, - structpath, - ast_expr.attrs.clone()) - } else { - expr_struct(lctx, - ast_expr.span, - structpath, - fields.into_iter().map(|&(s, e)| { - field(token::intern(s), - signal_block_expr(lctx, - hir_vec![], - lower_expr(lctx, &**e), - e.span, - hir::PopUnstableBlock, - None), - ast_expr.span) - }).collect(), - None, - ast_expr.attrs.clone()) - }; - - signal_block_expr(lctx, - hir_vec![], - hir_expr, - ast_expr.span, - hir::PushUnstableBlock, - None) - } - - return cache_ids(lctx, e.id, |lctx| { - use syntax::ast::RangeLimits::*; - - match (e1, e2, lims) { - (&None, &None, HalfOpen) => - make_struct(lctx, e, &["RangeFull"], - &[]), - - (&Some(ref e1), &None, HalfOpen) => - make_struct(lctx, e, &["RangeFrom"], - &[("start", e1)]), - - (&None, &Some(ref e2), HalfOpen) => - make_struct(lctx, e, &["RangeTo"], - &[("end", e2)]), - - (&Some(ref e1), &Some(ref e2), HalfOpen) => - make_struct(lctx, e, &["Range"], - &[("start", e1), ("end", e2)]), - - (&None, &Some(ref e2), Closed) => - make_struct(lctx, e, &["RangeToInclusive"], - &[("end", e2)]), - - (&Some(ref e1), &Some(ref e2), Closed) => - make_struct(lctx, e, &["RangeInclusive", "NonEmpty"], - &[("start", e1), ("end", e2)]), - - _ => panic!(lctx.diagnostic().span_fatal(e.span, - "inclusive range with no end")) - } - }); - } - ExprKind::Path(ref qself, ref path) => { - let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| { - hir::QSelf { - ty: lower_ty(lctx, ty), - position: position, - } - }); - hir::ExprPath(hir_qself, lower_path_full(lctx, path, qself.is_none())) - } - ExprKind::Break(opt_ident) => hir::ExprBreak(opt_ident.map(|sp_ident| { - respan(sp_ident.span, lower_ident(lctx, sp_ident.node)) - })), - ExprKind::Again(opt_ident) => hir::ExprAgain(opt_ident.map(|sp_ident| { - respan(sp_ident.span, lower_ident(lctx, sp_ident.node)) - })), - ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(lctx, x))), - ExprKind::InlineAsm(InlineAsm { - ref inputs, - ref outputs, - ref asm, - asm_str_style, - ref clobbers, - volatile, - alignstack, - dialect, - expn_id, - }) => hir::ExprInlineAsm(hir::InlineAsm { - inputs: inputs.iter().map(|&(ref c, _)| c.clone()).collect(), - outputs: outputs.iter() - .map(|out| { - hir::InlineAsmOutput { - constraint: out.constraint.clone(), - is_rw: out.is_rw, - is_indirect: out.is_indirect, - } - }) - .collect(), - asm: asm.clone(), - asm_str_style: asm_str_style, - clobbers: clobbers.clone().into(), - volatile: volatile, - alignstack: alignstack, - dialect: dialect, - expn_id: expn_id, - }, outputs.iter().map(|out| lower_expr(lctx, &out.expr)).collect(), - inputs.iter().map(|&(_, ref input)| lower_expr(lctx, input)).collect()), - ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - hir::ExprStruct(lower_path(lctx, path), - fields.iter().map(|x| lower_field(lctx, x)).collect(), - maybe_expr.as_ref().map(|x| lower_expr(lctx, x))) - } - ExprKind::Paren(ref ex) => { - // merge attributes into the inner expression. - return lower_expr(lctx, ex).map(|mut ex| { - ex.attrs.update(|attrs| { - attrs.prepend(e.attrs.clone()) - }); - ex - }); - } - - // Desugar ExprIfLet - // From: `if let <pat> = <sub_expr> <body> [<else_opt>]` - ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => { - // to: - // - // match <sub_expr> { - // <pat> => <body>, - // [_ if <else_opt_if_cond> => <else_opt_if_body>,] - // _ => [<else_opt> | ()] - // } - - return cache_ids(lctx, e.id, |lctx| { - // `<pat> => <body>` - let pat_arm = { - let body = lower_block(lctx, body); - let body_expr = expr_block(lctx, body, None); - arm(hir_vec![lower_pat(lctx, pat)], body_expr) - }; - - // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]` - let mut else_opt = else_opt.as_ref().map(|e| lower_expr(lctx, e)); - let else_if_arms = { - let mut arms = vec![]; - loop { - let else_opt_continue = else_opt.and_then(|els| { - els.and_then(|els| { - match els.node { - // else if - hir::ExprIf(cond, then, else_opt) => { - let pat_under = pat_wild(lctx, e.span); - arms.push(hir::Arm { - attrs: hir_vec![], - pats: hir_vec![pat_under], - guard: Some(cond), - body: expr_block(lctx, then, None), - }); - else_opt.map(|else_opt| (else_opt, true)) - } - _ => Some((P(els), false)), - } - }) - }); - match else_opt_continue { - Some((e, true)) => { - else_opt = Some(e); - } - Some((e, false)) => { - else_opt = Some(e); - break; - } - None => { - else_opt = None; - break; - } - } - } - arms - }; - - let contains_else_clause = else_opt.is_some(); - - // `_ => [<else_opt> | ()]` - let else_arm = { - let pat_under = pat_wild(lctx, e.span); - let else_expr = - else_opt.unwrap_or_else( - || expr_tuple(lctx, e.span, hir_vec![], None)); - arm(hir_vec![pat_under], else_expr) - }; - - let mut arms = Vec::with_capacity(else_if_arms.len() + 2); - arms.push(pat_arm); - arms.extend(else_if_arms); - arms.push(else_arm); - - let sub_expr = lower_expr(lctx, sub_expr); - // add attributes to the outer returned expr node - expr(lctx, - e.span, - hir::ExprMatch(sub_expr, - arms.into(), - hir::MatchSource::IfLetDesugar { - contains_else_clause: contains_else_clause, - }), - e.attrs.clone()) - }); - } - - // Desugar ExprWhileLet - // From: `[opt_ident]: while let <pat> = <sub_expr> <body>` - ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => { - // to: - // - // [opt_ident]: loop { - // match <sub_expr> { - // <pat> => <body>, - // _ => break - // } - // } - - return cache_ids(lctx, e.id, |lctx| { - // `<pat> => <body>` - let pat_arm = { - let body = lower_block(lctx, body); - let body_expr = expr_block(lctx, body, None); - arm(hir_vec![lower_pat(lctx, pat)], body_expr) - }; - - // `_ => break` - let break_arm = { - let pat_under = pat_wild(lctx, e.span); - let break_expr = expr_break(lctx, e.span, None); - arm(hir_vec![pat_under], break_expr) - }; - - // `match <sub_expr> { ... }` - let arms = hir_vec![pat_arm, break_arm]; - let sub_expr = lower_expr(lctx, sub_expr); - let match_expr = expr(lctx, - e.span, - hir::ExprMatch(sub_expr, - arms, - hir::MatchSource::WhileLetDesugar), - None); - - // `[opt_ident]: loop { ... }` - let loop_block = block_expr(lctx, match_expr); - let loop_expr = hir::ExprLoop(loop_block, - opt_ident.map(|ident| lower_ident(lctx, ident))); - // add attributes to the outer returned expr node - expr(lctx, e.span, loop_expr, e.attrs.clone()) - }); - } - - // Desugar ExprForLoop - // From: `[opt_ident]: for <pat> in <head> <body>` - ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => { - // to: - // - // { - // let result = match ::std::iter::IntoIterator::into_iter(<head>) { - // mut iter => { - // [opt_ident]: loop { - // match ::std::iter::Iterator::next(&mut iter) { - // ::std::option::Option::Some(<pat>) => <body>, - // ::std::option::Option::None => break - // } - // } - // } - // }; - // result - // } - - return cache_ids(lctx, e.id, |lctx| { - // expand <head> - let head = lower_expr(lctx, head); - - let iter = lctx.str_to_ident("iter"); - - // `::std::option::Option::Some(<pat>) => <body>` - let pat_arm = { - let body_block = lower_block(lctx, body); - let body_span = body_block.span; - let body_expr = P(hir::Expr { - id: lctx.next_id(), - node: hir::ExprBlock(body_block), - span: body_span, - attrs: None, - }); - let pat = lower_pat(lctx, pat); - let some_pat = pat_some(lctx, e.span, pat); - - arm(hir_vec![some_pat], body_expr) - }; - - // `::std::option::Option::None => break` - let break_arm = { - let break_expr = expr_break(lctx, e.span, None); - - arm(hir_vec![pat_none(lctx, e.span)], break_expr) - }; - - // `match ::std::iter::Iterator::next(&mut iter) { ... }` - let match_expr = { - let next_path = { - let strs = std_path(lctx, &["iter", "Iterator", "next"]); - - path_global(e.span, strs) - }; - let iter = expr_ident(lctx, e.span, iter, None); - let ref_mut_iter = expr_mut_addr_of(lctx, e.span, iter, None); - let next_path = expr_path(lctx, next_path, None); - let next_expr = expr_call(lctx, - e.span, - next_path, - hir_vec![ref_mut_iter], - None); - let arms = hir_vec![pat_arm, break_arm]; - - expr(lctx, - e.span, - hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), - None) - }; - - // `[opt_ident]: loop { ... }` - let loop_block = block_expr(lctx, match_expr); - let loop_expr = hir::ExprLoop(loop_block, - opt_ident.map(|ident| lower_ident(lctx, ident))); - let loop_expr = expr(lctx, e.span, loop_expr, None); - - // `mut iter => { ... }` - let iter_arm = { - let iter_pat = pat_ident_binding_mode(lctx, - e.span, - iter, - hir::BindByValue(hir::MutMutable)); - arm(hir_vec![iter_pat], loop_expr) - }; - - // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }` - let into_iter_expr = { - let into_iter_path = { - let strs = std_path(lctx, &["iter", "IntoIterator", "into_iter"]); - - path_global(e.span, strs) - }; - - let into_iter = expr_path(lctx, into_iter_path, None); - expr_call(lctx, e.span, into_iter, hir_vec![head], None) - }; - - let match_expr = expr_match(lctx, - e.span, - into_iter_expr, - hir_vec![iter_arm], - hir::MatchSource::ForLoopDesugar, - None); - - // `{ let _result = ...; _result }` - // underscore prevents an unused_variables lint if the head diverges - let result_ident = lctx.str_to_ident("_result"); - let let_stmt = stmt_let(lctx, e.span, false, result_ident, match_expr, None); - let result = expr_ident(lctx, e.span, result_ident, None); - let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result)); - // add the attributes to the outer returned expr node - expr_block(lctx, block, e.attrs.clone()) - }); - } - - // Desugar ExprKind::Try - // From: `<expr>?` - ExprKind::Try(ref sub_expr) => { - // to: - // - // { - // match <expr> { - // Ok(val) => val, - // Err(err) => { - // return Err(From::from(err)) - // } - // } - // } - - return cache_ids(lctx, e.id, |lctx| { - // expand <expr> - let sub_expr = lower_expr(lctx, sub_expr); - - // Ok(val) => val - let ok_arm = { - let val_ident = lctx.str_to_ident("val"); - let val_pat = pat_ident(lctx, e.span, val_ident); - let val_expr = expr_ident(lctx, e.span, val_ident, None); - let ok_pat = pat_ok(lctx, e.span, val_pat); - - arm(hir_vec![ok_pat], val_expr) - }; - - // Err(err) => return Err(From::from(err)) - let err_arm = { - let err_ident = lctx.str_to_ident("err"); - let from_expr = { - let path = std_path(lctx, &["convert", "From", "from"]); - let path = path_global(e.span, path); - let from = expr_path(lctx, path, None); - let err_expr = expr_ident(lctx, e.span, err_ident, None); - - expr_call(lctx, e.span, from, hir_vec![err_expr], None) - }; - let err_expr = { - let path = std_path(lctx, &["result", "Result", "Err"]); - let path = path_global(e.span, path); - let err_ctor = expr_path(lctx, path, None); - expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None) - }; - let err_pat = pat_err(lctx, e.span, pat_ident(lctx, e.span, err_ident)); - let ret_expr = expr(lctx, e.span, - hir::Expr_::ExprRet(Some(err_expr)), None); - - arm(hir_vec![err_pat], ret_expr) - }; - - expr_match(lctx, e.span, sub_expr, hir_vec![err_arm, ok_arm], - hir::MatchSource::TryDesugar, None) - }) - } - - ExprKind::Mac(_) => panic!("Shouldn't exist here"), - }, - span: e.span, - attrs: e.attrs.clone(), - }) -} - -pub fn lower_stmt(lctx: &LoweringContext, s: &Stmt) -> hir::Stmt { - match s.node { - StmtKind::Decl(ref d, id) => { - Spanned { - node: hir::StmtDecl(lower_decl(lctx, d), id), - span: s.span, - } - } - StmtKind::Expr(ref e, id) => { - Spanned { - node: hir::StmtExpr(lower_expr(lctx, e), id), - span: s.span, - } - } - StmtKind::Semi(ref e, id) => { - Spanned { - node: hir::StmtSemi(lower_expr(lctx, e), id), - span: s.span, - } - } - StmtKind::Mac(..) => panic!("Shouldn't exist here"), - } -} - -pub fn lower_capture_clause(_lctx: &LoweringContext, c: CaptureBy) -> hir::CaptureClause { - match c { - CaptureBy::Value => hir::CaptureByValue, - CaptureBy::Ref => hir::CaptureByRef, - } -} - -pub fn lower_visibility(lctx: &LoweringContext, v: &Visibility) -> hir::Visibility { - match *v { - Visibility::Public => hir::Public, - Visibility::Inherited => hir::Inherited, - _ => panic!(lctx.diagnostic().fatal("pub(restricted) is not implemented yet!")) - } -} - -pub fn lower_defaultness(_lctx: &LoweringContext, d: Defaultness) -> hir::Defaultness { - match d { - Defaultness::Default => hir::Defaultness::Default, - Defaultness::Final => hir::Defaultness::Final, - } -} - -pub fn lower_block_check_mode(lctx: &LoweringContext, b: &BlockCheckMode) -> hir::BlockCheckMode { - match *b { - BlockCheckMode::Default => hir::DefaultBlock, - BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(lower_unsafe_source(lctx, u)), - } -} - -pub fn lower_binding_mode(lctx: &LoweringContext, b: &BindingMode) -> hir::BindingMode { - match *b { - BindingMode::ByRef(m) => hir::BindByRef(lower_mutability(lctx, m)), - BindingMode::ByValue(m) => hir::BindByValue(lower_mutability(lctx, m)), - } -} - -pub fn lower_unsafe_source(_lctx: &LoweringContext, u: UnsafeSource) -> hir::UnsafeSource { - match u { - CompilerGenerated => hir::CompilerGenerated, - UserProvided => hir::UserProvided, - } -} - -pub fn lower_impl_polarity(_lctx: &LoweringContext, i: ImplPolarity) -> hir::ImplPolarity { - match i { - ImplPolarity::Positive => hir::ImplPolarity::Positive, - ImplPolarity::Negative => hir::ImplPolarity::Negative, - } -} - -pub fn lower_trait_bound_modifier(_lctx: &LoweringContext, - f: TraitBoundModifier) - -> hir::TraitBoundModifier { - match f { - TraitBoundModifier::None => hir::TraitBoundModifier::None, - TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe, - } -} - -// Helper methods for building HIR. - -fn arm(pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm { - hir::Arm { - attrs: hir_vec![], - pats: pats, - guard: None, - body: expr, - } -} - -fn field(name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field { - hir::Field { - name: Spanned { - node: name, - span: span, - }, - span: span, - expr: expr, - } -} - -fn expr_break(lctx: &LoweringContext, span: Span, - attrs: ThinAttributes) -> P<hir::Expr> { - expr(lctx, span, hir::ExprBreak(None), attrs) -} - -fn expr_call(lctx: &LoweringContext, - span: Span, - e: P<hir::Expr>, - args: hir::HirVec<P<hir::Expr>>, - attrs: ThinAttributes) - -> P<hir::Expr> { - expr(lctx, span, hir::ExprCall(e, args), attrs) -} - -fn expr_ident(lctx: &LoweringContext, span: Span, id: hir::Ident, - attrs: ThinAttributes) -> P<hir::Expr> { - expr_path(lctx, path_ident(span, id), attrs) -} - -fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>, - attrs: ThinAttributes) -> P<hir::Expr> { - expr(lctx, span, hir::ExprAddrOf(hir::MutMutable, e), attrs) -} - -fn expr_path(lctx: &LoweringContext, path: hir::Path, - attrs: ThinAttributes) -> P<hir::Expr> { - expr(lctx, path.span, hir::ExprPath(None, path), attrs) -} - -fn expr_match(lctx: &LoweringContext, - span: Span, - arg: P<hir::Expr>, - arms: hir::HirVec<hir::Arm>, - source: hir::MatchSource, - attrs: ThinAttributes) - -> P<hir::Expr> { - expr(lctx, span, hir::ExprMatch(arg, arms, source), attrs) -} - -fn expr_block(lctx: &LoweringContext, b: P<hir::Block>, - attrs: ThinAttributes) -> P<hir::Expr> { - expr(lctx, b.span, hir::ExprBlock(b), attrs) -} - -fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: hir::HirVec<P<hir::Expr>>, - attrs: ThinAttributes) -> P<hir::Expr> { - expr(lctx, sp, hir::ExprTup(exprs), attrs) -} - -fn expr_struct(lctx: &LoweringContext, - sp: Span, - path: hir::Path, - fields: hir::HirVec<hir::Field>, - e: Option<P<hir::Expr>>, - attrs: ThinAttributes) -> P<hir::Expr> { - expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs) -} - -fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_, - attrs: ThinAttributes) -> P<hir::Expr> { - P(hir::Expr { - id: lctx.next_id(), - node: node, - span: span, - attrs: attrs, - }) -} - -fn stmt_let(lctx: &LoweringContext, - sp: Span, - mutbl: bool, - ident: hir::Ident, - ex: P<hir::Expr>, - attrs: ThinAttributes) - -> hir::Stmt { - let pat = if mutbl { - pat_ident_binding_mode(lctx, sp, ident, hir::BindByValue(hir::MutMutable)) - } else { - pat_ident(lctx, sp, ident) - }; - let local = P(hir::Local { - pat: pat, - ty: None, - init: Some(ex), - id: lctx.next_id(), - span: sp, - attrs: attrs, - }); - let decl = respan(sp, hir::DeclLocal(local)); - respan(sp, hir::StmtDecl(P(decl), lctx.next_id())) -} - -fn block_expr(lctx: &LoweringContext, expr: P<hir::Expr>) -> P<hir::Block> { - block_all(lctx, expr.span, hir::HirVec::new(), Some(expr)) -} - -fn block_all(lctx: &LoweringContext, - span: Span, - stmts: hir::HirVec<hir::Stmt>, - expr: Option<P<hir::Expr>>) - -> P<hir::Block> { - P(hir::Block { - stmts: stmts, - expr: expr, - id: lctx.next_id(), - rules: hir::DefaultBlock, - span: span, - }) -} - -fn pat_ok(lctx: &LoweringContext, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> { - let ok = std_path(lctx, &["result", "Result", "Ok"]); - let path = path_global(span, ok); - pat_enum(lctx, span, path, hir_vec![pat]) -} - -fn pat_err(lctx: &LoweringContext, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> { - let err = std_path(lctx, &["result", "Result", "Err"]); - let path = path_global(span, err); - pat_enum(lctx, span, path, hir_vec![pat]) -} - -fn pat_some(lctx: &LoweringContext, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> { - let some = std_path(lctx, &["option", "Option", "Some"]); - let path = path_global(span, some); - pat_enum(lctx, span, path, hir_vec![pat]) -} - -fn pat_none(lctx: &LoweringContext, span: Span) -> P<hir::Pat> { - let none = std_path(lctx, &["option", "Option", "None"]); - let path = path_global(span, none); - pat_enum(lctx, span, path, hir_vec![]) -} - -fn pat_enum(lctx: &LoweringContext, - span: Span, - path: hir::Path, - subpats: hir::HirVec<P<hir::Pat>>) - -> P<hir::Pat> { - let pt = if subpats.is_empty() { - hir::PatKind::Path(path) - } else { - hir::PatKind::TupleStruct(path, Some(subpats)) - }; - pat(lctx, span, pt) -} - -fn pat_ident(lctx: &LoweringContext, span: Span, ident: hir::Ident) -> P<hir::Pat> { - pat_ident_binding_mode(lctx, span, ident, hir::BindByValue(hir::MutImmutable)) -} - -fn pat_ident_binding_mode(lctx: &LoweringContext, - span: Span, - ident: hir::Ident, - bm: hir::BindingMode) - -> P<hir::Pat> { - let pat_ident = hir::PatKind::Ident(bm, - Spanned { - span: span, - node: ident, - }, - None); - pat(lctx, span, pat_ident) -} - -fn pat_wild(lctx: &LoweringContext, span: Span) -> P<hir::Pat> { - pat(lctx, span, hir::PatKind::Wild) -} - -fn pat(lctx: &LoweringContext, span: Span, pat: hir::PatKind) -> P<hir::Pat> { - P(hir::Pat { - id: lctx.next_id(), - node: pat, - span: span, - }) -} - -fn path_ident(span: Span, id: hir::Ident) -> hir::Path { - path(span, vec![id]) -} - -fn path(span: Span, strs: Vec<hir::Ident>) -> hir::Path { - path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) -} - -fn path_global(span: Span, strs: Vec<hir::Ident>) -> hir::Path { - path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) -} - -fn path_all(sp: Span, - global: bool, - mut idents: Vec<hir::Ident>, - lifetimes: hir::HirVec<hir::Lifetime>, - types: hir::HirVec<P<hir::Ty>>, - bindings: hir::HirVec<hir::TypeBinding>) - -> hir::Path { - let last_identifier = idents.pop().unwrap(); - let mut segments: Vec<hir::PathSegment> = idents.into_iter() - .map(|ident| { - hir::PathSegment { - identifier: ident, - parameters: hir::PathParameters::none(), - } - }) - .collect(); - segments.push(hir::PathSegment { - identifier: last_identifier, - parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - bindings: bindings, - }), - }); - hir::Path { - span: sp, - global: global, - segments: segments.into(), - } -} - -fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec<hir::Ident> { - let mut v = Vec::new(); - if let Some(s) = lctx.crate_root { - v.push(hir::Ident::from_name(token::intern(s))); - } - v.extend(components.iter().map(|s| hir::Ident::from_name(token::intern(s)))); - return v; -} - -// Given suffix ["b","c","d"], returns path `::std::b::c::d` when -// `fld.cx.use_std`, and `::core::b::c::d` otherwise. -fn core_path(lctx: &LoweringContext, span: Span, components: &[&str]) -> hir::Path { - let idents = std_path(lctx, components); - path_global(span, idents) -} - -fn signal_block_expr(lctx: &LoweringContext, - stmts: hir::HirVec<hir::Stmt>, - expr: P<hir::Expr>, - span: Span, - rule: hir::BlockCheckMode, - attrs: ThinAttributes) - -> P<hir::Expr> { - let id = lctx.next_id(); - expr_block(lctx, - P(hir::Block { - rules: rule, - span: span, - id: id, - stmts: stmts, - expr: Some(expr), - }), - attrs) -} - - - -#[cfg(test)] -mod test { - use super::*; - use syntax::ast::{self, NodeId, NodeIdAssigner}; - use syntax::{parse, codemap}; - use syntax::fold::Folder; - use std::cell::Cell; - - struct MockAssigner { - next_id: Cell<NodeId>, - } - - impl MockAssigner { - fn new() -> MockAssigner { - MockAssigner { next_id: Cell::new(0) } - } - } - - trait FakeExtCtxt { - fn call_site(&self) -> codemap::Span; - fn cfg(&self) -> ast::CrateConfig; - fn ident_of(&self, st: &str) -> ast::Ident; - fn name_of(&self, st: &str) -> ast::Name; - fn parse_sess(&self) -> &parse::ParseSess; - } - - impl FakeExtCtxt for parse::ParseSess { - fn call_site(&self) -> codemap::Span { - codemap::Span { - lo: codemap::BytePos(0), - hi: codemap::BytePos(0), - expn_id: codemap::NO_EXPANSION, - } - } - fn cfg(&self) -> ast::CrateConfig { - Vec::new() - } - fn ident_of(&self, st: &str) -> ast::Ident { - parse::token::str_to_ident(st) - } - fn name_of(&self, st: &str) -> ast::Name { - parse::token::intern(st) - } - fn parse_sess(&self) -> &parse::ParseSess { - self - } - } - - impl NodeIdAssigner for MockAssigner { - fn next_node_id(&self) -> NodeId { - let result = self.next_id.get(); - self.next_id.set(result + 1); - result - } - - fn peek_node_id(&self) -> NodeId { - self.next_id.get() - } - } - - impl Folder for MockAssigner { - fn new_id(&mut self, old_id: NodeId) -> NodeId { - assert_eq!(old_id, ast::DUMMY_NODE_ID); - self.next_node_id() - } - } - - #[test] - fn test_preserves_ids() { - let cx = parse::ParseSess::new(); - let mut assigner = MockAssigner::new(); - - let ast_if_let = quote_expr!(&cx, - if let Some(foo) = baz { - bar(foo); - }); - let ast_if_let = assigner.fold_expr(ast_if_let); - let ast_while_let = quote_expr!(&cx, - while let Some(foo) = baz { - bar(foo); - }); - let ast_while_let = assigner.fold_expr(ast_while_let); - let ast_for = quote_expr!(&cx, - for i in 0..10 { - for j in 0..10 { - foo(i, j); - } - }); - let ast_for = assigner.fold_expr(ast_for); - let ast_in = quote_expr!(&cx, in HEAP { foo() }); - let ast_in = assigner.fold_expr(ast_in); - - let lctx = LoweringContext::new(&assigner, None); - let hir1 = lower_expr(&lctx, &ast_if_let); - let hir2 = lower_expr(&lctx, &ast_if_let); - assert!(hir1 == hir2); - - let hir1 = lower_expr(&lctx, &ast_while_let); - let hir2 = lower_expr(&lctx, &ast_while_let); - assert!(hir1 == hir2); - - let hir1 = lower_expr(&lctx, &ast_for); - let hir2 = lower_expr(&lctx, &ast_for); - assert!(hir1 == hir2); - - let hir1 = lower_expr(&lctx, &ast_in); - let hir2 = lower_expr(&lctx, &ast_in); - assert!(hir1 == hir2); - } -} diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs deleted file mode 100644 index 3b8e6763de0..00000000000 --- a/src/librustc_front/print/pprust.rs +++ /dev/null @@ -1,2413 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub use self::AnnNode::*; - -use syntax::abi::Abi; -use syntax::ast; -use syntax::codemap::{self, CodeMap, BytePos, Spanned}; -use syntax::errors; -use syntax::parse::token::{self, BinOpToken}; -use syntax::parse::lexer::comments; -use syntax::parse; -use syntax::print::pp::{self, break_offset, word, space, hardbreak}; -use syntax::print::pp::{Breaks, eof}; -use syntax::print::pp::Breaks::{Consistent, Inconsistent}; -use syntax::print::pprust::{self as ast_pp, PrintState}; -use syntax::ptr::P; - -use hir; -use hir::{Crate, PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; - -use std::io::{self, Write, Read}; - -pub enum AnnNode<'a> { - NodeName(&'a ast::Name), - NodeBlock(&'a hir::Block), - NodeItem(&'a hir::Item), - NodeSubItem(ast::NodeId), - NodeExpr(&'a hir::Expr), - NodePat(&'a hir::Pat), -} - -pub trait PpAnn { - fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { - Ok(()) - } - fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { - Ok(()) - } -} - -#[derive(Copy, Clone)] -pub struct NoAnn; - -impl PpAnn for NoAnn {} - - -pub struct State<'a> { - krate: Option<&'a Crate>, - pub s: pp::Printer<'a>, - cm: Option<&'a CodeMap>, - comments: Option<Vec<comments::Comment>>, - literals: Option<Vec<comments::Literal>>, - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral, - boxes: Vec<pp::Breaks>, - ann: &'a (PpAnn + 'a), -} - -impl<'a> PrintState<'a> for State<'a> { - fn writer(&mut self) -> &mut pp::Printer<'a> { - &mut self.s - } - - fn boxes(&mut self) -> &mut Vec<pp::Breaks> { - &mut self.boxes - } - - fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> { - &mut self.comments - } - - fn cur_cmnt_and_lit(&mut self) -> &mut ast_pp::CurrentCommentAndLiteral { - &mut self.cur_cmnt_and_lit - } - - fn literals(&self) -> &Option<Vec<comments::Literal>> { - &self.literals - } -} - -pub fn rust_printer<'a>(writer: Box<Write + 'a>, krate: Option<&'a Crate>) -> State<'a> { - static NO_ANN: NoAnn = NoAnn; - rust_printer_annotated(writer, &NO_ANN, krate) -} - -pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>, - ann: &'a PpAnn, - krate: Option<&'a Crate>) - -> State<'a> { - State { - krate: krate, - s: pp::mk_printer(writer, default_columns), - cm: None, - comments: None, - literals: None, - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0, - }, - boxes: Vec::new(), - ann: ann, - } -} - -#[allow(non_upper_case_globals)] -pub const indent_unit: usize = 4; - -#[allow(non_upper_case_globals)] -pub const default_columns: usize = 78; - - -/// Requires you to pass an input filename and reader so that -/// it can scan the input text for comments and literals to -/// copy forward. -pub fn print_crate<'a>(cm: &'a CodeMap, - span_diagnostic: &errors::Handler, - krate: &hir::Crate, - filename: String, - input: &mut Read, - out: Box<Write + 'a>, - ann: &'a PpAnn, - is_expanded: bool) - -> io::Result<()> { - let mut s = State::new_from_input(cm, span_diagnostic, filename, input, - out, ann, is_expanded, Some(krate)); - - // When printing the AST, we sometimes need to inject `#[no_std]` here. - // Since you can't compile the HIR, it's not necessary. - - s.print_mod(&krate.module, &krate.attrs)?; - s.print_remaining_comments()?; - eof(&mut s.s) -} - -impl<'a> State<'a> { - pub fn new_from_input(cm: &'a CodeMap, - span_diagnostic: &errors::Handler, - filename: String, - input: &mut Read, - out: Box<Write + 'a>, - ann: &'a PpAnn, - is_expanded: bool, - krate: Option<&'a Crate>) - -> State<'a> { - let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic, - filename, - input); - - State::new(cm, - out, - ann, - Some(cmnts), - // If the code is post expansion, don't use the table of - // literals, since it doesn't correspond with the literals - // in the AST anymore. - if is_expanded { - None - } else { - Some(lits) - }, - krate) - } - - pub fn new(cm: &'a CodeMap, - out: Box<Write + 'a>, - ann: &'a PpAnn, - comments: Option<Vec<comments::Comment>>, - literals: Option<Vec<comments::Literal>>, - krate: Option<&'a Crate>) - -> State<'a> { - State { - krate: krate, - s: pp::mk_printer(out, default_columns), - cm: Some(cm), - comments: comments.clone(), - literals: literals.clone(), - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0, - }, - boxes: Vec::new(), - ann: ann, - } - } -} - -pub fn to_string<F>(f: F) -> String - where F: FnOnce(&mut State) -> io::Result<()> -{ - let mut wr = Vec::new(); - { - let mut printer = rust_printer(Box::new(&mut wr), None); - f(&mut printer).unwrap(); - eof(&mut printer.s).unwrap(); - } - String::from_utf8(wr).unwrap() -} - -pub fn binop_to_string(op: BinOpToken) -> &'static str { - match op { - token::Plus => "+", - token::Minus => "-", - token::Star => "*", - token::Slash => "/", - token::Percent => "%", - token::Caret => "^", - token::And => "&", - token::Or => "|", - token::Shl => "<<", - token::Shr => ">>", - } -} - -pub fn ty_to_string(ty: &hir::Ty) -> String { - to_string(|s| s.print_type(ty)) -} - -pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String { - to_string(|s| s.print_bounds("", bounds)) -} - -pub fn pat_to_string(pat: &hir::Pat) -> String { - to_string(|s| s.print_pat(pat)) -} - -pub fn arm_to_string(arm: &hir::Arm) -> String { - to_string(|s| s.print_arm(arm)) -} - -pub fn expr_to_string(e: &hir::Expr) -> String { - to_string(|s| s.print_expr(e)) -} - -pub fn lifetime_to_string(e: &hir::Lifetime) -> String { - to_string(|s| s.print_lifetime(e)) -} - -pub fn stmt_to_string(stmt: &hir::Stmt) -> String { - to_string(|s| s.print_stmt(stmt)) -} - -pub fn item_to_string(i: &hir::Item) -> String { - to_string(|s| s.print_item(i)) -} - -pub fn impl_item_to_string(i: &hir::ImplItem) -> String { - to_string(|s| s.print_impl_item(i)) -} - -pub fn trait_item_to_string(i: &hir::TraitItem) -> String { - to_string(|s| s.print_trait_item(i)) -} - -pub fn generics_to_string(generics: &hir::Generics) -> String { - to_string(|s| s.print_generics(generics)) -} - -pub fn where_clause_to_string(i: &hir::WhereClause) -> String { - to_string(|s| s.print_where_clause(i)) -} - -pub fn fn_block_to_string(p: &hir::FnDecl) -> String { - to_string(|s| s.print_fn_block_args(p)) -} - -pub fn path_to_string(p: &hir::Path) -> String { - to_string(|s| s.print_path(p, false, 0)) -} - -pub fn name_to_string(name: ast::Name) -> String { - to_string(|s| s.print_name(name)) -} - -pub fn fun_to_string(decl: &hir::FnDecl, - unsafety: hir::Unsafety, - constness: hir::Constness, - name: ast::Name, - opt_explicit_self: Option<&hir::ExplicitSelf_>, - generics: &hir::Generics) - -> String { - to_string(|s| { - s.head("")?; - s.print_fn(decl, - unsafety, - constness, - Abi::Rust, - Some(name), - generics, - opt_explicit_self, - hir::Inherited)?; - s.end()?; // Close the head box - s.end() // Close the outer box - }) -} - -pub fn block_to_string(blk: &hir::Block) -> String { - to_string(|s| { - // containing cbox, will be closed by print-block at } - s.cbox(indent_unit)?; - // head-ibox, will be closed by print-block after { - s.ibox(0)?; - s.print_block(blk) - }) -} - -pub fn explicit_self_to_string(explicit_self: &hir::ExplicitSelf_) -> String { - to_string(|s| s.print_explicit_self(explicit_self, hir::MutImmutable).map(|_| {})) -} - -pub fn variant_to_string(var: &hir::Variant) -> String { - to_string(|s| s.print_variant(var)) -} - -pub fn arg_to_string(arg: &hir::Arg) -> String { - to_string(|s| s.print_arg(arg, false)) -} - -pub fn visibility_qualified(vis: hir::Visibility, s: &str) -> String { - match vis { - hir::Public => format!("pub {}", s), - hir::Inherited => s.to_string(), - } -} - -fn needs_parentheses(expr: &hir::Expr) -> bool { - match expr.node { - hir::ExprAssign(..) | - hir::ExprBinary(..) | - hir::ExprClosure(..) | - hir::ExprAssignOp(..) | - hir::ExprCast(..) | - hir::ExprType(..) => true, - _ => false, - } -} - -impl<'a> State<'a> { - pub fn cbox(&mut self, u: usize) -> io::Result<()> { - self.boxes.push(pp::Breaks::Consistent); - pp::cbox(&mut self.s, u) - } - - pub fn nbsp(&mut self) -> io::Result<()> { - word(&mut self.s, " ") - } - - pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { - word(&mut self.s, w)?; - self.nbsp() - } - - pub fn head(&mut self, w: &str) -> io::Result<()> { - // outer-box is consistent - self.cbox(indent_unit)?; - // head-box is inconsistent - self.ibox(w.len() + 1)?; - // keyword that starts the head - if !w.is_empty() { - self.word_nbsp(w)?; - } - Ok(()) - } - - pub fn bopen(&mut self) -> io::Result<()> { - word(&mut self.s, "{")?; - self.end() // close the head-box - } - - pub fn bclose_(&mut self, span: codemap::Span, indented: usize) -> io::Result<()> { - self.bclose_maybe_open(span, indented, true) - } - pub fn bclose_maybe_open(&mut self, - span: codemap::Span, - indented: usize, - close_box: bool) - -> io::Result<()> { - self.maybe_print_comment(span.hi)?; - self.break_offset_if_not_bol(1, -(indented as isize))?; - word(&mut self.s, "}")?; - if close_box { - self.end()?; // close the outer-box - } - Ok(()) - } - pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> { - self.bclose_(span, indent_unit) - } - - pub fn in_cbox(&self) -> bool { - match self.boxes.last() { - Some(&last_box) => last_box == pp::Breaks::Consistent, - None => false, - } - } - pub fn space_if_not_bol(&mut self) -> io::Result<()> { - if !self.is_bol() { - space(&mut self.s)?; - } - Ok(()) - } - pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> { - if !self.is_bol() { - break_offset(&mut self.s, n, off) - } else { - if off != 0 && self.s.last_token().is_hardbreak_tok() { - // We do something pretty sketchy here: tuck the nonzero - // offset-adjustment we were going to deposit along with the - // break into the previous hardbreak. - self.s.replace_last_token(pp::hardbreak_tok_offset(off)); - } - Ok(()) - } - } - - // Synthesizes a comment that was not textually present in the original source - // file. - pub fn synth_comment(&mut self, text: String) -> io::Result<()> { - word(&mut self.s, "/*")?; - space(&mut self.s)?; - word(&mut self.s, &text[..])?; - space(&mut self.s)?; - word(&mut self.s, "*/") - } - - - pub fn commasep_cmnt<T, F, G>(&mut self, - b: Breaks, - elts: &[T], - mut op: F, - mut get_span: G) - -> io::Result<()> - where F: FnMut(&mut State, &T) -> io::Result<()>, - G: FnMut(&T) -> codemap::Span - { - self.rbox(0, b)?; - let len = elts.len(); - let mut i = 0; - for elt in elts { - self.maybe_print_comment(get_span(elt).hi)?; - op(self, elt)?; - i += 1; - if i < len { - word(&mut self.s, ",")?; - self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))?; - self.space_if_not_bol()?; - } - } - self.end() - } - - pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<hir::Expr>]) -> io::Result<()> { - self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span) - } - - pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> { - self.print_inner_attributes(attrs)?; - for item_id in &_mod.item_ids { - self.print_item_id(item_id)?; - } - Ok(()) - } - - pub fn print_foreign_mod(&mut self, - nmod: &hir::ForeignMod, - attrs: &[ast::Attribute]) - -> io::Result<()> { - self.print_inner_attributes(attrs)?; - for item in &nmod.items { - self.print_foreign_item(item)?; - } - Ok(()) - } - - pub fn print_opt_lifetime(&mut self, lifetime: &Option<hir::Lifetime>) -> io::Result<()> { - if let Some(l) = *lifetime { - self.print_lifetime(&l)?; - self.nbsp()?; - } - Ok(()) - } - - pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> { - self.maybe_print_comment(ty.span.lo)?; - self.ibox(0)?; - match ty.node { - hir::TyVec(ref ty) => { - word(&mut self.s, "[")?; - self.print_type(&ty)?; - word(&mut self.s, "]")?; - } - hir::TyPtr(ref mt) => { - word(&mut self.s, "*")?; - match mt.mutbl { - hir::MutMutable => self.word_nbsp("mut")?, - hir::MutImmutable => self.word_nbsp("const")?, - } - self.print_type(&mt.ty)?; - } - hir::TyRptr(ref lifetime, ref mt) => { - word(&mut self.s, "&")?; - self.print_opt_lifetime(lifetime)?; - self.print_mt(mt)?; - } - hir::TyTup(ref elts) => { - self.popen()?; - self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))?; - if elts.len() == 1 { - word(&mut self.s, ",")?; - } - self.pclose()?; - } - hir::TyBareFn(ref f) => { - let generics = hir::Generics { - lifetimes: f.lifetimes.clone(), - ty_params: hir::HirVec::new(), - where_clause: hir::WhereClause { - id: ast::DUMMY_NODE_ID, - predicates: hir::HirVec::new(), - }, - }; - self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics, None)?; - } - hir::TyPath(None, ref path) => { - self.print_path(path, false, 0)?; - } - hir::TyPath(Some(ref qself), ref path) => { - self.print_qpath(path, qself, false)? - } - hir::TyObjectSum(ref ty, ref bounds) => { - self.print_type(&ty)?; - self.print_bounds("+", &bounds[..])?; - } - hir::TyPolyTraitRef(ref bounds) => { - self.print_bounds("", &bounds[..])?; - } - hir::TyFixedLengthVec(ref ty, ref v) => { - word(&mut self.s, "[")?; - self.print_type(&ty)?; - word(&mut self.s, "; ")?; - self.print_expr(&v)?; - word(&mut self.s, "]")?; - } - hir::TyTypeof(ref e) => { - word(&mut self.s, "typeof(")?; - self.print_expr(&e)?; - word(&mut self.s, ")")?; - } - hir::TyInfer => { - word(&mut self.s, "_")?; - } - } - self.end() - } - - pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()> { - self.hardbreak_if_not_bol()?; - self.maybe_print_comment(item.span.lo)?; - self.print_outer_attributes(&item.attrs)?; - match item.node { - hir::ForeignItemFn(ref decl, ref generics) => { - self.head("")?; - self.print_fn(decl, - hir::Unsafety::Normal, - hir::Constness::NotConst, - Abi::Rust, - Some(item.name), - generics, - None, - item.vis)?; - self.end()?; // end head-ibox - word(&mut self.s, ";")?; - self.end() // end the outer fn box - } - hir::ForeignItemStatic(ref t, m) => { - self.head(&visibility_qualified(item.vis, "static"))?; - if m { - self.word_space("mut")?; - } - self.print_name(item.name)?; - self.word_space(":")?; - self.print_type(&t)?; - word(&mut self.s, ";")?; - self.end()?; // end the head-ibox - self.end() // end the outer cbox - } - } - } - - fn print_associated_const(&mut self, - name: ast::Name, - ty: &hir::Ty, - default: Option<&hir::Expr>, - vis: hir::Visibility) - -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; - self.word_space("const")?; - self.print_name(name)?; - self.word_space(":")?; - self.print_type(ty)?; - if let Some(expr) = default { - space(&mut self.s)?; - self.word_space("=")?; - self.print_expr(expr)?; - } - word(&mut self.s, ";") - } - - fn print_associated_type(&mut self, - name: ast::Name, - bounds: Option<&hir::TyParamBounds>, - ty: Option<&hir::Ty>) - -> io::Result<()> { - self.word_space("type")?; - self.print_name(name)?; - if let Some(bounds) = bounds { - self.print_bounds(":", bounds)?; - } - if let Some(ty) = ty { - space(&mut self.s)?; - self.word_space("=")?; - self.print_type(ty)?; - } - word(&mut self.s, ";") - } - - pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> { - if let Some(krate) = self.krate { - // skip nested items if krate context was not provided - let item = &krate.items[&item_id.id]; - self.print_item(item) - } else { - Ok(()) - } - } - - /// Pretty-print an item - pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> { - self.hardbreak_if_not_bol()?; - self.maybe_print_comment(item.span.lo)?; - self.print_outer_attributes(&item.attrs)?; - self.ann.pre(self, NodeItem(item))?; - match item.node { - hir::ItemExternCrate(ref optional_path) => { - self.head(&visibility_qualified(item.vis, "extern crate"))?; - if let Some(p) = *optional_path { - let val = p.as_str(); - if val.contains("-") { - self.print_string(&val, ast::StrStyle::Cooked)?; - } else { - self.print_name(p)?; - } - space(&mut self.s)?; - word(&mut self.s, "as")?; - space(&mut self.s)?; - } - self.print_name(item.name)?; - word(&mut self.s, ";")?; - self.end()?; // end inner head-block - self.end()?; // end outer head-block - } - hir::ItemUse(ref vp) => { - self.head(&visibility_qualified(item.vis, "use"))?; - self.print_view_path(&vp)?; - word(&mut self.s, ";")?; - self.end()?; // end inner head-block - self.end()?; // end outer head-block - } - hir::ItemStatic(ref ty, m, ref expr) => { - self.head(&visibility_qualified(item.vis, "static"))?; - if m == hir::MutMutable { - self.word_space("mut")?; - } - self.print_name(item.name)?; - self.word_space(":")?; - self.print_type(&ty)?; - space(&mut self.s)?; - self.end()?; // end the head-ibox - - self.word_space("=")?; - self.print_expr(&expr)?; - word(&mut self.s, ";")?; - self.end()?; // end the outer cbox - } - hir::ItemConst(ref ty, ref expr) => { - self.head(&visibility_qualified(item.vis, "const"))?; - self.print_name(item.name)?; - self.word_space(":")?; - self.print_type(&ty)?; - space(&mut self.s)?; - self.end()?; // end the head-ibox - - self.word_space("=")?; - self.print_expr(&expr)?; - word(&mut self.s, ";")?; - self.end()?; // end the outer cbox - } - hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => { - self.head("")?; - self.print_fn(decl, - unsafety, - constness, - abi, - Some(item.name), - typarams, - None, - item.vis)?; - word(&mut self.s, " ")?; - self.print_block_with_attrs(&body, &item.attrs)?; - } - hir::ItemMod(ref _mod) => { - self.head(&visibility_qualified(item.vis, "mod"))?; - self.print_name(item.name)?; - self.nbsp()?; - self.bopen()?; - self.print_mod(_mod, &item.attrs)?; - self.bclose(item.span)?; - } - hir::ItemForeignMod(ref nmod) => { - self.head("extern")?; - self.word_nbsp(&nmod.abi.to_string())?; - self.bopen()?; - self.print_foreign_mod(nmod, &item.attrs)?; - self.bclose(item.span)?; - } - hir::ItemTy(ref ty, ref params) => { - self.ibox(indent_unit)?; - self.ibox(0)?; - self.word_nbsp(&visibility_qualified(item.vis, "type"))?; - self.print_name(item.name)?; - self.print_generics(params)?; - self.end()?; // end the inner ibox - - self.print_where_clause(¶ms.where_clause)?; - space(&mut self.s)?; - self.word_space("=")?; - self.print_type(&ty)?; - word(&mut self.s, ";")?; - self.end()?; // end the outer ibox - } - hir::ItemEnum(ref enum_definition, ref params) => { - self.print_enum_def(enum_definition, params, item.name, item.span, item.vis)?; - } - hir::ItemStruct(ref struct_def, ref generics) => { - self.head(&visibility_qualified(item.vis, "struct"))?; - self.print_struct(struct_def, generics, item.name, item.span, true)?; - } - - hir::ItemDefaultImpl(unsafety, ref trait_ref) => { - self.head("")?; - self.print_visibility(item.vis)?; - self.print_unsafety(unsafety)?; - self.word_nbsp("impl")?; - self.print_trait_ref(trait_ref)?; - space(&mut self.s)?; - self.word_space("for")?; - self.word_space("..")?; - self.bopen()?; - self.bclose(item.span)?; - } - hir::ItemImpl(unsafety, - polarity, - ref generics, - ref opt_trait, - ref ty, - ref impl_items) => { - self.head("")?; - self.print_visibility(item.vis)?; - self.print_unsafety(unsafety)?; - self.word_nbsp("impl")?; - - if generics.is_parameterized() { - self.print_generics(generics)?; - space(&mut self.s)?; - } - - match polarity { - hir::ImplPolarity::Negative => { - word(&mut self.s, "!")?; - } - _ => {} - } - - match opt_trait { - &Some(ref t) => { - self.print_trait_ref(t)?; - space(&mut self.s)?; - self.word_space("for")?; - } - &None => {} - } - - self.print_type(&ty)?; - self.print_where_clause(&generics.where_clause)?; - - space(&mut self.s)?; - self.bopen()?; - self.print_inner_attributes(&item.attrs)?; - for impl_item in impl_items { - self.print_impl_item(impl_item)?; - } - self.bclose(item.span)?; - } - hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => { - self.head("")?; - self.print_visibility(item.vis)?; - self.print_unsafety(unsafety)?; - self.word_nbsp("trait")?; - self.print_name(item.name)?; - self.print_generics(generics)?; - let mut real_bounds = Vec::with_capacity(bounds.len()); - for b in bounds.iter() { - if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - space(&mut self.s)?; - self.word_space("for ?")?; - self.print_trait_ref(&ptr.trait_ref)?; - } else { - real_bounds.push(b.clone()); - } - } - self.print_bounds(":", &real_bounds[..])?; - self.print_where_clause(&generics.where_clause)?; - word(&mut self.s, " ")?; - self.bopen()?; - for trait_item in trait_items { - self.print_trait_item(trait_item)?; - } - self.bclose(item.span)?; - } - } - self.ann.post(self, NodeItem(item)) - } - - fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> { - self.print_path(&t.path, false, 0) - } - - fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> { - if !lifetimes.is_empty() { - word(&mut self.s, "for<")?; - let mut comma = false; - for lifetime_def in lifetimes { - if comma { - self.word_space(",")? - } - self.print_lifetime_def(lifetime_def)?; - comma = true; - } - word(&mut self.s, ">")?; - } - Ok(()) - } - - fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> { - self.print_formal_lifetime_list(&t.bound_lifetimes)?; - self.print_trait_ref(&t.trait_ref) - } - - pub fn print_enum_def(&mut self, - enum_definition: &hir::EnumDef, - generics: &hir::Generics, - name: ast::Name, - span: codemap::Span, - visibility: hir::Visibility) - -> io::Result<()> { - self.head(&visibility_qualified(visibility, "enum"))?; - self.print_name(name)?; - self.print_generics(generics)?; - self.print_where_clause(&generics.where_clause)?; - space(&mut self.s)?; - self.print_variants(&enum_definition.variants, span) - } - - pub fn print_variants(&mut self, - variants: &[hir::Variant], - span: codemap::Span) - -> io::Result<()> { - self.bopen()?; - for v in variants { - self.space_if_not_bol()?; - self.maybe_print_comment(v.span.lo)?; - self.print_outer_attributes(&v.node.attrs)?; - self.ibox(indent_unit)?; - self.print_variant(v)?; - word(&mut self.s, ",")?; - self.end()?; - self.maybe_print_trailing_comment(v.span, None)?; - } - self.bclose(span) - } - - pub fn print_visibility(&mut self, vis: hir::Visibility) -> io::Result<()> { - match vis { - hir::Public => self.word_nbsp("pub"), - hir::Inherited => Ok(()), - } - } - - pub fn print_struct(&mut self, - struct_def: &hir::VariantData, - generics: &hir::Generics, - name: ast::Name, - span: codemap::Span, - print_finalizer: bool) - -> io::Result<()> { - self.print_name(name)?; - self.print_generics(generics)?; - if !struct_def.is_struct() { - if struct_def.is_tuple() { - self.popen()?; - self.commasep(Inconsistent, struct_def.fields(), |s, field| { - s.print_visibility(field.vis)?; - s.maybe_print_comment(field.span.lo)?; - s.print_type(&field.ty) - })?; - self.pclose()?; - } - self.print_where_clause(&generics.where_clause)?; - if print_finalizer { - word(&mut self.s, ";")?; - } - self.end()?; - self.end() // close the outer-box - } else { - self.print_where_clause(&generics.where_clause)?; - self.nbsp()?; - self.bopen()?; - self.hardbreak_if_not_bol()?; - - for field in struct_def.fields() { - self.hardbreak_if_not_bol()?; - self.maybe_print_comment(field.span.lo)?; - self.print_outer_attributes(&field.attrs)?; - self.print_visibility(field.vis)?; - self.print_name(field.name)?; - self.word_nbsp(":")?; - self.print_type(&field.ty)?; - word(&mut self.s, ",")?; - } - - self.bclose(span) - } - } - - pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> { - self.head("")?; - let generics = ::util::empty_generics(); - self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; - match v.node.disr_expr { - Some(ref d) => { - space(&mut self.s)?; - self.word_space("=")?; - self.print_expr(&d) - } - _ => Ok(()), - } - } - pub fn print_method_sig(&mut self, - name: ast::Name, - m: &hir::MethodSig, - vis: hir::Visibility) - -> io::Result<()> { - self.print_fn(&m.decl, - m.unsafety, - m.constness, - m.abi, - Some(name), - &m.generics, - Some(&m.explicit_self.node), - vis) - } - - pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> { - self.ann.pre(self, NodeSubItem(ti.id))?; - self.hardbreak_if_not_bol()?; - self.maybe_print_comment(ti.span.lo)?; - self.print_outer_attributes(&ti.attrs)?; - match ti.node { - hir::ConstTraitItem(ref ty, ref default) => { - self.print_associated_const(ti.name, - &ty, - default.as_ref().map(|expr| &**expr), - hir::Inherited)?; - } - hir::MethodTraitItem(ref sig, ref body) => { - if body.is_some() { - self.head("")?; - } - self.print_method_sig(ti.name, sig, hir::Inherited)?; - if let Some(ref body) = *body { - self.nbsp()?; - self.print_block_with_attrs(body, &ti.attrs)?; - } else { - word(&mut self.s, ";")?; - } - } - hir::TypeTraitItem(ref bounds, ref default) => { - self.print_associated_type(ti.name, - Some(bounds), - default.as_ref().map(|ty| &**ty))?; - } - } - self.ann.post(self, NodeSubItem(ti.id)) - } - - pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> { - self.ann.pre(self, NodeSubItem(ii.id))?; - self.hardbreak_if_not_bol()?; - self.maybe_print_comment(ii.span.lo)?; - self.print_outer_attributes(&ii.attrs)?; - - if let hir::Defaultness::Default = ii.defaultness { - self.word_nbsp("default")?; - } - - match ii.node { - hir::ImplItemKind::Const(ref ty, ref expr) => { - self.print_associated_const(ii.name, &ty, Some(&expr), ii.vis)?; - } - hir::ImplItemKind::Method(ref sig, ref body) => { - self.head("")?; - self.print_method_sig(ii.name, sig, ii.vis)?; - self.nbsp()?; - self.print_block_with_attrs(body, &ii.attrs)?; - } - hir::ImplItemKind::Type(ref ty) => { - self.print_associated_type(ii.name, None, Some(ty))?; - } - } - self.ann.post(self, NodeSubItem(ii.id)) - } - - pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> { - self.maybe_print_comment(st.span.lo)?; - match st.node { - hir::StmtDecl(ref decl, _) => { - self.print_decl(&decl)?; - } - hir::StmtExpr(ref expr, _) => { - self.space_if_not_bol()?; - self.print_expr(&expr)?; - } - hir::StmtSemi(ref expr, _) => { - self.space_if_not_bol()?; - self.print_expr(&expr)?; - word(&mut self.s, ";")?; - } - } - if stmt_ends_with_semi(&st.node) { - word(&mut self.s, ";")?; - } - self.maybe_print_trailing_comment(st.span, None) - } - - pub fn print_block(&mut self, blk: &hir::Block) -> io::Result<()> { - self.print_block_with_attrs(blk, &[]) - } - - pub fn print_block_unclosed(&mut self, blk: &hir::Block) -> io::Result<()> { - self.print_block_unclosed_indent(blk, indent_unit) - } - - pub fn print_block_unclosed_indent(&mut self, - blk: &hir::Block, - indented: usize) - -> io::Result<()> { - self.print_block_maybe_unclosed(blk, indented, &[], false) - } - - pub fn print_block_with_attrs(&mut self, - blk: &hir::Block, - attrs: &[ast::Attribute]) - -> io::Result<()> { - self.print_block_maybe_unclosed(blk, indent_unit, attrs, true) - } - - pub fn print_block_maybe_unclosed(&mut self, - blk: &hir::Block, - indented: usize, - attrs: &[ast::Attribute], - close_box: bool) - -> io::Result<()> { - match blk.rules { - hir::UnsafeBlock(..) => self.word_space("unsafe")?, - hir::PushUnsafeBlock(..) => self.word_space("push_unsafe")?, - hir::PopUnsafeBlock(..) => self.word_space("pop_unsafe")?, - hir::PushUnstableBlock => self.word_space("push_unstable")?, - hir::PopUnstableBlock => self.word_space("pop_unstable")?, - hir::DefaultBlock => (), - } - self.maybe_print_comment(blk.span.lo)?; - self.ann.pre(self, NodeBlock(blk))?; - self.bopen()?; - - self.print_inner_attributes(attrs)?; - - for st in &blk.stmts { - self.print_stmt(st)?; - } - match blk.expr { - Some(ref expr) => { - self.space_if_not_bol()?; - self.print_expr(&expr)?; - self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))?; - } - _ => (), - } - self.bclose_maybe_open(blk.span, indented, close_box)?; - self.ann.post(self, NodeBlock(blk)) - } - - fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> { - match els { - Some(_else) => { - match _else.node { - // "another else-if" - hir::ExprIf(ref i, ref then, ref e) => { - self.cbox(indent_unit - 1)?; - self.ibox(0)?; - word(&mut self.s, " else if ")?; - self.print_expr(&i)?; - space(&mut self.s)?; - self.print_block(&then)?; - self.print_else(e.as_ref().map(|e| &**e)) - } - // "final else" - hir::ExprBlock(ref b) => { - self.cbox(indent_unit - 1)?; - self.ibox(0)?; - word(&mut self.s, " else ")?; - self.print_block(&b) - } - // BLEAH, constraints would be great here - _ => { - panic!("print_if saw if with weird alternative"); - } - } - } - _ => Ok(()), - } - } - - pub fn print_if(&mut self, - test: &hir::Expr, - blk: &hir::Block, - elseopt: Option<&hir::Expr>) - -> io::Result<()> { - self.head("if")?; - self.print_expr(test)?; - space(&mut self.s)?; - self.print_block(blk)?; - self.print_else(elseopt) - } - - pub fn print_if_let(&mut self, - pat: &hir::Pat, - expr: &hir::Expr, - blk: &hir::Block, - elseopt: Option<&hir::Expr>) - -> io::Result<()> { - self.head("if let")?; - self.print_pat(pat)?; - space(&mut self.s)?; - self.word_space("=")?; - self.print_expr(expr)?; - space(&mut self.s)?; - self.print_block(blk)?; - self.print_else(elseopt) - } - - - fn print_call_post(&mut self, args: &[P<hir::Expr>]) -> io::Result<()> { - self.popen()?; - self.commasep_exprs(Inconsistent, args)?; - self.pclose() - } - - pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr) -> io::Result<()> { - let needs_par = needs_parentheses(expr); - if needs_par { - self.popen()?; - } - self.print_expr(expr)?; - if needs_par { - self.pclose()?; - } - Ok(()) - } - - fn print_expr_vec(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> { - self.ibox(indent_unit)?; - word(&mut self.s, "[")?; - self.commasep_exprs(Inconsistent, &exprs[..])?; - word(&mut self.s, "]")?; - self.end() - } - - fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> { - self.ibox(indent_unit)?; - word(&mut self.s, "[")?; - self.print_expr(element)?; - self.word_space(";")?; - self.print_expr(count)?; - word(&mut self.s, "]")?; - self.end() - } - - fn print_expr_struct(&mut self, - path: &hir::Path, - fields: &[hir::Field], - wth: &Option<P<hir::Expr>>) - -> io::Result<()> { - self.print_path(path, true, 0)?; - word(&mut self.s, "{")?; - self.commasep_cmnt(Consistent, - &fields[..], - |s, field| { - s.ibox(indent_unit)?; - s.print_name(field.name.node)?; - s.word_space(":")?; - s.print_expr(&field.expr)?; - s.end() - }, - |f| f.span)?; - match *wth { - Some(ref expr) => { - self.ibox(indent_unit)?; - if !fields.is_empty() { - word(&mut self.s, ",")?; - space(&mut self.s)?; - } - word(&mut self.s, "..")?; - self.print_expr(&expr)?; - self.end()?; - } - _ => if !fields.is_empty() { - word(&mut self.s, ",")? - }, - } - word(&mut self.s, "}")?; - Ok(()) - } - - fn print_expr_tup(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> { - self.popen()?; - self.commasep_exprs(Inconsistent, &exprs[..])?; - if exprs.len() == 1 { - word(&mut self.s, ",")?; - } - self.pclose() - } - - fn print_expr_call(&mut self, func: &hir::Expr, args: &[P<hir::Expr>]) -> io::Result<()> { - self.print_expr_maybe_paren(func)?; - self.print_call_post(args) - } - - fn print_expr_method_call(&mut self, - name: Spanned<ast::Name>, - tys: &[P<hir::Ty>], - args: &[P<hir::Expr>]) - -> io::Result<()> { - let base_args = &args[1..]; - self.print_expr(&args[0])?; - word(&mut self.s, ".")?; - self.print_name(name.node)?; - if !tys.is_empty() { - word(&mut self.s, "::<")?; - self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?; - word(&mut self.s, ">")?; - } - self.print_call_post(base_args) - } - - fn print_expr_binary(&mut self, - op: hir::BinOp, - lhs: &hir::Expr, - rhs: &hir::Expr) - -> io::Result<()> { - self.print_expr(lhs)?; - space(&mut self.s)?; - self.word_space(::util::binop_to_string(op.node))?; - self.print_expr(rhs) - } - - fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> { - word(&mut self.s, ::util::unop_to_string(op))?; - self.print_expr_maybe_paren(expr) - } - - fn print_expr_addr_of(&mut self, - mutability: hir::Mutability, - expr: &hir::Expr) - -> io::Result<()> { - word(&mut self.s, "&")?; - self.print_mutability(mutability)?; - self.print_expr_maybe_paren(expr) - } - - pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> { - self.maybe_print_comment(expr.span.lo)?; - self.ibox(indent_unit)?; - self.ann.pre(self, NodeExpr(expr))?; - match expr.node { - hir::ExprBox(ref expr) => { - self.word_space("box")?; - self.print_expr(expr)?; - } - hir::ExprVec(ref exprs) => { - self.print_expr_vec(&exprs[..])?; - } - hir::ExprRepeat(ref element, ref count) => { - self.print_expr_repeat(&element, &count)?; - } - hir::ExprStruct(ref path, ref fields, ref wth) => { - self.print_expr_struct(path, &fields[..], wth)?; - } - hir::ExprTup(ref exprs) => { - self.print_expr_tup(&exprs[..])?; - } - hir::ExprCall(ref func, ref args) => { - self.print_expr_call(&func, &args[..])?; - } - hir::ExprMethodCall(name, ref tys, ref args) => { - self.print_expr_method_call(name, &tys[..], &args[..])?; - } - hir::ExprBinary(op, ref lhs, ref rhs) => { - self.print_expr_binary(op, &lhs, &rhs)?; - } - hir::ExprUnary(op, ref expr) => { - self.print_expr_unary(op, &expr)?; - } - hir::ExprAddrOf(m, ref expr) => { - self.print_expr_addr_of(m, &expr)?; - } - hir::ExprLit(ref lit) => { - self.print_literal(&lit)?; - } - hir::ExprCast(ref expr, ref ty) => { - self.print_expr(&expr)?; - space(&mut self.s)?; - self.word_space("as")?; - self.print_type(&ty)?; - } - hir::ExprType(ref expr, ref ty) => { - self.print_expr(&expr)?; - self.word_space(":")?; - self.print_type(&ty)?; - } - hir::ExprIf(ref test, ref blk, ref elseopt) => { - self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?; - } - hir::ExprWhile(ref test, ref blk, opt_ident) => { - if let Some(ident) = opt_ident { - self.print_name(ident.name)?; - self.word_space(":")?; - } - self.head("while")?; - self.print_expr(&test)?; - space(&mut self.s)?; - self.print_block(&blk)?; - } - hir::ExprLoop(ref blk, opt_ident) => { - if let Some(ident) = opt_ident { - self.print_name(ident.name)?; - self.word_space(":")?; - } - self.head("loop")?; - space(&mut self.s)?; - self.print_block(&blk)?; - } - hir::ExprMatch(ref expr, ref arms, _) => { - self.cbox(indent_unit)?; - self.ibox(4)?; - self.word_nbsp("match")?; - self.print_expr(&expr)?; - space(&mut self.s)?; - self.bopen()?; - for arm in arms { - self.print_arm(arm)?; - } - self.bclose_(expr.span, indent_unit)?; - } - hir::ExprClosure(capture_clause, ref decl, ref body) => { - self.print_capture_clause(capture_clause)?; - - self.print_fn_block_args(&decl)?; - space(&mut self.s)?; - - let default_return = match decl.output { - hir::DefaultReturn(..) => true, - _ => false, - }; - - if !default_return || !body.stmts.is_empty() || body.expr.is_none() { - self.print_block_unclosed(&body)?; - } else { - // we extract the block, so as not to create another set of boxes - match body.expr.as_ref().unwrap().node { - hir::ExprBlock(ref blk) => { - self.print_block_unclosed(&blk)?; - } - _ => { - // this is a bare expression - self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())?; - self.end()?; // need to close a box - } - } - } - // a box will be closed by print_expr, but we didn't want an overall - // wrapper so we closed the corresponding opening. so create an - // empty box to satisfy the close. - self.ibox(0)?; - } - hir::ExprBlock(ref blk) => { - // containing cbox, will be closed by print-block at } - self.cbox(indent_unit)?; - // head-box, will be closed by print-block after { - self.ibox(0)?; - self.print_block(&blk)?; - } - hir::ExprAssign(ref lhs, ref rhs) => { - self.print_expr(&lhs)?; - space(&mut self.s)?; - self.word_space("=")?; - self.print_expr(&rhs)?; - } - hir::ExprAssignOp(op, ref lhs, ref rhs) => { - self.print_expr(&lhs)?; - space(&mut self.s)?; - word(&mut self.s, ::util::binop_to_string(op.node))?; - self.word_space("=")?; - self.print_expr(&rhs)?; - } - hir::ExprField(ref expr, name) => { - self.print_expr(&expr)?; - word(&mut self.s, ".")?; - self.print_name(name.node)?; - } - hir::ExprTupField(ref expr, id) => { - self.print_expr(&expr)?; - word(&mut self.s, ".")?; - self.print_usize(id.node)?; - } - hir::ExprIndex(ref expr, ref index) => { - self.print_expr(&expr)?; - word(&mut self.s, "[")?; - self.print_expr(&index)?; - word(&mut self.s, "]")?; - } - hir::ExprPath(None, ref path) => { - self.print_path(path, true, 0)? - } - hir::ExprPath(Some(ref qself), ref path) => { - self.print_qpath(path, qself, true)? - } - hir::ExprBreak(opt_ident) => { - word(&mut self.s, "break")?; - space(&mut self.s)?; - if let Some(ident) = opt_ident { - self.print_name(ident.node.name)?; - space(&mut self.s)?; - } - } - hir::ExprAgain(opt_ident) => { - word(&mut self.s, "continue")?; - space(&mut self.s)?; - if let Some(ident) = opt_ident { - self.print_name(ident.node.name)?; - space(&mut self.s)? - } - } - hir::ExprRet(ref result) => { - word(&mut self.s, "return")?; - match *result { - Some(ref expr) => { - word(&mut self.s, " ")?; - self.print_expr(&expr)?; - } - _ => (), - } - } - hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => { - word(&mut self.s, "asm!")?; - self.popen()?; - self.print_string(&a.asm, a.asm_str_style)?; - self.word_space(":")?; - - let mut out_idx = 0; - self.commasep(Inconsistent, &a.outputs, |s, out| { - match out.constraint.slice_shift_char() { - Some(('=', operand)) if out.is_rw => { - s.print_string(&format!("+{}", operand), ast::StrStyle::Cooked)? - } - _ => s.print_string(&out.constraint, ast::StrStyle::Cooked)?, - } - s.popen()?; - s.print_expr(&outputs[out_idx])?; - s.pclose()?; - out_idx += 1; - Ok(()) - })?; - space(&mut self.s)?; - self.word_space(":")?; - - let mut in_idx = 0; - self.commasep(Inconsistent, &a.inputs, |s, co| { - s.print_string(&co, ast::StrStyle::Cooked)?; - s.popen()?; - s.print_expr(&inputs[in_idx])?; - s.pclose()?; - in_idx += 1; - Ok(()) - })?; - space(&mut self.s)?; - self.word_space(":")?; - - self.commasep(Inconsistent, &a.clobbers, |s, co| { - s.print_string(&co, ast::StrStyle::Cooked)?; - Ok(()) - })?; - - let mut options = vec![]; - if a.volatile { - options.push("volatile"); - } - if a.alignstack { - options.push("alignstack"); - } - if a.dialect == ast::AsmDialect::Intel { - options.push("intel"); - } - - if !options.is_empty() { - space(&mut self.s)?; - self.word_space(":")?; - self.commasep(Inconsistent, &options, |s, &co| { - s.print_string(co, ast::StrStyle::Cooked)?; - Ok(()) - })?; - } - - self.pclose()?; - } - } - self.ann.post(self, NodeExpr(expr))?; - self.end() - } - - pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> { - self.print_pat(&loc.pat)?; - if let Some(ref ty) = loc.ty { - self.word_space(":")?; - self.print_type(&ty)?; - } - Ok(()) - } - - pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> { - self.maybe_print_comment(decl.span.lo)?; - match decl.node { - hir::DeclLocal(ref loc) => { - self.space_if_not_bol()?; - self.ibox(indent_unit)?; - self.word_nbsp("let")?; - - self.ibox(indent_unit)?; - self.print_local_decl(&loc)?; - self.end()?; - if let Some(ref init) = loc.init { - self.nbsp()?; - self.word_space("=")?; - self.print_expr(&init)?; - } - self.end() - } - hir::DeclItem(ref item) => { - self.print_item_id(item) - } - } - } - - pub fn print_usize(&mut self, i: usize) -> io::Result<()> { - word(&mut self.s, &i.to_string()) - } - - pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { - word(&mut self.s, &name.as_str())?; - self.ann.post(self, NodeName(&name)) - } - - pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> { - self.print_local_decl(loc)?; - space(&mut self.s)?; - self.word_space("in")?; - self.print_expr(coll) - } - - fn print_path(&mut self, - path: &hir::Path, - colons_before_params: bool, - depth: usize) - -> io::Result<()> { - self.maybe_print_comment(path.span.lo)?; - - let mut first = !path.global; - for segment in &path.segments[..path.segments.len() - depth] { - if first { - first = false - } else { - word(&mut self.s, "::")? - } - - self.print_name(segment.identifier.name)?; - - self.print_path_parameters(&segment.parameters, colons_before_params)?; - } - - Ok(()) - } - - fn print_qpath(&mut self, - path: &hir::Path, - qself: &hir::QSelf, - colons_before_params: bool) - -> io::Result<()> { - word(&mut self.s, "<")?; - self.print_type(&qself.ty)?; - if qself.position > 0 { - space(&mut self.s)?; - self.word_space("as")?; - let depth = path.segments.len() - qself.position; - self.print_path(&path, false, depth)?; - } - word(&mut self.s, ">")?; - word(&mut self.s, "::")?; - let item_segment = path.segments.last().unwrap(); - self.print_name(item_segment.identifier.name)?; - self.print_path_parameters(&item_segment.parameters, colons_before_params) - } - - fn print_path_parameters(&mut self, - parameters: &hir::PathParameters, - colons_before_params: bool) - -> io::Result<()> { - if parameters.is_empty() { - return Ok(()); - } - - if colons_before_params { - word(&mut self.s, "::")? - } - - match *parameters { - hir::AngleBracketedParameters(ref data) => { - word(&mut self.s, "<")?; - - let mut comma = false; - for lifetime in &data.lifetimes { - if comma { - self.word_space(",")? - } - self.print_lifetime(lifetime)?; - comma = true; - } - - if !data.types.is_empty() { - if comma { - self.word_space(",")? - } - self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?; - comma = true; - } - - for binding in data.bindings.iter() { - if comma { - self.word_space(",")? - } - self.print_name(binding.name)?; - space(&mut self.s)?; - self.word_space("=")?; - self.print_type(&binding.ty)?; - comma = true; - } - - word(&mut self.s, ">")? - } - - hir::ParenthesizedParameters(ref data) => { - word(&mut self.s, "(")?; - self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?; - word(&mut self.s, ")")?; - - match data.output { - None => {} - Some(ref ty) => { - self.space_if_not_bol()?; - self.word_space("->")?; - self.print_type(&ty)?; - } - } - } - } - - Ok(()) - } - - pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> { - self.maybe_print_comment(pat.span.lo)?; - self.ann.pre(self, NodePat(pat))?; - // Pat isn't normalized, but the beauty of it - // is that it doesn't matter - match pat.node { - PatKind::Wild => word(&mut self.s, "_")?, - PatKind::Ident(binding_mode, ref path1, ref sub) => { - match binding_mode { - hir::BindByRef(mutbl) => { - self.word_nbsp("ref")?; - self.print_mutability(mutbl)?; - } - hir::BindByValue(hir::MutImmutable) => {} - hir::BindByValue(hir::MutMutable) => { - self.word_nbsp("mut")?; - } - } - self.print_name(path1.node.name)?; - match *sub { - Some(ref p) => { - word(&mut self.s, "@")?; - self.print_pat(&p)?; - } - None => (), - } - } - PatKind::TupleStruct(ref path, ref args_) => { - self.print_path(path, true, 0)?; - match *args_ { - None => word(&mut self.s, "(..)")?, - Some(ref args) => { - self.popen()?; - self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&p))?; - self.pclose()?; - } - } - } - PatKind::Path(ref path) => { - self.print_path(path, true, 0)?; - } - PatKind::QPath(ref qself, ref path) => { - self.print_qpath(path, qself, false)?; - } - PatKind::Struct(ref path, ref fields, etc) => { - self.print_path(path, true, 0)?; - self.nbsp()?; - self.word_space("{")?; - self.commasep_cmnt(Consistent, - &fields[..], - |s, f| { - s.cbox(indent_unit)?; - if !f.node.is_shorthand { - s.print_name(f.node.name)?; - s.word_nbsp(":")?; - } - s.print_pat(&f.node.pat)?; - s.end() - }, - |f| f.node.pat.span)?; - if etc { - if !fields.is_empty() { - self.word_space(",")?; - } - word(&mut self.s, "..")?; - } - space(&mut self.s)?; - word(&mut self.s, "}")?; - } - PatKind::Tup(ref elts) => { - self.popen()?; - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?; - if elts.len() == 1 { - word(&mut self.s, ",")?; - } - self.pclose()?; - } - PatKind::Box(ref inner) => { - word(&mut self.s, "box ")?; - self.print_pat(&inner)?; - } - PatKind::Ref(ref inner, mutbl) => { - word(&mut self.s, "&")?; - if mutbl == hir::MutMutable { - word(&mut self.s, "mut ")?; - } - self.print_pat(&inner)?; - } - PatKind::Lit(ref e) => self.print_expr(&e)?, - PatKind::Range(ref begin, ref end) => { - self.print_expr(&begin)?; - space(&mut self.s)?; - word(&mut self.s, "...")?; - self.print_expr(&end)?; - } - PatKind::Vec(ref before, ref slice, ref after) => { - word(&mut self.s, "[")?; - self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))?; - if let Some(ref p) = *slice { - if !before.is_empty() { - self.word_space(",")?; - } - if p.node != PatKind::Wild { - self.print_pat(&p)?; - } - word(&mut self.s, "..")?; - if !after.is_empty() { - self.word_space(",")?; - } - } - self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))?; - word(&mut self.s, "]")?; - } - } - self.ann.post(self, NodePat(pat)) - } - - fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> { - // I have no idea why this check is necessary, but here it - // is :( - if arm.attrs.is_empty() { - space(&mut self.s)?; - } - self.cbox(indent_unit)?; - self.ibox(0)?; - self.print_outer_attributes(&arm.attrs)?; - let mut first = true; - for p in &arm.pats { - if first { - first = false; - } else { - space(&mut self.s)?; - self.word_space("|")?; - } - self.print_pat(&p)?; - } - space(&mut self.s)?; - if let Some(ref e) = arm.guard { - self.word_space("if")?; - self.print_expr(&e)?; - space(&mut self.s)?; - } - self.word_space("=>")?; - - match arm.body.node { - hir::ExprBlock(ref blk) => { - // the block will close the pattern's ibox - self.print_block_unclosed_indent(&blk, indent_unit)?; - - // If it is a user-provided unsafe block, print a comma after it - if let hir::UnsafeBlock(hir::UserProvided) = blk.rules { - word(&mut self.s, ",")?; - } - } - _ => { - self.end()?; // close the ibox for the pattern - self.print_expr(&arm.body)?; - word(&mut self.s, ",")?; - } - } - self.end() // close enclosing cbox - } - - // Returns whether it printed anything - fn print_explicit_self(&mut self, - explicit_self: &hir::ExplicitSelf_, - mutbl: hir::Mutability) - -> io::Result<bool> { - self.print_mutability(mutbl)?; - match *explicit_self { - hir::SelfStatic => { - return Ok(false); - } - hir::SelfValue(_) => { - word(&mut self.s, "self")?; - } - hir::SelfRegion(ref lt, m, _) => { - word(&mut self.s, "&")?; - self.print_opt_lifetime(lt)?; - self.print_mutability(m)?; - word(&mut self.s, "self")?; - } - hir::SelfExplicit(ref typ, _) => { - word(&mut self.s, "self")?; - self.word_space(":")?; - self.print_type(&typ)?; - } - } - return Ok(true); - } - - pub fn print_fn(&mut self, - decl: &hir::FnDecl, - unsafety: hir::Unsafety, - constness: hir::Constness, - abi: Abi, - name: Option<ast::Name>, - generics: &hir::Generics, - opt_explicit_self: Option<&hir::ExplicitSelf_>, - vis: hir::Visibility) - -> io::Result<()> { - self.print_fn_header_info(unsafety, constness, abi, vis)?; - - if let Some(name) = name { - self.nbsp()?; - self.print_name(name)?; - } - self.print_generics(generics)?; - self.print_fn_args_and_ret(decl, opt_explicit_self)?; - self.print_where_clause(&generics.where_clause) - } - - pub fn print_fn_args(&mut self, - decl: &hir::FnDecl, - opt_explicit_self: Option<&hir::ExplicitSelf_>, - is_closure: bool) - -> io::Result<()> { - // It is unfortunate to duplicate the commasep logic, but we want the - // self type and the args all in the same box. - self.rbox(0, Inconsistent)?; - let mut first = true; - if let Some(explicit_self) = opt_explicit_self { - let m = match explicit_self { - &hir::SelfStatic => hir::MutImmutable, - _ => match decl.inputs[0].pat.node { - PatKind::Ident(hir::BindByValue(m), _, _) => m, - _ => hir::MutImmutable, - }, - }; - first = !self.print_explicit_self(explicit_self, m)?; - } - - // HACK(eddyb) ignore the separately printed self argument. - let args = if first { - &decl.inputs[..] - } else { - &decl.inputs[1..] - }; - - for arg in args { - if first { - first = false; - } else { - self.word_space(",")?; - } - self.print_arg(arg, is_closure)?; - } - - self.end() - } - - pub fn print_fn_args_and_ret(&mut self, - decl: &hir::FnDecl, - opt_explicit_self: Option<&hir::ExplicitSelf_>) - -> io::Result<()> { - self.popen()?; - self.print_fn_args(decl, opt_explicit_self, false)?; - if decl.variadic { - word(&mut self.s, ", ...")?; - } - self.pclose()?; - - self.print_fn_output(decl) - } - - pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> { - word(&mut self.s, "|")?; - self.print_fn_args(decl, None, true)?; - word(&mut self.s, "|")?; - - if let hir::DefaultReturn(..) = decl.output { - return Ok(()); - } - - self.space_if_not_bol()?; - self.word_space("->")?; - match decl.output { - hir::Return(ref ty) => { - self.print_type(&ty)?; - self.maybe_print_comment(ty.span.lo) - } - hir::DefaultReturn(..) => unreachable!(), - hir::NoReturn(span) => { - self.word_nbsp("!")?; - self.maybe_print_comment(span.lo) - } - } - } - - pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) -> io::Result<()> { - match capture_clause { - hir::CaptureByValue => self.word_space("move"), - hir::CaptureByRef => Ok(()), - } - } - - pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> { - if !bounds.is_empty() { - word(&mut self.s, prefix)?; - let mut first = true; - for bound in bounds { - self.nbsp()?; - if first { - first = false; - } else { - self.word_space("+")?; - } - - match *bound { - TraitTyParamBound(ref tref, TraitBoundModifier::None) => { - self.print_poly_trait_ref(tref) - } - TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => { - word(&mut self.s, "?")?; - self.print_poly_trait_ref(tref) - } - RegionTyParamBound(ref lt) => { - self.print_lifetime(lt) - } - }? - } - Ok(()) - } else { - Ok(()) - } - } - - pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> { - self.print_name(lifetime.name) - } - - pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> { - self.print_lifetime(&lifetime.lifetime)?; - let mut sep = ":"; - for v in &lifetime.bounds { - word(&mut self.s, sep)?; - self.print_lifetime(v)?; - sep = "+"; - } - Ok(()) - } - - pub fn print_generics(&mut self, generics: &hir::Generics) -> io::Result<()> { - let total = generics.lifetimes.len() + generics.ty_params.len(); - if total == 0 { - return Ok(()); - } - - word(&mut self.s, "<")?; - - let mut ints = Vec::new(); - for i in 0..total { - ints.push(i); - } - - self.commasep(Inconsistent, &ints[..], |s, &idx| { - if idx < generics.lifetimes.len() { - let lifetime = &generics.lifetimes[idx]; - s.print_lifetime_def(lifetime) - } else { - let idx = idx - generics.lifetimes.len(); - let param = &generics.ty_params[idx]; - s.print_ty_param(param) - } - })?; - - word(&mut self.s, ">")?; - Ok(()) - } - - pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> { - self.print_name(param.name)?; - self.print_bounds(":", ¶m.bounds)?; - match param.default { - Some(ref default) => { - space(&mut self.s)?; - self.word_space("=")?; - self.print_type(&default) - } - _ => Ok(()), - } - } - - pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> { - if where_clause.predicates.is_empty() { - return Ok(()); - } - - space(&mut self.s)?; - self.word_space("where")?; - - for (i, predicate) in where_clause.predicates.iter().enumerate() { - if i != 0 { - self.word_space(",")?; - } - - match predicate { - &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bound_lifetimes, - ref bounded_ty, - ref bounds, - ..}) => { - self.print_formal_lifetime_list(bound_lifetimes)?; - self.print_type(&bounded_ty)?; - self.print_bounds(":", bounds)?; - } - &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime, - ref bounds, - ..}) => { - self.print_lifetime(lifetime)?; - word(&mut self.s, ":")?; - - for (i, bound) in bounds.iter().enumerate() { - self.print_lifetime(bound)?; - - if i != 0 { - word(&mut self.s, ":")?; - } - } - } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => { - self.print_path(path, false, 0)?; - space(&mut self.s)?; - self.word_space("=")?; - self.print_type(&ty)?; - } - } - } - - Ok(()) - } - - pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> { - match vp.node { - hir::ViewPathSimple(name, ref path) => { - self.print_path(path, false, 0)?; - - if path.segments.last().unwrap().identifier.name != name { - space(&mut self.s)?; - self.word_space("as")?; - self.print_name(name)?; - } - - Ok(()) - } - - hir::ViewPathGlob(ref path) => { - self.print_path(path, false, 0)?; - word(&mut self.s, "::*") - } - - hir::ViewPathList(ref path, ref segments) => { - if path.segments.is_empty() { - word(&mut self.s, "{")?; - } else { - self.print_path(path, false, 0)?; - word(&mut self.s, "::{")?; - } - self.commasep(Inconsistent, &segments[..], |s, w| { - match w.node { - hir::PathListIdent { name, .. } => { - s.print_name(name) - } - hir::PathListMod { .. } => { - word(&mut s.s, "self") - } - } - })?; - word(&mut self.s, "}") - } - } - } - - pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> { - match mutbl { - hir::MutMutable => self.word_nbsp("mut"), - hir::MutImmutable => Ok(()), - } - } - - pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> { - self.print_mutability(mt.mutbl)?; - self.print_type(&mt.ty) - } - - pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> { - self.ibox(indent_unit)?; - match input.ty.node { - hir::TyInfer if is_closure => self.print_pat(&input.pat)?, - _ => { - match input.pat.node { - PatKind::Ident(_, ref path1, _) if - path1.node.name == - parse::token::special_idents::invalid.name => { - // Do nothing. - } - _ => { - self.print_pat(&input.pat)?; - word(&mut self.s, ":")?; - space(&mut self.s)?; - } - } - self.print_type(&input.ty)?; - } - } - self.end() - } - - pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> { - if let hir::DefaultReturn(..) = decl.output { - return Ok(()); - } - - self.space_if_not_bol()?; - self.ibox(indent_unit)?; - self.word_space("->")?; - match decl.output { - hir::NoReturn(_) => self.word_nbsp("!")?, - hir::DefaultReturn(..) => unreachable!(), - hir::Return(ref ty) => self.print_type(&ty)?, - } - self.end()?; - - match decl.output { - hir::Return(ref output) => self.maybe_print_comment(output.span.lo), - _ => Ok(()), - } - } - - pub fn print_ty_fn(&mut self, - abi: Abi, - unsafety: hir::Unsafety, - decl: &hir::FnDecl, - name: Option<ast::Name>, - generics: &hir::Generics, - opt_explicit_self: Option<&hir::ExplicitSelf_>) - -> io::Result<()> { - self.ibox(indent_unit)?; - if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { - word(&mut self.s, "for")?; - self.print_generics(generics)?; - } - let generics = hir::Generics { - lifetimes: hir::HirVec::new(), - ty_params: hir::HirVec::new(), - where_clause: hir::WhereClause { - id: ast::DUMMY_NODE_ID, - predicates: hir::HirVec::new(), - }, - }; - self.print_fn(decl, - unsafety, - hir::Constness::NotConst, - abi, - name, - &generics, - opt_explicit_self, - hir::Inherited)?; - self.end() - } - - pub fn maybe_print_trailing_comment(&mut self, - span: codemap::Span, - next_pos: Option<BytePos>) - -> io::Result<()> { - let cm = match self.cm { - Some(cm) => cm, - _ => return Ok(()), - }; - match self.next_comment() { - Some(ref cmnt) => { - if (*cmnt).style != comments::Trailing { - return Ok(()); - } - let span_line = cm.lookup_char_pos(span.hi); - let comment_line = cm.lookup_char_pos((*cmnt).pos); - let mut next = (*cmnt).pos + BytePos(1); - match next_pos { - None => (), - Some(p) => next = p, - } - if span.hi < (*cmnt).pos && (*cmnt).pos < next && - span_line.line == comment_line.line { - self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; - } - } - _ => (), - } - Ok(()) - } - - pub fn print_remaining_comments(&mut self) -> io::Result<()> { - // If there aren't any remaining comments, then we need to manually - // make sure there is a line break at the end. - if self.next_comment().is_none() { - hardbreak(&mut self.s)?; - } - loop { - match self.next_comment() { - Some(ref cmnt) => { - self.print_comment(cmnt)?; - self.cur_cmnt_and_lit.cur_cmnt += 1; - } - _ => break, - } - } - Ok(()) - } - - pub fn print_opt_abi_and_extern_if_nondefault(&mut self, - opt_abi: Option<Abi>) - -> io::Result<()> { - match opt_abi { - Some(Abi::Rust) => Ok(()), - Some(abi) => { - self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) - } - None => Ok(()), - } - } - - pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) -> io::Result<()> { - match opt_abi { - Some(abi) => { - self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string()) - } - None => Ok(()), - } - } - - pub fn print_fn_header_info(&mut self, - unsafety: hir::Unsafety, - constness: hir::Constness, - abi: Abi, - vis: hir::Visibility) - -> io::Result<()> { - word(&mut self.s, &visibility_qualified(vis, ""))?; - self.print_unsafety(unsafety)?; - - match constness { - hir::Constness::NotConst => {} - hir::Constness::Const => self.word_nbsp("const")?, - } - - if abi != Abi::Rust { - self.word_nbsp("extern")?; - self.word_nbsp(&abi.to_string())?; - } - - word(&mut self.s, "fn") - } - - pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> { - match s { - hir::Unsafety::Normal => Ok(()), - hir::Unsafety::Unsafe => self.word_nbsp("unsafe"), - } - } -} - -// Dup'ed from parse::classify, but adapted for the HIR. -/// Does this expression require a semicolon to be treated -/// as a statement? The negation of this: 'can this expression -/// be used as a statement without a semicolon' -- is used -/// as an early-bail-out in the parser so that, for instance, -/// if true {...} else {...} -/// |x| 5 -/// isn't parsed as (if true {...} else {...} | x) | 5 -fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool { - match e.node { - hir::ExprIf(..) | - hir::ExprMatch(..) | - hir::ExprBlock(_) | - hir::ExprWhile(..) | - hir::ExprLoop(..) => false, - _ => true, - } -} - -/// this statement requires a semicolon after it. -/// note that in one case (stmt_semi), we've already -/// seen the semicolon, and thus don't need another. -fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool { - match *stmt { - hir::StmtDecl(ref d, _) => { - match d.node { - hir::DeclLocal(_) => true, - hir::DeclItem(_) => false, - } - } - hir::StmtExpr(ref e, _) => { - expr_requires_semi_to_be_stmt(&e) - } - hir::StmtSemi(..) => { - false - } - } -} diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs deleted file mode 100644 index f4f9cb75eaf..00000000000 --- a/src/librustc_front/util.rs +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use hir; -use hir::*; -use intravisit::{self, Visitor, FnKind}; -use syntax::ast_util; -use syntax::ast::{Name, NodeId, DUMMY_NODE_ID}; -use syntax::codemap::Span; -use syntax::ptr::P; - -pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool - where F: FnMut(&Pat) -> bool -{ - // FIXME(#19596) this is a workaround, but there should be a better way - fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool - where G: FnMut(&Pat) -> bool - { - if !it(pat) { - return false; - } - - match pat.node { - PatKind::Ident(_, _, Some(ref p)) => walk_pat_(&p, it), - PatKind::Struct(_, ref fields, _) => { - fields.iter().all(|field| walk_pat_(&field.node.pat, it)) - } - PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => { - s.iter().all(|p| walk_pat_(&p, it)) - } - PatKind::Box(ref s) | PatKind::Ref(ref s, _) => { - walk_pat_(&s, it) - } - PatKind::Vec(ref before, ref slice, ref after) => { - before.iter().all(|p| walk_pat_(&p, it)) && - slice.iter().all(|p| walk_pat_(&p, it)) && - after.iter().all(|p| walk_pat_(&p, it)) - } - PatKind::Wild | - PatKind::Lit(_) | - PatKind::Range(_, _) | - PatKind::Ident(_, _, _) | - PatKind::TupleStruct(..) | - PatKind::Path(..) | - PatKind::QPath(_, _) => { - true - } - } - } - - walk_pat_(pat, &mut it) -} - -pub fn binop_to_string(op: BinOp_) -> &'static str { - match op { - BiAdd => "+", - BiSub => "-", - BiMul => "*", - BiDiv => "/", - BiRem => "%", - BiAnd => "&&", - BiOr => "||", - BiBitXor => "^", - BiBitAnd => "&", - BiBitOr => "|", - BiShl => "<<", - BiShr => ">>", - BiEq => "==", - BiLt => "<", - BiLe => "<=", - BiNe => "!=", - BiGe => ">=", - BiGt => ">", - } -} - -pub fn stmt_id(s: &Stmt) -> NodeId { - match s.node { - StmtDecl(_, id) => id, - StmtExpr(_, id) => id, - StmtSemi(_, id) => id, - } -} - -pub fn lazy_binop(b: BinOp_) -> bool { - match b { - BiAnd => true, - BiOr => true, - _ => false, - } -} - -pub fn is_shift_binop(b: BinOp_) -> bool { - match b { - BiShl => true, - BiShr => true, - _ => false, - } -} - -pub fn is_comparison_binop(b: BinOp_) -> bool { - match b { - BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true, - BiAnd | - BiOr | - BiAdd | - BiSub | - BiMul | - BiDiv | - BiRem | - BiBitXor | - BiBitAnd | - BiBitOr | - BiShl | - BiShr => false, - } -} - -/// Returns `true` if the binary operator takes its arguments by value -pub fn is_by_value_binop(b: BinOp_) -> bool { - !is_comparison_binop(b) -} - -/// Returns `true` if the unary operator takes its argument by value -pub fn is_by_value_unop(u: UnOp) -> bool { - match u { - UnNeg | UnNot => true, - _ => false, - } -} - -pub fn unop_to_string(op: UnOp) -> &'static str { - match op { - UnDeref => "*", - UnNot => "!", - UnNeg => "-", - } -} - -pub struct IdVisitor<'a, O: 'a> { - operation: &'a mut O, - - // In general, the id visitor visits the contents of an item, but - // not including nested trait/impl items, nor other nested items. - // The base visitor itself always skips nested items, but not - // trait/impl items. This means in particular that if you start by - // visiting a trait or an impl, you should not visit the - // trait/impl items respectively. This is handled by setting - // `skip_members` to true when `visit_item` is on the stack. This - // way, if the user begins by calling `visit_trait_item`, we will - // visit the trait item, but if they begin with `visit_item`, we - // won't visit the (nested) trait items. - skip_members: bool, -} - -impl<'a, O: ast_util::IdVisitingOperation> IdVisitor<'a, O> { - pub fn new(operation: &'a mut O) -> IdVisitor<'a, O> { - IdVisitor { operation: operation, skip_members: false } - } - - fn visit_generics_helper(&mut self, generics: &Generics) { - for type_parameter in generics.ty_params.iter() { - self.operation.visit_id(type_parameter.id) - } - for lifetime in &generics.lifetimes { - self.operation.visit_id(lifetime.lifetime.id) - } - } -} - -impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { - fn visit_mod(&mut self, module: &Mod, _: Span, node_id: NodeId) { - self.operation.visit_id(node_id); - intravisit::walk_mod(self, module) - } - - fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { - self.operation.visit_id(foreign_item.id); - intravisit::walk_foreign_item(self, foreign_item) - } - - fn visit_item(&mut self, item: &Item) { - assert!(!self.skip_members); - self.skip_members = true; - - self.operation.visit_id(item.id); - match item.node { - ItemUse(ref view_path) => { - match view_path.node { - ViewPathSimple(_, _) | - ViewPathGlob(_) => {} - ViewPathList(_, ref paths) => { - for path in paths { - self.operation.visit_id(path.node.id()) - } - } - } - } - _ => {} - } - intravisit::walk_item(self, item); - - self.skip_members = false; - } - - fn visit_local(&mut self, local: &Local) { - self.operation.visit_id(local.id); - intravisit::walk_local(self, local) - } - - fn visit_block(&mut self, block: &Block) { - self.operation.visit_id(block.id); - intravisit::walk_block(self, block) - } - - fn visit_stmt(&mut self, statement: &Stmt) { - self.operation.visit_id(stmt_id(statement)); - intravisit::walk_stmt(self, statement) - } - - fn visit_pat(&mut self, pattern: &Pat) { - self.operation.visit_id(pattern.id); - intravisit::walk_pat(self, pattern) - } - - fn visit_expr(&mut self, expression: &Expr) { - self.operation.visit_id(expression.id); - intravisit::walk_expr(self, expression) - } - - fn visit_ty(&mut self, typ: &Ty) { - self.operation.visit_id(typ.id); - intravisit::walk_ty(self, typ) - } - - fn visit_generics(&mut self, generics: &Generics) { - self.visit_generics_helper(generics); - intravisit::walk_generics(self, generics) - } - - fn visit_fn(&mut self, - function_kind: FnKind<'v>, - function_declaration: &'v FnDecl, - block: &'v Block, - span: Span, - node_id: NodeId) { - self.operation.visit_id(node_id); - - match function_kind { - FnKind::ItemFn(_, generics, _, _, _, _, _) => { - self.visit_generics_helper(generics) - } - FnKind::Method(_, sig, _, _) => { - self.visit_generics_helper(&sig.generics) - } - FnKind::Closure(_) => {} - } - - for argument in &function_declaration.inputs { - self.operation.visit_id(argument.id) - } - - intravisit::walk_fn(self, function_kind, function_declaration, block, span); - } - - fn visit_struct_field(&mut self, struct_field: &StructField) { - self.operation.visit_id(struct_field.id); - intravisit::walk_struct_field(self, struct_field) - } - - fn visit_variant_data(&mut self, - struct_def: &VariantData, - _: Name, - _: &hir::Generics, - _: NodeId, - _: Span) { - self.operation.visit_id(struct_def.id()); - intravisit::walk_struct_def(self, struct_def); - } - - fn visit_trait_item(&mut self, ti: &hir::TraitItem) { - if !self.skip_members { - self.operation.visit_id(ti.id); - intravisit::walk_trait_item(self, ti); - } - } - - fn visit_impl_item(&mut self, ii: &hir::ImplItem) { - if !self.skip_members { - self.operation.visit_id(ii.id); - intravisit::walk_impl_item(self, ii); - } - } - - fn visit_lifetime(&mut self, lifetime: &Lifetime) { - self.operation.visit_id(lifetime.id); - } - - fn visit_lifetime_def(&mut self, def: &LifetimeDef) { - self.visit_lifetime(&def.lifetime); - } - - fn visit_trait_ref(&mut self, trait_ref: &TraitRef) { - self.operation.visit_id(trait_ref.ref_id); - intravisit::walk_trait_ref(self, trait_ref); - } -} - -/// Computes the id range for a single fn body, ignoring nested items. -pub fn compute_id_range_for_fn_body(fk: FnKind, - decl: &FnDecl, - body: &Block, - sp: Span, - id: NodeId) - -> ast_util::IdRange { - let mut visitor = ast_util::IdRangeComputingVisitor { result: ast_util::IdRange::max() }; - let mut id_visitor = IdVisitor::new(&mut visitor); - id_visitor.visit_fn(fk, decl, body, sp, id); - id_visitor.operation.result -} - -pub fn is_path(e: P<Expr>) -> bool { - match e.node { - ExprPath(..) => true, - _ => false, - } -} - -pub fn empty_generics() -> Generics { - Generics { - lifetimes: HirVec::new(), - ty_params: HirVec::new(), - where_clause: WhereClause { - id: DUMMY_NODE_ID, - predicates: HirVec::new(), - }, - } -} - -// convert a span and an identifier to the corresponding -// 1-segment path -pub fn ident_to_path(s: Span, ident: Ident) -> Path { - hir::Path { - span: s, - global: false, - segments: hir_vec![hir::PathSegment { - identifier: ident, - parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: HirVec::new(), - types: HirVec::new(), - bindings: HirVec::new(), - }), - }], - } -} |
