rust/src/librustc_hir_pretty/lib.rs

2355 lines
81 KiB
Rust
Raw Normal View History

use rustc_ast::ast;
use rustc_ast::util::parser::{self, AssocOp, Fixity};
use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
use rustc_ast_pretty::pp::{self, Breaks};
2020-02-22 23:29:36 +01:00
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
use rustc_span::source_map::{SourceMap, Spanned};
2020-02-22 23:29:36 +01:00
use rustc_span::symbol::{kw, IdentPrinter};
use rustc_span::{self, BytePos, FileName};
use rustc_target::spec::abi::Abi;
2015-07-31 09:04:06 +02:00
use std::borrow::Cow;
use std::cell::Cell;
use std::vec;
2015-07-31 09:04:06 +02:00
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String {
to_string(&map, |s| s.print_node(map.find(hir_id).unwrap()))
}
2015-07-31 09:04:06 +02:00
pub enum AnnNode<'a> {
2018-08-22 23:05:19 +02:00
Name(&'a ast::Name),
2019-11-29 13:43:03 +01:00
Block(&'a hir::Block<'a>),
2019-11-28 19:28:50 +01:00
Item(&'a hir::Item<'a>),
2019-02-26 11:04:58 +01:00
SubItem(hir::HirId),
2019-11-29 13:43:03 +01:00
Expr(&'a hir::Expr<'a>),
Pat(&'a hir::Pat<'a>),
Arm(&'a hir::Arm<'a>),
2015-07-31 09:04:06 +02:00
}
pub enum Nested {
Item(hir::ItemId),
TraitItem(hir::TraitItemId),
ImplItem(hir::ImplItemId),
Body(hir::BodyId),
2019-12-22 23:42:04 +01:00
BodyParamPat(hir::BodyId, usize),
}
2015-07-31 09:04:06 +02:00
pub trait PpAnn {
2019-12-22 23:42:04 +01:00
fn nested(&self, _state: &mut State<'_>, _nested: Nested) {}
fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
2019-11-28 19:28:50 +01:00
fn try_fetch_item(&self, _: hir::HirId) -> Option<&hir::Item<'_>> {
2018-05-22 14:31:56 +02:00
None
}
2015-07-31 09:04:06 +02:00
}
pub struct NoAnn;
impl PpAnn for NoAnn {}
pub const NO_ANN: &dyn PpAnn = &NoAnn;
impl PpAnn for hir::Crate<'_> {
2019-11-28 19:28:50 +01:00
fn try_fetch_item(&self, item: hir::HirId) -> Option<&hir::Item<'_>> {
2018-05-22 14:31:56 +02:00
Some(self.item(item))
}
fn nested(&self, state: &mut State<'_>, nested: Nested) {
match nested {
Nested::Item(id) => state.print_item(self.item(id.id)),
Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
Nested::Body(id) => state.print_expr(&self.body(id).value),
Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat),
}
}
}
/// Identical to the `PpAnn` implementation for `hir::Crate`,
/// except it avoids creating a dependency on the whole crate.
impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
fn nested(&self, state: &mut State<'_>, nested: Nested) {
match nested {
Nested::Item(id) => state.print_item(self.item(id.id)),
Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
Nested::Body(id) => state.print_expr(&self.body(id).value),
2019-12-22 23:42:04 +01:00
Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat),
}
}
}
2015-07-31 09:04:06 +02:00
pub struct State<'a> {
pub s: pp::Printer,
comments: Option<Comments<'a>>,
2018-02-23 18:53:00 +01:00
ann: &'a (dyn PpAnn + 'a),
2015-07-31 09:04:06 +02:00
}
impl<'a> State<'a> {
pub fn print_node(&mut self, node: Node<'_>) {
match node {
Node::Param(a) => self.print_param(&a),
Node::Item(a) => self.print_item(&a),
Node::ForeignItem(a) => self.print_foreign_item(&a),
Node::TraitItem(a) => self.print_trait_item(a),
Node::ImplItem(a) => self.print_impl_item(a),
Node::Variant(a) => self.print_variant(&a),
Node::AnonConst(a) => self.print_anon_const(&a),
Node::Expr(a) => self.print_expr(&a),
Node::Stmt(a) => self.print_stmt(&a),
Node::PathSegment(a) => self.print_path_segment(&a),
Node::Ty(a) => self.print_type(&a),
Node::TraitRef(a) => self.print_trait_ref(&a),
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
Node::Arm(a) => self.print_arm(&a),
Node::Block(a) => {
// Containing cbox, will be closed by print-block at `}`.
self.cbox(INDENT_UNIT);
// Head-ibox, will be closed by print-block after `{`.
self.ibox(0);
self.print_block(&a)
}
Node::Lifetime(a) => self.print_lifetime(&a),
Node::Visibility(a) => self.print_visibility(&a),
Node::GenericParam(_) => panic!("cannot print Node::GenericParam"),
Node::Field(_) => panic!("cannot print StructField"),
// These cases do not carry enough information in the
// `hir_map` to reconstruct their full structure for pretty
// printing.
Node::Ctor(..) => panic!("cannot print isolated Ctor"),
Node::Local(a) => self.print_local_decl(&a),
Node::MacroDef(_) => panic!("cannot print MacroDef"),
2020-02-07 16:43:36 +01:00
Node::Crate(..) => panic!("cannot print Crate"),
}
}
}
impl std::ops::Deref for State<'_> {
type Target = pp::Printer;
fn deref(&self) -> &Self::Target {
&self.s
}
}
impl std::ops::DerefMut for State<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.s
}
}
impl<'a> PrintState<'a> for State<'a> {
fn comments(&mut self) -> &mut Option<Comments<'a>> {
&mut self.comments
}
fn print_ident(&mut self, ident: ast::Ident) {
2020-02-22 23:29:36 +01:00
self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
self.ann.post(self, AnnNode::Name(&ident.name))
}
fn print_generic_args(&mut self, _: &ast::GenericArgs, _colons_before_params: bool) {
panic!("AST generic args printed by HIR pretty-printer");
}
}
2019-07-09 15:32:25 +02:00
pub const INDENT_UNIT: usize = 4;
2015-07-31 09:04:06 +02:00
/// Requires you to pass an input filename and reader so that
2019-05-09 18:04:04 +02:00
/// it can scan the input text for comments to copy forward.
2019-12-22 23:42:04 +01:00
pub fn print_crate<'a>(
2020-02-22 15:07:05 +01:00
sm: &'a SourceMap,
2019-12-22 23:42:04 +01:00
krate: &hir::Crate<'_>,
filename: FileName,
input: String,
ann: &'a dyn PpAnn,
) -> String {
2020-02-22 15:07:05 +01:00
let mut s = State::new_from_input(sm, filename, input, ann);
2015-07-31 09:04:06 +02:00
// When printing the AST, we sometimes need to inject `#[no_std]` here.
// Since you can't compile the HIR, it's not necessary.
2020-02-07 16:43:36 +01:00
s.print_mod(&krate.item.module, &krate.item.attrs);
s.print_remaining_comments();
s.s.eof()
2015-07-31 09:04:06 +02:00
}
impl<'a> State<'a> {
2019-12-22 23:42:04 +01:00
pub fn new_from_input(
2020-02-22 15:07:05 +01:00
sm: &'a SourceMap,
2019-12-22 23:42:04 +01:00
filename: FileName,
input: String,
ann: &'a dyn PpAnn,
) -> State<'a> {
2020-02-22 15:07:05 +01:00
State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann }
2015-07-31 09:04:06 +02:00
}
}
2018-02-23 18:53:00 +01:00
pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
2019-12-22 23:42:04 +01:00
where
F: FnOnce(&mut State<'_>),
2015-07-31 09:04:06 +02:00
{
2019-12-22 23:42:04 +01:00
let mut printer = State { s: pp::mk_printer(), comments: None, ann };
f(&mut printer);
printer.s.eof()
2015-07-31 09:04:06 +02:00
}
2019-11-30 17:46:46 +01:00
pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility<'_>, w: S) -> String {
to_string(NO_ANN, |s| {
s.print_visibility(vis);
s.s.word(w)
2015-07-31 09:04:06 +02:00
})
}
impl<'a> State<'a> {
pub fn cbox(&mut self, u: usize) {
self.s.cbox(u);
2015-07-31 09:04:06 +02:00
}
pub fn nbsp(&mut self) {
self.s.word(" ")
2015-09-27 21:23:31 +02:00
}
2015-07-31 09:04:06 +02:00
pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) {
self.s.word(w);
2015-07-31 09:04:06 +02:00
self.nbsp()
}
pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
let w = w.into();
2015-07-31 09:04:06 +02:00
// outer-box is consistent
2019-07-09 15:32:25 +02:00
self.cbox(INDENT_UNIT);
2015-07-31 09:04:06 +02:00
// head-box is inconsistent
self.ibox(w.len() + 1);
2015-07-31 09:04:06 +02:00
// keyword that starts the head
if !w.is_empty() {
self.word_nbsp(w);
2015-07-31 09:04:06 +02:00
}
}
pub fn bopen(&mut self) {
self.s.word("{");
self.end(); // close the head-box
2015-07-31 09:04:06 +02:00
}
pub fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) {
self.maybe_print_comment(span.hi());
self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
self.s.word("}");
2015-07-31 09:04:06 +02:00
if close_box {
self.end(); // close the outer-box
2015-07-31 09:04:06 +02:00
}
}
2018-09-12 12:31:11 +02:00
pub fn bclose(&mut self, span: rustc_span::Span) {
self.bclose_maybe_open(span, true)
2015-07-31 09:04:06 +02:00
}
pub fn space_if_not_bol(&mut self) {
if !self.s.is_beginning_of_line() {
self.s.space();
2015-09-27 21:23:31 +02:00
}
2015-07-31 09:04:06 +02:00
}
2018-09-12 12:31:11 +02:00
pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
if !self.s.is_beginning_of_line() {
self.s.break_offset(n, off)
2015-07-31 09:04:06 +02:00
} 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::Printer::hardbreak_tok_offset(off));
2015-07-31 09:04:06 +02:00
}
}
}
// Synthesizes a comment that was not textually present in the original source
// file.
pub fn synth_comment(&mut self, text: String) {
self.s.word("/*");
self.s.space();
self.s.word(text);
self.s.space();
self.s.word("*/")
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
pub fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)
where
F: FnMut(&mut State<'_>, &T),
G: FnMut(&T) -> rustc_span::Span,
2015-07-31 09:04:06 +02:00
{
self.rbox(0, b);
2015-07-31 09:04:06 +02:00
let len = elts.len();
let mut i = 0;
for elt in elts {
self.maybe_print_comment(get_span(elt).hi());
op(self, elt);
2015-07-31 09:04:06 +02:00
i += 1;
if i < len {
self.s.word(",");
self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi()));
self.space_if_not_bol();
2015-07-31 09:04:06 +02:00
}
}
self.end();
2015-07-31 09:04:06 +02:00
}
2019-11-29 13:43:03 +01:00
pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr<'_>]) {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
2015-07-31 09:04:06 +02:00
}
2019-11-29 10:24:47 +01:00
pub fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
self.print_inner_attributes(attrs);
2019-11-29 10:24:47 +01:00
for &item_id in _mod.item_ids {
self.ann.nested(self, Nested::Item(item_id));
2015-07-31 09:04:06 +02:00
}
}
2019-12-22 23:42:04 +01:00
pub fn print_foreign_mod(&mut self, nmod: &hir::ForeignMod<'_>, attrs: &[ast::Attribute]) {
self.print_inner_attributes(attrs);
2019-11-28 20:18:29 +01:00
for item in nmod.items {
self.print_foreign_item(item);
2015-07-31 09:04:06 +02:00
}
}
pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) {
if !lifetime.is_elided() {
self.print_lifetime(lifetime);
self.nbsp();
2015-07-31 09:04:06 +02:00
}
}
2019-11-30 17:46:46 +01:00
pub fn print_type(&mut self, ty: &hir::Ty<'_>) {
self.maybe_print_comment(ty.span.lo());
self.ibox(0);
2019-09-26 18:25:31 +02:00
match ty.kind {
2018-07-11 16:41:03 +02:00
hir::TyKind::Slice(ref ty) => {
self.s.word("[");
self.print_type(&ty);
self.s.word("]");
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Ptr(ref mt) => {
self.s.word("*");
self.print_mt(mt, true);
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Rptr(ref lifetime, ref mt) => {
self.s.word("&");
self.print_opt_lifetime(lifetime);
self.print_mt(mt, false);
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Never => {
self.s.word("!");
2019-12-22 23:42:04 +01:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Tup(ref elts) => {
self.popen();
self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty));
2015-07-31 09:04:06 +02:00
if elts.len() == 1 {
self.s.word(",");
2015-07-31 09:04:06 +02:00
}
self.pclose();
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::BareFn(ref f) => {
2019-12-22 23:42:04 +01:00
self.print_ty_fn(
f.abi,
f.unsafety,
&f.decl,
None,
&f.generic_params,
&f.param_names[..],
);
}
hir::TyKind::Def(..) => {}
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
2019-12-01 00:17:43 +01:00
hir::TyKind::TraitObject(bounds, ref lifetime) => {
let mut first = true;
for bound in bounds {
if first {
first = false;
} else {
self.nbsp();
self.word_space("+");
}
self.print_poly_trait_ref(bound);
}
if !lifetime.is_elided() {
self.nbsp();
self.word_space("+");
self.print_lifetime(lifetime);
}
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Array(ref ty, ref length) => {
self.s.word("[");
self.print_type(&ty);
self.s.word("; ");
self.print_anon_const(length);
self.s.word("]");
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Typeof(ref e) => {
self.s.word("typeof(");
self.print_anon_const(e);
self.s.word(")");
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Infer => {
self.s.word("_");
2015-07-31 09:04:06 +02:00
}
2018-07-11 16:41:03 +02:00
hir::TyKind::Err => {
self.popen();
self.s.word("/*ERROR*/");
self.pclose();
}
2015-07-31 09:04:06 +02:00
}
self.end()
}
2019-11-28 20:18:29 +01:00
pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
self.hardbreak_if_not_bol();
self.maybe_print_comment(item.span.lo());
self.print_outer_attributes(&item.attrs);
match item.kind {
2018-07-11 16:56:44 +02:00
hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => {
self.head("");
2019-12-22 23:42:04 +01:00
self.print_fn(
decl,
hir::FnHeader {
unsafety: hir::Unsafety::Normal,
constness: hir::Constness::NotConst,
abi: Abi::Rust,
asyncness: hir::IsAsync::NotAsync,
},
Some(item.ident.name),
generics,
&item.vis,
arg_names,
None,
);
self.end(); // end head-ibox
self.s.word(";");
2015-07-31 09:04:06 +02:00
self.end() // end the outer fn box
}
2018-07-11 16:56:44 +02:00
hir::ForeignItemKind::Static(ref t, m) => {
self.head(visibility_qualified(&item.vis, "static"));
if m == hir::Mutability::Mut {
self.word_space("mut");
2015-07-31 09:04:06 +02:00
}
self.print_ident(item.ident);
self.word_space(":");
self.print_type(&t);
self.s.word(";");
self.end(); // end the head-ibox
2017-09-03 20:53:58 +02:00
self.end() // end the outer cbox
}
2018-07-11 16:56:44 +02:00
hir::ForeignItemKind::Type => {
self.head(visibility_qualified(&item.vis, "type"));
self.print_ident(item.ident);
self.s.word(";");
self.end(); // end the head-ibox
2015-07-31 09:04:06 +02:00
self.end() // end the outer cbox
}
}
}
2019-12-22 23:42:04 +01:00
fn print_associated_const(
&mut self,
ident: ast::Ident,
2019-11-30 17:46:46 +01:00
ty: &hir::Ty<'_>,
2019-12-22 23:42:04 +01:00
default: Option<hir::BodyId>,
2019-11-30 17:46:46 +01:00
vis: &hir::Visibility<'_>,
2019-12-22 23:42:04 +01:00
) {
self.s.word(visibility_qualified(vis, ""));
self.word_space("const");
self.print_ident(ident);
self.word_space(":");
self.print_type(ty);
2015-07-31 09:04:06 +02:00
if let Some(expr) = default {
self.s.space();
self.word_space("=");
self.ann.nested(self, Nested::Body(expr));
2015-07-31 09:04:06 +02:00
}
self.s.word(";")
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
fn print_associated_type(
&mut self,
ident: ast::Ident,
2020-02-07 16:27:12 +01:00
generics: &hir::Generics<'_>,
2019-12-01 00:17:43 +01:00
bounds: Option<hir::GenericBounds<'_>>,
2019-11-30 17:46:46 +01:00
ty: Option<&hir::Ty<'_>>,
2019-12-22 23:42:04 +01:00
) {
self.word_space("type");
self.print_ident(ident);
2020-02-07 16:27:12 +01:00
self.print_generic_params(&generics.params);
2015-07-31 09:04:06 +02:00
if let Some(bounds) = bounds {
self.print_bounds(":", bounds);
2015-07-31 09:04:06 +02:00
}
2020-02-07 16:27:12 +01:00
self.print_where_clause(&generics.where_clause);
2015-07-31 09:04:06 +02:00
if let Some(ty) = ty {
self.s.space();
self.word_space("=");
self.print_type(ty);
2015-07-31 09:04:06 +02:00
}
self.s.word(";")
2015-07-31 09:04:06 +02:00
}
2019-08-02 04:40:16 +02:00
fn print_item_type(
&mut self,
2019-11-28 19:28:50 +01:00
item: &hir::Item<'_>,
2019-11-30 17:46:46 +01:00
generics: &hir::Generics<'_>,
2019-08-02 04:40:16 +02:00
inner: impl Fn(&mut Self),
) {
self.head(visibility_qualified(&item.vis, "type"));
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
self.end(); // end the inner ibox
self.print_where_clause(&generics.where_clause);
self.s.space();
inner(self);
self.s.word(";");
self.end(); // end the outer ibox
}
2015-07-31 09:04:06 +02:00
/// Pretty-print an item
2019-11-28 19:28:50 +01:00
pub fn print_item(&mut self, item: &hir::Item<'_>) {
self.hardbreak_if_not_bol();
self.maybe_print_comment(item.span.lo());
self.print_outer_attributes(&item.attrs);
self.ann.pre(self, AnnNode::Item(item));
2019-09-26 18:51:36 +02:00
match item.kind {
2018-07-11 17:36:06 +02:00
hir::ItemKind::ExternCrate(orig_name) => {
self.head(visibility_qualified(&item.vis, "extern crate"));
if let Some(orig_name) = orig_name {
self.print_name(orig_name);
self.s.space();
self.s.word("as");
self.s.space();
2015-07-31 09:04:06 +02:00
}
self.print_ident(item.ident);
self.s.word(";");
self.end(); // end inner head-block
self.end(); // end outer head-block
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::Use(ref path, kind) => {
self.head(visibility_qualified(&item.vis, "use"));
self.print_path(path, false);
match kind {
hir::UseKind::Single => {
if path.segments.last().unwrap().ident != item.ident {
self.s.space();
self.word_space("as");
self.print_ident(item.ident);
}
self.s.word(";");
}
hir::UseKind::Glob => self.s.word("::*;"),
2019-12-22 23:42:04 +01:00
hir::UseKind::ListStem => self.s.word("::{};"),
}
self.end(); // end inner head-block
self.end(); // end outer head-block
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::Static(ref ty, m, expr) => {
self.head(visibility_qualified(&item.vis, "static"));
if m == hir::Mutability::Mut {
self.word_space("mut");
2015-07-31 09:04:06 +02:00
}
self.print_ident(item.ident);
self.word_space(":");
self.print_type(&ty);
self.s.space();
self.end(); // end the head-ibox
2015-07-31 09:04:06 +02:00
self.word_space("=");
self.ann.nested(self, Nested::Body(expr));
self.s.word(";");
self.end(); // end the outer cbox
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::Const(ref ty, expr) => {
self.head(visibility_qualified(&item.vis, "const"));
self.print_ident(item.ident);
self.word_space(":");
self.print_type(&ty);
self.s.space();
self.end(); // end the head-ibox
self.word_space("=");
self.ann.nested(self, Nested::Body(expr));
self.s.word(";");
self.end(); // end the outer cbox
2015-07-31 09:04:06 +02:00
}
2019-11-07 12:57:52 +01:00
hir::ItemKind::Fn(ref sig, ref param_names, body) => {
self.head("");
2019-12-22 23:42:04 +01:00
self.print_fn(
&sig.decl,
sig.header,
Some(item.ident.name),
param_names,
&item.vis,
&[],
Some(body),
);
self.s.word(" ");
self.end(); // need to close a box
self.end(); // need to close a box
self.ann.nested(self, Nested::Body(body));
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::Mod(ref _mod) => {
self.head(visibility_qualified(&item.vis, "mod"));
self.print_ident(item.ident);
self.nbsp();
self.bopen();
self.print_mod(_mod, &item.attrs);
self.bclose(item.span);
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::ForeignMod(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);
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::GlobalAsm(ref ga) => {
self.head(visibility_qualified(&item.vis, "global asm"));
self.s.word(ga.asm.to_string());
self.end()
2017-03-16 03:27:40 +01:00
}
hir::ItemKind::TyAlias(ref ty, ref generics) => {
2019-08-02 04:40:16 +02:00
self.print_item_type(item, &generics, |state| {
state.word_space("=");
state.print_type(&ty);
});
2015-07-31 09:04:06 +02:00
}
2019-08-02 02:14:42 +02:00
hir::ItemKind::OpaqueTy(ref opaque_ty) => {
2019-08-02 04:40:16 +02:00
self.print_item_type(item, &opaque_ty.generics, |state| {
let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len());
for b in opaque_ty.bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
state.s.space();
state.word_space("for ?");
state.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b);
}
2018-05-22 14:31:56 +02:00
}
2019-08-02 04:40:16 +02:00
state.print_bounds("= impl", real_bounds);
});
2018-05-22 14:31:56 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::Enum(ref enum_definition, ref params) => {
2019-08-02 04:40:16 +02:00
self.print_enum_def(enum_definition, params, item.ident.name, item.span, &item.vis);
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::Struct(ref struct_def, ref generics) => {
self.head(visibility_qualified(&item.vis, "struct"));
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::Union(ref struct_def, ref generics) => {
self.head(visibility_qualified(&item.vis, "union"));
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
2016-08-06 20:36:28 +02:00
}
hir::ItemKind::Impl {
2019-12-22 23:42:04 +01:00
unsafety,
polarity,
defaultness,
constness,
defaultness_span: _,
2019-12-22 23:42:04 +01:00
ref generics,
ref of_trait,
ref self_ty,
items,
} => {
self.head("");
self.print_visibility(&item.vis);
self.print_defaultness(defaultness);
self.print_unsafety(unsafety);
self.word_nbsp("impl");
2015-07-31 09:04:06 +02:00
if !generics.params.is_empty() {
self.print_generic_params(&generics.params);
self.s.space();
2015-07-31 09:04:06 +02:00
}
2020-02-10 15:24:53 +01:00
if constness == hir::Constness::Const {
self.word_nbsp("const");
}
if let hir::ImplPolarity::Negative(_) = polarity {
self.s.word("!");
2015-07-31 09:04:06 +02:00
}
if let Some(ref t) = of_trait {
self.print_trait_ref(t);
self.s.space();
self.word_space("for");
2015-07-31 09:04:06 +02:00
}
self.print_type(&self_ty);
self.print_where_clause(&generics.where_clause);
2015-07-31 09:04:06 +02:00
self.s.space();
self.bopen();
self.print_inner_attributes(&item.attrs);
for impl_item in items {
self.ann.nested(self, Nested::ImplItem(impl_item.id));
2015-07-31 09:04:06 +02:00
}
self.bclose(item.span);
2015-07-31 09:04:06 +02:00
}
2019-11-28 19:28:50 +01:00
hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => {
self.head("");
self.print_visibility(&item.vis);
self.print_is_auto(is_auto);
self.print_unsafety(unsafety);
self.word_nbsp("trait");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
2015-07-31 09:04:06 +02:00
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
self.s.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
2015-07-31 09:04:06 +02:00
} else {
2019-06-12 10:43:15 +02:00
real_bounds.push(b);
2015-07-31 09:04:06 +02:00
}
}
self.print_bounds(":", real_bounds);
self.print_where_clause(&generics.where_clause);
self.s.word(" ");
self.bopen();
2015-07-31 09:04:06 +02:00
for trait_item in trait_items {
self.ann.nested(self, Nested::TraitItem(trait_item.id));
2015-07-31 09:04:06 +02:00
}
self.bclose(item.span);
2015-07-31 09:04:06 +02:00
}
2018-07-11 17:36:06 +02:00
hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
self.head("");
self.print_visibility(&item.vis);
self.word_nbsp("trait");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
2017-10-02 14:28:16 +02:00
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
self.s.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
2017-10-02 14:28:16 +02:00
} else {
2019-06-12 10:43:15 +02:00
real_bounds.push(b);
2017-10-02 14:28:16 +02:00
}
}
self.nbsp();
self.print_bounds("=", real_bounds);
self.print_where_clause(&generics.where_clause);
self.s.word(";");
2017-10-02 14:28:16 +02:00
}
2015-07-31 09:04:06 +02:00
}
2018-08-22 23:05:19 +02:00
self.ann.post(self, AnnNode::Item(item))
2015-07-31 09:04:06 +02:00
}
2019-11-30 17:46:46 +01:00
pub fn print_trait_ref(&mut self, t: &hir::TraitRef<'_>) {
self.print_path(&t.path, false)
2015-07-31 09:04:06 +02:00
}
2019-11-30 17:46:46 +01:00
fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) {
if !generic_params.is_empty() {
self.s.word("for");
self.print_generic_params(generic_params);
self.nbsp();
2015-07-31 09:04:06 +02:00
}
}
2019-11-30 17:46:46 +01:00
fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) {
self.print_formal_generic_params(&t.bound_generic_params);
2015-07-31 09:04:06 +02:00
self.print_trait_ref(&t.trait_ref)
}
2019-12-22 23:42:04 +01:00
pub fn print_enum_def(
&mut self,
enum_definition: &hir::EnumDef<'_>,
2019-11-30 17:46:46 +01:00
generics: &hir::Generics<'_>,
2019-12-22 23:42:04 +01:00
name: ast::Name,
span: rustc_span::Span,
2019-11-30 17:46:46 +01:00
visibility: &hir::Visibility<'_>,
2019-12-22 23:42:04 +01:00
) {
self.head(visibility_qualified(visibility, "enum"));
self.print_name(name);
self.print_generic_params(&generics.params);
self.print_where_clause(&generics.where_clause);
self.s.space();
2015-07-31 09:04:06 +02:00
self.print_variants(&enum_definition.variants, span)
}
pub fn print_variants(&mut self, variants: &[hir::Variant<'_>], span: rustc_span::Span) {
self.bopen();
2015-07-31 09:04:06 +02:00
for v in variants {
self.space_if_not_bol();
self.maybe_print_comment(v.span.lo());
2019-08-14 02:40:21 +02:00
self.print_outer_attributes(&v.attrs);
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
self.print_variant(v);
self.s.word(",");
self.end();
self.maybe_print_trailing_comment(v.span, None);
2015-07-31 09:04:06 +02:00
}
self.bclose(span)
}
2019-11-30 17:46:46 +01:00
pub fn print_visibility(&mut self, vis: &hir::Visibility<'_>) {
match vis.node {
hir::VisibilityKind::Public => self.word_nbsp("pub"),
hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"),
hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"),
hir::VisibilityKind::Restricted { ref path, .. } => {
self.s.word("pub(");
2019-12-22 23:42:04 +01:00
if path.segments.len() == 1 && path.segments[0].ident.name == kw::Super {
// Special case: `super` can print like `pub(super)`.
self.s.word("super");
} else {
// Everything else requires `in` at present.
self.word_nbsp("in");
self.print_path(path, false);
}
self.word_nbsp(")");
}
2019-12-22 23:42:04 +01:00
hir::VisibilityKind::Inherited => (),
2015-07-31 09:04:06 +02:00
}
}
pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) {
match defaultness {
hir::Defaultness::Default { .. } => self.word_nbsp("default"),
hir::Defaultness::Final => (),
}
}
2019-12-22 23:42:04 +01:00
pub fn print_struct(
&mut self,
struct_def: &hir::VariantData<'_>,
2019-11-30 17:46:46 +01:00
generics: &hir::Generics<'_>,
2019-12-22 23:42:04 +01:00
name: ast::Name,
span: rustc_span::Span,
2019-12-22 23:42:04 +01:00
print_finalizer: bool,
) {
self.print_name(name);
self.print_generic_params(&generics.params);
match struct_def {
hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
if let hir::VariantData::Tuple(..) = struct_def {
self.popen();
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.maybe_print_comment(field.span.lo());
s.print_outer_attributes(&field.attrs);
s.print_visibility(&field.vis);
s.print_type(&field.ty)
});
self.pclose();
}
self.print_where_clause(&generics.where_clause);
if print_finalizer {
self.s.word(";");
}
self.end();
self.end() // close the outer-box
}
hir::VariantData::Struct(..) => {
self.print_where_clause(&generics.where_clause);
self.nbsp();
self.bopen();
self.hardbreak_if_not_bol();
2015-07-31 09:04:06 +02:00
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_ident(field.ident);
self.word_nbsp(":");
self.print_type(&field.ty);
self.s.word(",");
}
self.bclose(span)
}
2015-07-31 09:04:06 +02:00
}
}
2019-11-29 09:26:18 +01:00
pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
self.head("");
let generics = hir::Generics::empty();
2019-08-14 02:40:21 +02:00
self.print_struct(&v.data, &generics, v.ident.name, v.span, false);
if let Some(ref d) = v.disr_expr {
self.s.space();
self.word_space("=");
self.print_anon_const(d);
2015-07-31 09:04:06 +02:00
}
}
2019-12-22 23:42:04 +01:00
pub fn print_method_sig(
&mut self,
ident: ast::Ident,
2019-11-30 15:20:35 +01:00
m: &hir::FnSig<'_>,
2019-11-30 17:46:46 +01:00
generics: &hir::Generics<'_>,
vis: &hir::Visibility<'_>,
2019-12-22 23:42:04 +01:00
arg_names: &[ast::Ident],
body_id: Option<hir::BodyId>,
) {
self.print_fn(&m.decl, m.header, Some(ident.name), generics, vis, arg_names, body_id)
2015-07-31 09:04:06 +02:00
}
2019-11-28 21:47:10 +01:00
pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
self.ann.pre(self, AnnNode::SubItem(ti.hir_id));
self.hardbreak_if_not_bol();
self.maybe_print_comment(ti.span.lo());
self.print_outer_attributes(&ti.attrs);
match ti.kind {
hir::TraitItemKind::Const(ref ty, default) => {
2019-12-22 23:42:04 +01:00
let vis =
Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
self.print_associated_const(ti.ident, &ty, default, &vis);
2015-07-31 09:04:06 +02:00
}
2020-03-05 16:57:34 +01:00
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => {
2019-12-22 23:42:04 +01:00
let vis =
Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None);
self.s.word(";");
}
2020-03-05 16:57:34 +01:00
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
2019-12-22 23:42:04 +01:00
let vis =
Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
self.head("");
self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body));
self.nbsp();
self.end(); // need to close a box
self.end(); // need to close a box
self.ann.nested(self, Nested::Body(body));
2015-07-31 09:04:06 +02:00
}
hir::TraitItemKind::Type(ref bounds, ref default) => {
2019-12-22 23:42:04 +01:00
self.print_associated_type(
ti.ident,
2020-02-07 16:27:12 +01:00
&ti.generics,
2019-12-22 23:42:04 +01:00
Some(bounds),
default.as_ref().map(|ty| &**ty),
);
2015-07-31 09:04:06 +02:00
}
}
2019-02-26 11:04:58 +01:00
self.ann.post(self, AnnNode::SubItem(ti.hir_id))
2015-07-31 09:04:06 +02:00
}
2019-11-28 22:16:44 +01:00
pub fn print_impl_item(&mut self, ii: &hir::ImplItem<'_>) {
self.ann.pre(self, AnnNode::SubItem(ii.hir_id));
self.hardbreak_if_not_bol();
self.maybe_print_comment(ii.span.lo());
self.print_outer_attributes(&ii.attrs);
self.print_defaultness(ii.defaultness);
match ii.kind {
hir::ImplItemKind::Const(ref ty, expr) => {
self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis);
2015-07-31 09:04:06 +02:00
}
2020-03-05 16:57:34 +01:00
hir::ImplItemKind::Fn(ref sig, body) => {
self.head("");
self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body));
self.nbsp();
self.end(); // need to close a box
self.end(); // need to close a box
self.ann.nested(self, Nested::Body(body));
2015-07-31 09:04:06 +02:00
}
hir::ImplItemKind::TyAlias(ref ty) => {
2020-02-07 16:27:12 +01:00
self.print_associated_type(ii.ident, &ii.generics, None, Some(ty));
2015-07-31 09:04:06 +02:00
}
2019-12-01 00:17:43 +01:00
hir::ImplItemKind::OpaqueTy(bounds) => {
2019-08-01 01:41:54 +02:00
self.word_space("type");
self.print_ident(ii.ident);
self.print_bounds("= impl", bounds);
self.s.word(";");
2018-07-03 19:38:14 +02:00
}
2015-07-31 09:04:06 +02:00
}
2019-02-26 11:04:58 +01:00
self.ann.post(self, AnnNode::SubItem(ii.hir_id))
2015-07-31 09:04:06 +02:00
}
2019-11-29 13:43:03 +01:00
pub fn print_local(&mut self, init: Option<&hir::Expr<'_>>, decl: impl Fn(&mut Self)) {
self.space_if_not_bol();
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
self.word_nbsp("let");
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
decl(self);
self.end();
if let Some(ref init) = init {
self.nbsp();
self.word_space("=");
self.print_expr(&init);
}
self.end()
}
2019-11-29 13:43:03 +01:00
pub fn print_stmt(&mut self, st: &hir::Stmt<'_>) {
self.maybe_print_comment(st.span.lo());
2019-09-26 18:34:50 +02:00
match st.kind {
hir::StmtKind::Local(ref loc) => {
2019-07-05 20:35:19 +02:00
self.print_local(loc.init.as_deref(), |this| this.print_local_decl(&loc));
}
2019-12-22 23:42:04 +01:00
hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)),
hir::StmtKind::Expr(ref expr) => {
self.space_if_not_bol();
self.print_expr(&expr);
2015-07-31 09:04:06 +02:00
}
hir::StmtKind::Semi(ref expr) => {
self.space_if_not_bol();
self.print_expr(&expr);
self.s.word(";");
2015-07-31 09:04:06 +02:00
}
}
2019-09-26 18:34:50 +02:00
if stmt_ends_with_semi(&st.kind) {
self.s.word(";");
2015-07-31 09:04:06 +02:00
}
self.maybe_print_trailing_comment(st.span, None)
}
2019-11-29 13:43:03 +01:00
pub fn print_block(&mut self, blk: &hir::Block<'_>) {
2015-07-31 09:04:06 +02:00
self.print_block_with_attrs(blk, &[])
}
2019-11-29 13:43:03 +01:00
pub fn print_block_unclosed(&mut self, blk: &hir::Block<'_>) {
self.print_block_maybe_unclosed(blk, &[], false)
2015-07-31 09:04:06 +02:00
}
2019-11-29 13:43:03 +01:00
pub fn print_block_with_attrs(&mut self, blk: &hir::Block<'_>, attrs: &[ast::Attribute]) {
self.print_block_maybe_unclosed(blk, attrs, true)
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
pub fn print_block_maybe_unclosed(
&mut self,
2019-11-29 13:43:03 +01:00
blk: &hir::Block<'_>,
2019-12-22 23:42:04 +01:00
attrs: &[ast::Attribute],
close_box: bool,
) {
2015-07-31 09:04:06 +02:00
match blk.rules {
2020-03-23 11:32:07 +01:00
hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"),
hir::BlockCheckMode::PushUnsafeBlock(..) => self.word_space("push_unsafe"),
hir::BlockCheckMode::PopUnsafeBlock(..) => self.word_space("pop_unsafe"),
hir::BlockCheckMode::DefaultBlock => (),
2015-07-31 09:04:06 +02:00
}
self.maybe_print_comment(blk.span.lo());
self.ann.pre(self, AnnNode::Block(blk));
self.bopen();
2015-07-31 09:04:06 +02:00
self.print_inner_attributes(attrs);
2015-07-31 09:04:06 +02:00
2019-11-29 14:08:03 +01:00
for st in blk.stmts {
self.print_stmt(st);
2015-07-31 09:04:06 +02:00
}
2018-09-12 12:31:11 +02:00
if let Some(ref expr) = blk.expr {
self.space_if_not_bol();
self.print_expr(&expr);
self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
2015-07-31 09:04:06 +02:00
}
self.bclose_maybe_open(blk.span, close_box);
2018-08-22 23:05:19 +02:00
self.ann.post(self, AnnNode::Block(blk))
2015-07-31 09:04:06 +02:00
}
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) {
self.ann.nested(self, Nested::Body(constant.body))
}
2015-07-31 09:04:06 +02:00
2019-11-29 13:43:03 +01:00
fn print_call_post(&mut self, args: &[hir::Expr<'_>]) {
self.popen();
self.commasep_exprs(Inconsistent, args);
2015-07-31 09:04:06 +02:00
self.pclose()
}
2019-11-29 13:43:03 +01:00
pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr<'_>, prec: i8) {
let needs_par = expr.precedence().order() < prec;
if needs_par {
self.popen();
}
self.print_expr(expr);
if needs_par {
self.pclose();
}
}
/// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
/// `if cond { ... }`.
2019-11-29 13:43:03 +01:00
pub fn print_expr_as_cond(&mut self, expr: &hir::Expr<'_>) {
let needs_par = match expr.kind {
// These cases need parens due to the parse error observed in #26461: `if return {}`
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
2019-12-22 23:42:04 +01:00
hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) | hir::ExprKind::Break(..) => true,
_ => contains_exterior_struct_lit(expr),
};
2015-07-31 09:04:06 +02:00
if needs_par {
self.popen();
2015-07-31 09:04:06 +02:00
}
self.print_expr(expr);
2015-07-31 09:04:06 +02:00
if needs_par {
self.pclose();
2015-07-31 09:04:06 +02:00
}
}
2019-11-29 13:43:03 +01:00
fn print_expr_vec(&mut self, exprs: &[hir::Expr<'_>]) {
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
self.s.word("[");
self.commasep_exprs(Inconsistent, exprs);
self.s.word("]");
2015-07-31 09:04:06 +02:00
self.end()
}
2019-11-29 13:43:03 +01:00
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) {
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
self.s.word("[");
self.print_expr(element);
self.word_space(";");
self.print_anon_const(count);
self.s.word("]");
2015-07-31 09:04:06 +02:00
self.end()
}
2019-12-22 23:42:04 +01:00
fn print_expr_struct(
&mut self,
2019-11-30 17:46:46 +01:00
qpath: &hir::QPath<'_>,
2019-11-29 13:43:03 +01:00
fields: &[hir::Field<'_>],
wth: &Option<&hir::Expr<'_>>,
2019-12-22 23:42:04 +01:00
) {
self.print_qpath(qpath, true);
self.s.word("{");
2019-12-22 23:42:04 +01:00
self.commasep_cmnt(
Consistent,
&fields[..],
|s, field| {
s.ibox(INDENT_UNIT);
if !field.is_shorthand {
s.print_ident(field.ident);
s.word_space(":");
}
s.print_expr(&field.expr);
s.end()
},
|f| f.span,
);
match *wth {
Some(ref expr) => {
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
if !fields.is_empty() {
self.s.word(",");
self.s.space();
2015-07-31 09:04:06 +02:00
}
self.s.word("..");
self.print_expr(&expr);
self.end();
}
2019-12-22 23:42:04 +01:00
_ => {
if !fields.is_empty() {
self.s.word(",")
}
}
2015-07-31 09:04:06 +02:00
}
self.s.word("}");
2015-07-31 09:04:06 +02:00
}
2019-11-29 13:43:03 +01:00
fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) {
self.popen();
self.commasep_exprs(Inconsistent, exprs);
2015-07-31 09:04:06 +02:00
if exprs.len() == 1 {
self.s.word(",");
2015-07-31 09:04:06 +02:00
}
self.pclose()
}
2019-11-29 13:43:03 +01:00
fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
let prec = match func.kind {
hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
_ => parser::PREC_POSTFIX,
};
self.print_expr_maybe_paren(func, prec);
2015-07-31 09:04:06 +02:00
self.print_call_post(args)
}
2019-11-30 17:46:46 +01:00
fn print_expr_method_call(&mut self, segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>]) {
2015-07-31 09:04:06 +02:00
let base_args = &args[1..];
self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
self.s.word(".");
self.print_ident(segment.ident);
let generic_args = segment.generic_args();
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
self.print_generic_args(generic_args, segment.infer_args, true);
}
2015-07-31 09:04:06 +02:00
self.print_call_post(base_args)
}
2019-11-29 13:43:03 +01:00
fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
let assoc_op = bin_op_to_assoc_op(op.node);
let prec = assoc_op.precedence() as i8;
let fixity = assoc_op.fixity();
let (left_prec, right_prec) = match fixity {
Fixity::Left => (prec, prec + 1),
Fixity::Right => (prec + 1, prec),
Fixity::None => (prec + 1, prec + 1),
};
let left_prec = match (&lhs.kind, op.node) {
// These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
// the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
// of `(x as i32) < ...`. We need to convince it _not_ to do that.
2019-12-22 23:42:04 +01:00
(&hir::ExprKind::Cast { .. }, hir::BinOpKind::Lt)
| (&hir::ExprKind::Cast { .. }, hir::BinOpKind::Shl) => parser::PREC_FORCE_PAREN,
_ => left_prec,
};
self.print_expr_maybe_paren(lhs, left_prec);
self.s.space();
self.word_space(op.node.as_str());
self.print_expr_maybe_paren(rhs, right_prec)
2015-07-31 09:04:06 +02:00
}
2019-11-29 13:43:03 +01:00
fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
self.s.word(op.as_str());
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
fn print_expr_addr_of(
&mut self,
kind: hir::BorrowKind,
mutability: hir::Mutability,
2019-11-29 13:43:03 +01:00
expr: &hir::Expr<'_>,
2019-12-22 23:42:04 +01:00
) {
self.s.word("&");
match kind {
hir::BorrowKind::Ref => self.print_mutability(mutability, false),
hir::BorrowKind::Raw => {
self.word_nbsp("raw");
self.print_mutability(mutability, true);
}
}
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
2015-07-31 09:04:06 +02:00
}
fn print_literal(&mut self, lit: &hir::Lit) {
self.maybe_print_comment(lit.span.lo());
2019-07-09 15:51:56 +02:00
self.word(lit.node.to_lit_token().to_string())
}
2019-11-29 13:43:03 +01:00
pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
self.maybe_print_comment(expr.span.lo());
self.print_outer_attributes(&expr.attrs);
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Expr(expr));
match expr.kind {
2018-07-11 14:05:29 +02:00
hir::ExprKind::Box(ref expr) => {
self.word_space("box");
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Array(ref exprs) => {
self.print_expr_vec(exprs);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Repeat(ref element, ref count) => {
self.print_expr_repeat(&element, count);
2015-07-31 09:04:06 +02:00
}
2019-11-29 14:08:03 +01:00
hir::ExprKind::Struct(ref qpath, fields, ref wth) => {
self.print_expr_struct(qpath, fields, wth);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Tup(ref exprs) => {
self.print_expr_tup(exprs);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(&func, args);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::MethodCall(ref segment, _, ref args) => {
self.print_expr_method_call(segment, args);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, &lhs, &rhs);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Unary(op, ref expr) => {
self.print_expr_unary(op, &expr);
2015-07-31 09:04:06 +02:00
}
hir::ExprKind::AddrOf(k, m, ref expr) => {
self.print_expr_addr_of(k, m, &expr);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Lit(ref lit) => {
self.print_literal(&lit);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Cast(ref expr, ref ty) => {
let prec = AssocOp::As.precedence() as i8;
self.print_expr_maybe_paren(&expr, prec);
self.s.space();
self.word_space("as");
self.print_type(&ty);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Type(ref expr, ref ty) => {
let prec = AssocOp::Colon.precedence() as i8;
self.print_expr_maybe_paren(&expr, prec);
self.word_space(":");
self.print_type(&ty);
}
hir::ExprKind::DropTemps(ref init) => {
// Print `{`:
2019-07-09 15:32:25 +02:00
self.cbox(INDENT_UNIT);
self.ibox(0);
self.bopen();
// Print `let _t = $init;`:
let temp = ast::Ident::from_str("_t");
self.print_local(Some(init), |this| this.print_ident(temp));
self.s.word(";");
// Print `_t`:
self.space_if_not_bol();
self.print_ident(temp);
// Print `}`:
self.bclose_maybe_open(expr.span, true);
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Loop(ref blk, opt_label, _) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
2015-07-31 09:04:06 +02:00
}
self.head("loop");
self.s.space();
self.print_block(&blk);
2015-07-31 09:04:06 +02:00
}
2019-11-29 14:08:03 +01:00
hir::ExprKind::Match(ref expr, arms, _) => {
2019-07-09 15:32:25 +02:00
self.cbox(INDENT_UNIT);
2019-07-09 15:49:37 +02:00
self.ibox(INDENT_UNIT);
self.word_nbsp("match");
self.print_expr_as_cond(&expr);
self.s.space();
self.bopen();
2015-07-31 09:04:06 +02:00
for arm in arms {
self.print_arm(arm);
2015-07-31 09:04:06 +02:00
}
2019-07-09 13:38:31 +02:00
self.bclose(expr.span);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => {
self.print_capture_clause(capture_clause);
2015-07-31 09:04:06 +02:00
self.print_closure_params(&decl, body);
self.s.space();
2015-07-31 09:04:06 +02:00
// This is a bare expression.
self.ann.nested(self, Nested::Body(body));
self.end(); // need to close a box
2015-07-31 09:04:06 +02:00
// A box will be closed by `print_expr`, but we didn't want an overall
2015-07-31 09:04:06 +02:00
// wrapper so we closed the corresponding opening. so create an
// empty box to satisfy the close.
self.ibox(0);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Block(ref blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
}
// containing cbox, will be closed by print-block at `}`
2019-07-09 15:32:25 +02:00
self.cbox(INDENT_UNIT);
// head-box, will be closed by print-block after `{`
self.ibox(0);
self.print_block(&blk);
2015-07-31 09:04:06 +02:00
}
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_maybe_paren(&lhs, prec + 1);
self.s.space();
self.word_space("=");
self.print_expr_maybe_paren(&rhs, prec);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_maybe_paren(&lhs, prec + 1);
self.s.space();
self.s.word(op.node.as_str());
self.word_space("=");
self.print_expr_maybe_paren(&rhs, prec);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Field(ref expr, ident) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
self.s.word(".");
self.print_ident(ident);
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Index(ref expr, ref index) => {
self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX);
self.s.word("[");
self.print_expr(&index);
self.s.word("]");
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true),
2018-07-11 14:05:29 +02:00
hir::ExprKind::Break(destination, ref opt_expr) => {
self.s.word("break");
self.s.space();
if let Some(label) = destination.label {
self.print_ident(label.ident);
self.s.space();
2015-07-31 09:04:06 +02:00
}
if let Some(ref expr) = *opt_expr {
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
self.s.space();
}
2015-07-31 09:04:06 +02:00
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Continue(destination) => {
self.s.word("continue");
self.s.space();
if let Some(label) = destination.label {
self.print_ident(label.ident);
self.s.space()
2015-07-31 09:04:06 +02:00
}
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::Ret(ref result) => {
self.s.word("return");
2018-09-12 12:31:11 +02:00
if let Some(ref expr) = *result {
self.s.word(" ");
self.print_expr_maybe_paren(&expr, parser::PREC_JUMP);
2015-07-31 09:04:06 +02:00
}
}
2019-11-18 14:43:34 +01:00
hir::ExprKind::InlineAsm(ref a) => {
let i = &a.inner;
self.s.word("asm!");
self.popen();
2019-11-18 14:43:34 +01:00
self.print_string(&i.asm.as_str(), i.asm_str_style);
self.word_space(":");
2015-07-31 09:04:06 +02:00
let mut out_idx = 0;
2019-11-18 14:43:34 +01:00
self.commasep(Inconsistent, &i.outputs, |s, out| {
let constraint = out.constraint.as_str();
let mut ch = constraint.chars();
std: Stabilize APIs for the 1.9 release This commit applies all stabilizations, renamings, and deprecations that the library team has decided on for the upcoming 1.9 release. All tracking issues have gone through a cycle-long "final comment period" and the specific APIs stabilized/deprecated are: Stable * `std::panic` * `std::panic::catch_unwind` (renamed from `recover`) * `std::panic::resume_unwind` (renamed from `propagate`) * `std::panic::AssertUnwindSafe` (renamed from `AssertRecoverSafe`) * `std::panic::UnwindSafe` (renamed from `RecoverSafe`) * `str::is_char_boundary` * `<*const T>::as_ref` * `<*mut T>::as_ref` * `<*mut T>::as_mut` * `AsciiExt::make_ascii_uppercase` * `AsciiExt::make_ascii_lowercase` * `char::decode_utf16` * `char::DecodeUtf16` * `char::DecodeUtf16Error` * `char::DecodeUtf16Error::unpaired_surrogate` * `BTreeSet::take` * `BTreeSet::replace` * `BTreeSet::get` * `HashSet::take` * `HashSet::replace` * `HashSet::get` * `OsString::with_capacity` * `OsString::clear` * `OsString::capacity` * `OsString::reserve` * `OsString::reserve_exact` * `OsStr::is_empty` * `OsStr::len` * `std::os::unix::thread` * `RawPthread` * `JoinHandleExt` * `JoinHandleExt::as_pthread_t` * `JoinHandleExt::into_pthread_t` * `HashSet::hasher` * `HashMap::hasher` * `CommandExt::exec` * `File::try_clone` * `SocketAddr::set_ip` * `SocketAddr::set_port` * `SocketAddrV4::set_ip` * `SocketAddrV4::set_port` * `SocketAddrV6::set_ip` * `SocketAddrV6::set_port` * `SocketAddrV6::set_flowinfo` * `SocketAddrV6::set_scope_id` * `<[T]>::copy_from_slice` * `ptr::read_volatile` * `ptr::write_volatile` * The `#[deprecated]` attribute * `OpenOptions::create_new` Deprecated * `std::raw::Slice` - use raw parts of `slice` module instead * `std::raw::Repr` - use raw parts of `slice` module instead * `str::char_range_at` - use slicing plus `chars()` plus `len_utf8` * `str::char_range_at_reverse` - use slicing plus `chars().rev()` plus `len_utf8` * `str::char_at` - use slicing plus `chars()` * `str::char_at_reverse` - use slicing plus `chars().rev()` * `str::slice_shift_char` - use `chars()` plus `Chars::as_str` * `CommandExt::session_leader` - use `before_exec` instead. Closes #27719 cc #27751 (deprecating the `Slice` bits) Closes #27754 Closes #27780 Closes #27809 Closes #27811 Closes #27830 Closes #28050 Closes #29453 Closes #29791 Closes #29935 Closes #30014 Closes #30752 Closes #31262 cc #31398 (still need to deal with `before_exec`) Closes #31405 Closes #31572 Closes #31755 Closes #31756
2016-04-07 19:42:53 +02:00
match ch.next() {
Some('=') if out.is_rw => {
2019-12-22 23:42:04 +01:00
s.print_string(&format!("+{}", ch.as_str()), ast::StrStyle::Cooked)
2015-11-05 22:17:59 +01:00
}
_ => s.print_string(&constraint, ast::StrStyle::Cooked),
2015-11-05 22:17:59 +01:00
}
s.popen();
2019-11-18 14:43:34 +01:00
s.print_expr(&a.outputs_exprs[out_idx]);
s.pclose();
out_idx += 1;
});
self.s.space();
self.word_space(":");
2015-07-31 09:04:06 +02:00
let mut in_idx = 0;
2019-11-18 14:43:34 +01:00
self.commasep(Inconsistent, &i.inputs, |s, co| {
s.print_string(&co.as_str(), ast::StrStyle::Cooked);
s.popen();
2019-11-18 14:43:34 +01:00
s.print_expr(&a.inputs_exprs[in_idx]);
s.pclose();
in_idx += 1;
});
self.s.space();
self.word_space(":");
2015-07-31 09:04:06 +02:00
2019-11-18 14:43:34 +01:00
self.commasep(Inconsistent, &i.clobbers, |s, co| {
s.print_string(&co.as_str(), ast::StrStyle::Cooked);
});
2015-07-31 09:04:06 +02:00
2015-11-05 22:17:59 +01:00
let mut options = vec![];
2019-11-18 14:43:34 +01:00
if i.volatile {
2015-07-31 09:04:06 +02:00
options.push("volatile");
}
2019-11-18 14:43:34 +01:00
if i.alignstack {
2015-07-31 09:04:06 +02:00
options.push("alignstack");
}
2019-11-18 14:43:34 +01:00
if i.dialect == ast::AsmDialect::Intel {
2015-07-31 09:04:06 +02:00
options.push("intel");
}
if !options.is_empty() {
self.s.space();
self.word_space(":");
self.commasep(Inconsistent, &options, |s, &co| {
s.print_string(co, ast::StrStyle::Cooked);
});
2015-07-31 09:04:06 +02:00
}
self.pclose();
2015-07-31 09:04:06 +02:00
}
hir::ExprKind::Yield(ref expr, _) => {
self.word_space("yield");
self.print_expr_maybe_paren(&expr, parser::PREC_JUMP);
2016-12-26 14:34:03 +01:00
}
hir::ExprKind::Err => {
self.popen();
self.s.word("/*ERROR*/");
self.pclose();
}
2015-07-31 09:04:06 +02:00
}
self.ann.post(self, AnnNode::Expr(expr));
2015-07-31 09:04:06 +02:00
self.end()
}
2019-11-29 13:43:03 +01:00
pub fn print_local_decl(&mut self, loc: &hir::Local<'_>) {
self.print_pat(&loc.pat);
2015-07-31 09:04:06 +02:00
if let Some(ref ty) = loc.ty {
self.word_space(":");
self.print_type(&ty);
2015-07-31 09:04:06 +02:00
}
}
pub fn print_usize(&mut self, i: usize) {
self.s.word(i.to_string())
2015-07-31 09:04:06 +02:00
}
pub fn print_name(&mut self, name: ast::Name) {
self.print_ident(ast::Ident::with_dummy_span(name))
2015-07-31 09:04:06 +02:00
}
2019-11-29 13:43:03 +01:00
pub fn print_for_decl(&mut self, loc: &hir::Local<'_>, coll: &hir::Expr<'_>) {
self.print_local_decl(loc);
self.s.space();
self.word_space("in");
2015-07-31 09:04:06 +02:00
self.print_expr(coll)
}
2019-11-30 17:46:46 +01:00
pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) {
self.maybe_print_comment(path.span.lo());
2015-07-31 09:04:06 +02:00
for (i, segment) in path.segments.iter().enumerate() {
if i > 0 {
self.s.word("::")
2015-07-31 09:04:06 +02:00
}
2019-05-11 16:41:37 +02:00
if segment.ident.name != kw::PathRoot {
self.print_ident(segment.ident);
2019-12-22 23:42:04 +01:00
self.print_generic_args(
segment.generic_args(),
segment.infer_args,
colons_before_params,
);
}
2015-07-31 09:04:06 +02:00
}
}
2019-11-30 17:46:46 +01:00
pub fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
2019-05-11 16:41:37 +02:00
if segment.ident.name != kw::PathRoot {
self.print_ident(segment.ident);
self.print_generic_args(segment.generic_args(), segment.infer_args, false);
}
}
2019-11-30 17:46:46 +01:00
pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool) {
match *qpath {
2019-12-22 23:42:04 +01:00
hir::QPath::Resolved(None, ref path) => self.print_path(path, colons_before_params),
hir::QPath::Resolved(Some(ref qself), ref path) => {
self.s.word("<");
self.print_type(qself);
self.s.space();
self.word_space("as");
for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
if i > 0 {
self.s.word("::")
}
2019-05-11 16:41:37 +02:00
if segment.ident.name != kw::PathRoot {
self.print_ident(segment.ident);
2019-12-22 23:42:04 +01:00
self.print_generic_args(
segment.generic_args(),
segment.infer_args,
colons_before_params,
);
}
}
self.s.word(">");
self.s.word("::");
let item_segment = path.segments.last().unwrap();
self.print_ident(item_segment.ident);
2019-12-22 23:42:04 +01:00
self.print_generic_args(
item_segment.generic_args(),
item_segment.infer_args,
colons_before_params,
)
}
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
// If we've got a compound-qualified-path, let's push an additional pair of angle
// brackets, so that we pretty-print `<<A::B>::C>` as `<A::B>::C`, instead of just
// `A::B::C` (since the latter could be ambiguous to the user)
if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = &qself.kind {
self.print_type(qself);
} else {
self.s.word("<");
self.print_type(qself);
self.s.word(">");
}
self.s.word("::");
self.print_ident(item_segment.ident);
2019-12-22 23:42:04 +01:00
self.print_generic_args(
item_segment.generic_args(),
item_segment.infer_args,
colons_before_params,
)
}
2015-07-31 09:04:06 +02:00
}
}
2019-12-22 23:42:04 +01:00
fn print_generic_args(
&mut self,
2019-11-30 17:46:46 +01:00
generic_args: &hir::GenericArgs<'_>,
2019-12-22 23:42:04 +01:00
infer_args: bool,
colons_before_params: bool,
) {
if generic_args.parenthesized {
self.s.word("(");
self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty));
self.s.word(")");
2015-07-31 09:04:06 +02:00
self.space_if_not_bol();
self.word_space("->");
self.print_type(generic_args.bindings[0].ty());
} else {
let start = if colons_before_params { "::<" } else { "<" };
let empty = Cell::new(true);
let start_or_comma = |this: &mut Self| {
if empty.get() {
empty.set(false);
this.s.word(start)
} else {
this.word_space(",")
2015-07-31 09:04:06 +02:00
}
};
2015-07-31 09:04:06 +02:00
let mut nonelided_generic_args: bool = false;
let elide_lifetimes = generic_args.args.iter().all(|arg| match arg {
GenericArg::Lifetime(lt) => lt.is_elided(),
_ => {
nonelided_generic_args = true;
true
}
});
if nonelided_generic_args {
start_or_comma(self);
2019-12-22 23:42:04 +01:00
self.commasep(
Inconsistent,
&generic_args.args,
|s, generic_arg| match generic_arg {
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
2019-12-22 23:42:04 +01:00
GenericArg::Lifetime(_) => {}
GenericArg::Type(ty) => s.print_type(ty),
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
2019-12-22 23:42:04 +01:00
},
);
2018-02-12 22:44:05 +01:00
}
// FIXME(eddyb): this would leak into error messages (e.g.,
// "non-exhaustive patterns: `Some::<..>(_)` not covered").
2019-06-07 11:18:03 +02:00
if infer_args && false {
start_or_comma(self);
self.s.word("..");
2015-07-31 09:04:06 +02:00
}
for binding in generic_args.bindings.iter() {
start_or_comma(self);
self.print_ident(binding.ident);
self.s.space();
2019-05-08 21:57:06 +02:00
match generic_args.bindings[0].kind {
hir::TypeBindingKind::Equality { ref ty } => {
self.word_space("=");
self.print_type(ty);
2019-05-08 21:57:06 +02:00
}
2019-12-01 00:17:43 +01:00
hir::TypeBindingKind::Constraint { bounds } => {
self.print_bounds(":", bounds);
2019-05-08 21:57:06 +02:00
}
}
}
2015-07-31 09:04:06 +02:00
if !empty.get() {
self.s.word(">")
2015-07-31 09:04:06 +02:00
}
}
}
2019-11-29 13:43:03 +01:00
pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
self.maybe_print_comment(pat.span.lo());
self.ann.pre(self, AnnNode::Pat(pat));
2015-11-05 22:17:59 +01:00
// Pat isn't normalized, but the beauty of it
// is that it doesn't matter
2019-09-26 17:18:31 +02:00
match pat.kind {
PatKind::Wild => self.s.word("_"),
2019-03-07 12:18:59 +01:00
PatKind::Binding(binding_mode, _, ident, ref sub) => {
2015-07-31 09:04:06 +02:00
match binding_mode {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Not, false);
2015-07-31 09:04:06 +02:00
}
hir::BindingAnnotation::RefMut => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Mut, false);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => {
self.word_nbsp("mut");
2015-07-31 09:04:06 +02:00
}
}
self.print_ident(ident);
if let Some(ref p) = *sub {
self.s.word("@");
self.print_pat(&p);
2015-07-31 09:04:06 +02:00
}
}
PatKind::TupleStruct(ref qpath, ref elts, ddpos) => {
self.print_qpath(qpath, true);
self.popen();
if let Some(ddpos) = ddpos {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p));
if ddpos != 0 {
self.word_space(",");
}
self.s.word("..");
if ddpos != elts.len() {
self.s.word(",");
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p));
2015-07-31 09:04:06 +02:00
}
} else {
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p));
2015-07-31 09:04:06 +02:00
}
self.pclose();
2015-07-31 09:04:06 +02:00
}
PatKind::Path(ref qpath) => {
self.print_qpath(qpath, true);
2015-07-31 09:04:06 +02:00
}
PatKind::Struct(ref qpath, ref fields, etc) => {
self.print_qpath(qpath, true);
self.nbsp();
self.word_space("{");
2019-12-22 23:42:04 +01:00
self.commasep_cmnt(
Consistent,
&fields[..],
|s, f| {
s.cbox(INDENT_UNIT);
if !f.is_shorthand {
s.print_ident(f.ident);
s.word_nbsp(":");
}
s.print_pat(&f.pat);
s.end()
},
|f| f.pat.span,
);
2015-07-31 09:04:06 +02:00
if etc {
2015-09-27 21:23:31 +02:00
if !fields.is_empty() {
self.word_space(",");
2015-09-27 21:23:31 +02:00
}
self.s.word("..");
2015-07-31 09:04:06 +02:00
}
self.s.space();
self.s.word("}");
2015-07-31 09:04:06 +02:00
}
2018-10-19 16:40:07 +02:00
PatKind::Or(ref pats) => {
self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p));
2018-10-19 16:40:07 +02:00
}
PatKind::Tuple(ref elts, ddpos) => {
self.popen();
if let Some(ddpos) = ddpos {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p));
if ddpos != 0 {
self.word_space(",");
}
self.s.word("..");
if ddpos != elts.len() {
self.s.word(",");
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p));
}
} else {
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p));
if elts.len() == 1 {
self.s.word(",");
}
2015-07-31 09:04:06 +02:00
}
self.pclose();
2015-07-31 09:04:06 +02:00
}
2016-02-14 13:25:12 +01:00
PatKind::Box(ref inner) => {
2019-09-26 17:18:31 +02:00
let is_range_inner = match inner.kind {
PatKind::Range(..) => true,
_ => false,
};
self.s.word("box ");
if is_range_inner {
self.popen();
}
self.print_pat(&inner);
if is_range_inner {
self.pclose();
}
2015-07-31 09:04:06 +02:00
}
2016-02-14 13:25:12 +01:00
PatKind::Ref(ref inner, mutbl) => {
2019-09-26 17:18:31 +02:00
let is_range_inner = match inner.kind {
PatKind::Range(..) => true,
_ => false,
};
self.s.word("&");
2019-10-30 20:55:38 +01:00
self.s.word(mutbl.prefix_str());
if is_range_inner {
self.popen();
}
self.print_pat(&inner);
if is_range_inner {
self.pclose();
}
2015-07-31 09:04:06 +02:00
}
PatKind::Lit(ref e) => self.print_expr(&e),
PatKind::Range(ref begin, ref end, ref end_kind) => {
if let Some(expr) = begin {
self.print_expr(expr);
self.s.space();
}
match *end_kind {
RangeEnd::Included => self.s.word("..."),
RangeEnd::Excluded => self.s.word(".."),
}
if let Some(expr) = end {
self.print_expr(expr);
}
2015-07-31 09:04:06 +02:00
}
PatKind::Slice(ref before, ref slice, ref after) => {
self.s.word("[");
self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p));
2015-07-31 09:04:06 +02:00
if let Some(ref p) = *slice {
2015-09-27 21:23:31 +02:00
if !before.is_empty() {
self.word_space(",");
2015-09-27 21:23:31 +02:00
}
2019-09-26 17:18:31 +02:00
if let PatKind::Wild = p.kind {
// Print nothing.
} else {
self.print_pat(&p);
2015-07-31 09:04:06 +02:00
}
self.s.word("..");
2015-09-27 21:23:31 +02:00
if !after.is_empty() {
self.word_space(",");
2015-09-27 21:23:31 +02:00
}
2015-07-31 09:04:06 +02:00
}
self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p));
self.s.word("]");
2015-07-31 09:04:06 +02:00
}
}
2018-08-22 23:05:19 +02:00
self.ann.post(self, AnnNode::Pat(pat))
2015-07-31 09:04:06 +02:00
}
2019-11-29 13:43:03 +01:00
pub fn print_param(&mut self, arg: &hir::Param<'_>) {
2019-07-27 00:52:37 +02:00
self.print_outer_attributes(&arg.attrs);
self.print_pat(&arg.pat);
}
2019-11-29 13:43:03 +01:00
pub fn print_arm(&mut self, arm: &hir::Arm<'_>) {
2015-07-31 09:04:06 +02:00
// I have no idea why this check is necessary, but here it
// is :(
if arm.attrs.is_empty() {
self.s.space();
2015-07-31 09:04:06 +02:00
}
2019-07-09 15:32:25 +02:00
self.cbox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Arm(arm));
self.ibox(0);
self.print_outer_attributes(&arm.attrs);
self.print_pat(&arm.pat);
self.s.space();
2018-08-30 06:18:11 +02:00
if let Some(ref g) = arm.guard {
match g {
hir::Guard::If(e) => {
self.word_space("if");
self.print_expr(&e);
self.s.space();
2018-08-30 06:18:11 +02:00
}
}
2015-07-31 09:04:06 +02:00
}
self.word_space("=>");
2015-07-31 09:04:06 +02:00
match arm.body.kind {
2018-07-11 14:05:29 +02:00
hir::ExprKind::Block(ref blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
}
2015-07-31 09:04:06 +02:00
// the block will close the pattern's ibox
self.print_block_unclosed(&blk);
2015-07-31 09:04:06 +02:00
// If it is a user-provided unsafe block, print a comma after it
2020-03-23 11:32:07 +01:00
if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules
{
self.s.word(",");
2015-07-31 09:04:06 +02:00
}
}
_ => {
self.end(); // close the ibox for the pattern
self.print_expr(&arm.body);
self.s.word(",");
2015-07-31 09:04:06 +02:00
}
}
self.ann.post(self, AnnNode::Arm(arm));
2015-07-31 09:04:06 +02:00
self.end() // close enclosing cbox
}
2019-12-22 23:42:04 +01:00
pub fn print_fn(
&mut self,
2019-11-30 17:46:46 +01:00
decl: &hir::FnDecl<'_>,
2019-12-22 23:42:04 +01:00
header: hir::FnHeader,
name: Option<ast::Name>,
2019-11-30 17:46:46 +01:00
generics: &hir::Generics<'_>,
vis: &hir::Visibility<'_>,
2019-12-22 23:42:04 +01:00
arg_names: &[ast::Ident],
body_id: Option<hir::BodyId>,
) {
self.print_fn_header_info(header, vis);
2015-07-31 09:04:06 +02:00
if let Some(name) = name {
self.nbsp();
self.print_name(name);
2015-07-31 09:04:06 +02:00
}
self.print_generic_params(&generics.params);
2015-07-31 09:04:06 +02:00
self.popen();
let mut i = 0;
// Make sure we aren't supplied *both* `arg_names` and `body_id`.
assert!(arg_names.is_empty() || body_id.is_none());
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
2019-07-09 15:32:25 +02:00
s.ibox(INDENT_UNIT);
if let Some(arg_name) = arg_names.get(i) {
s.s.word(arg_name.to_string());
s.s.word(":");
s.s.space();
} else if let Some(body_id) = body_id {
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
s.s.word(":");
s.s.space();
}
i += 1;
s.print_type(ty);
s.end()
});
if decl.c_variadic {
self.s.word(", ...");
2015-07-31 09:04:06 +02:00
}
self.pclose();
2015-07-31 09:04:06 +02:00
self.print_fn_output(decl);
self.print_where_clause(&generics.where_clause)
2015-07-31 09:04:06 +02:00
}
2019-11-30 17:46:46 +01:00
fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) {
self.s.word("|");
let mut i = 0;
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
2019-07-09 15:32:25 +02:00
s.ibox(INDENT_UNIT);
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
i += 1;
2019-09-26 18:25:31 +02:00
if let hir::TyKind::Infer = ty.kind {
// Print nothing.
} else {
s.s.word(":");
s.s.space();
s.print_type(ty);
}
s.end();
});
self.s.word("|");
2015-07-31 09:04:06 +02:00
2020-03-23 11:32:07 +01:00
if let hir::FnRetTy::DefaultReturn(..) = decl.output {
return;
2015-07-31 09:04:06 +02:00
}
self.space_if_not_bol();
self.word_space("->");
2015-07-31 09:04:06 +02:00
match decl.output {
2020-03-23 11:32:07 +01:00
hir::FnRetTy::Return(ref ty) => {
self.print_type(&ty);
2017-07-31 22:04:34 +02:00
self.maybe_print_comment(ty.span.lo())
2015-07-31 09:04:06 +02:00
}
2020-03-23 11:32:07 +01:00
hir::FnRetTy::DefaultReturn(..) => unreachable!(),
2015-07-31 09:04:06 +02:00
}
}
pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
2015-07-31 09:04:06 +02:00
match capture_clause {
hir::CaptureBy::Value => self.word_space("move"),
2019-12-22 23:42:04 +01:00
hir::CaptureBy::Ref => {}
2015-07-31 09:04:06 +02:00
}
}
2019-06-12 10:43:15 +02:00
pub fn print_bounds<'b>(
&mut self,
prefix: &'static str,
2019-11-30 17:46:46 +01:00
bounds: impl IntoIterator<Item = &'b hir::GenericBound<'b>>,
) {
2019-06-12 10:43:15 +02:00
let mut first = true;
for bound in bounds {
if first {
self.s.word(prefix);
2019-06-12 10:43:15 +02:00
}
if !(first && prefix.is_empty()) {
self.nbsp();
2019-06-12 10:43:15 +02:00
}
if first {
first = false;
} else {
self.word_space("+");
2019-06-12 10:43:15 +02:00
}
2015-07-31 09:04:06 +02:00
2019-06-12 10:43:15 +02:00
match bound {
GenericBound::Trait(tref, modifier) => {
if modifier == &TraitBoundModifier::Maybe {
self.s.word("?");
2015-07-31 09:04:06 +02:00
}
self.print_poly_trait_ref(tref);
2019-06-12 10:43:15 +02:00
}
GenericBound::Outlives(lt) => {
self.print_lifetime(lt);
}
2015-07-31 09:04:06 +02:00
}
}
}
2019-11-30 17:46:46 +01:00
pub fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) {
if !generic_params.is_empty() {
self.s.word("<");
2015-07-31 09:04:06 +02:00
2019-12-22 23:42:04 +01:00
self.commasep(Inconsistent, generic_params, |s, param| s.print_generic_param(param));
2015-07-31 09:04:06 +02:00
self.s.word(">");
2015-07-31 09:04:06 +02:00
}
}
2019-11-30 17:46:46 +01:00
pub fn print_generic_param(&mut self, param: &GenericParam<'_>) {
if let GenericParamKind::Const { .. } = param.kind {
self.word_space("const");
}
self.print_ident(param.name.ident());
2018-05-26 01:27:54 +02:00
match param.kind {
2018-05-28 14:33:28 +02:00
GenericParamKind::Lifetime { .. } => {
2018-05-26 01:27:54 +02:00
let mut sep = ":";
2019-12-01 00:17:43 +01:00
for bound in param.bounds {
2018-05-28 14:33:28 +02:00
match bound {
2019-12-01 00:17:43 +01:00
GenericBound::Outlives(ref lt) => {
self.s.word(sep);
self.print_lifetime(lt);
2018-05-28 14:33:28 +02:00
sep = "+";
}
_ => panic!(),
2018-05-28 14:33:28 +02:00
}
2018-05-26 01:27:54 +02:00
}
}
2018-05-28 14:33:28 +02:00
GenericParamKind::Type { ref default, .. } => {
2019-12-01 00:17:43 +01:00
self.print_bounds(":", param.bounds);
2018-05-26 01:27:54 +02:00
match default {
Some(default) => {
self.s.space();
self.word_space("=");
2018-05-26 01:27:54 +02:00
self.print_type(&default)
}
_ => {}
2018-05-26 01:27:54 +02:00
}
2015-07-31 09:04:06 +02:00
}
GenericParamKind::Const { ref ty } => {
self.word_space(":");
self.print_type(ty)
}
2015-07-31 09:04:06 +02:00
}
}
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) {
2018-06-27 23:12:17 +02:00
self.print_ident(lifetime.name.ident())
2018-05-26 01:27:54 +02:00
}
2019-11-30 17:46:46 +01:00
pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause<'_>) {
2015-07-31 09:04:06 +02:00
if where_clause.predicates.is_empty() {
return;
2015-07-31 09:04:06 +02:00
}
self.s.space();
self.word_space("where");
2015-07-31 09:04:06 +02:00
for (i, predicate) in where_clause.predicates.iter().enumerate() {
if i != 0 {
self.word_space(",");
2015-07-31 09:04:06 +02:00
}
match predicate {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
ref bound_generic_params,
ref bounded_ty,
2019-12-01 00:17:43 +01:00
bounds,
..
}) => {
self.print_formal_generic_params(bound_generic_params);
self.print_type(&bounded_ty);
self.print_bounds(":", bounds);
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
ref lifetime,
ref bounds,
..
}) => {
self.print_lifetime(lifetime);
self.s.word(":");
2015-07-31 09:04:06 +02:00
for (i, bound) in bounds.iter().enumerate() {
match bound {
GenericBound::Outlives(lt) => {
self.print_lifetime(lt);
}
_ => panic!(),
}
2015-07-31 09:04:06 +02:00
if i != 0 {
self.s.word(":");
2015-07-31 09:04:06 +02:00
}
}
}
2019-12-22 23:42:04 +01:00
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
ref lhs_ty,
ref rhs_ty,
..
}) => {
self.print_type(lhs_ty);
self.s.space();
self.word_space("=");
self.print_type(rhs_ty);
2015-07-31 09:04:06 +02:00
}
}
}
}
pub fn print_mutability(&mut self, mutbl: hir::Mutability, print_const: bool) {
2015-07-31 09:04:06 +02:00
match mutbl {
hir::Mutability::Mut => self.word_nbsp("mut"),
2019-12-22 23:42:04 +01:00
hir::Mutability::Not => {
if print_const {
self.word_nbsp("const")
}
}
2015-07-31 09:04:06 +02:00
}
}
2019-11-30 17:46:46 +01:00
pub fn print_mt(&mut self, mt: &hir::MutTy<'_>, print_const: bool) {
self.print_mutability(mt.mutbl, print_const);
self.print_type(&mt.ty)
2015-07-31 09:04:06 +02:00
}
2019-11-30 17:46:46 +01:00
pub fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) {
2020-03-23 11:32:07 +01:00
if let hir::FnRetTy::DefaultReturn(..) = decl.output {
return;
2015-07-31 09:04:06 +02:00
}
self.space_if_not_bol();
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
self.word_space("->");
2015-07-31 09:04:06 +02:00
match decl.output {
2020-03-23 11:32:07 +01:00
hir::FnRetTy::DefaultReturn(..) => unreachable!(),
hir::FnRetTy::Return(ref ty) => self.print_type(&ty),
2015-07-31 09:04:06 +02:00
}
self.end();
2015-07-31 09:04:06 +02:00
match decl.output {
2020-03-23 11:32:07 +01:00
hir::FnRetTy::Return(ref output) => self.maybe_print_comment(output.span.lo()),
2019-12-22 23:42:04 +01:00
_ => {}
2015-07-31 09:04:06 +02:00
}
}
2019-12-22 23:42:04 +01:00
pub fn print_ty_fn(
&mut self,
abi: Abi,
unsafety: hir::Unsafety,
2019-11-30 17:46:46 +01:00
decl: &hir::FnDecl<'_>,
2019-12-22 23:42:04 +01:00
name: Option<ast::Name>,
2019-11-30 17:46:46 +01:00
generic_params: &[hir::GenericParam<'_>],
2019-12-22 23:42:04 +01:00
arg_names: &[ast::Ident],
) {
2019-07-09 15:32:25 +02:00
self.ibox(INDENT_UNIT);
if !generic_params.is_empty() {
self.s.word("for");
self.print_generic_params(generic_params);
2015-07-31 09:04:06 +02:00
}
let generics = hir::Generics {
2019-12-01 17:10:12 +01:00
params: &[],
where_clause: hir::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP },
span: rustc_span::DUMMY_SP,
2015-07-31 09:04:06 +02:00
};
2019-12-22 23:42:04 +01:00
self.print_fn(
decl,
hir::FnHeader {
unsafety,
abi,
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
name,
&generics,
&Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited },
2019-12-22 23:42:04 +01:00
arg_names,
None,
);
self.end();
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
pub fn maybe_print_trailing_comment(
&mut self,
span: rustc_span::Span,
2019-12-22 23:42:04 +01:00
next_pos: Option<BytePos>,
) {
if let Some(cmnts) = self.comments() {
if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
self.print_comment(&cmnt);
2015-07-31 09:04:06 +02:00
}
}
}
pub fn print_remaining_comments(&mut self) {
2015-07-31 09:04:06 +02:00
// 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() {
self.s.hardbreak();
2015-07-31 09:04:06 +02:00
}
2018-03-05 19:58:54 +01:00
while let Some(ref cmnt) = self.next_comment() {
self.print_comment(cmnt)
2015-07-31 09:04:06 +02:00
}
}
2019-12-22 23:42:04 +01:00
pub fn print_opt_abi_and_extern_if_nondefault(&mut self, opt_abi: Option<Abi>) {
2015-07-31 09:04:06 +02:00
match opt_abi {
2019-12-22 23:42:04 +01:00
Some(Abi::Rust) => {}
2015-07-31 09:04:06 +02:00
Some(abi) => {
self.word_nbsp("extern");
self.word_nbsp(abi.to_string())
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
None => {}
2015-07-31 09:04:06 +02:00
}
}
pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) {
2015-07-31 09:04:06 +02:00
match opt_abi {
Some(abi) => {
self.word_nbsp("extern");
self.word_nbsp(abi.to_string())
2015-07-31 09:04:06 +02:00
}
2019-12-22 23:42:04 +01:00
None => {}
2015-07-31 09:04:06 +02:00
}
}
2019-11-30 17:46:46 +01:00
pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) {
self.s.word(visibility_qualified(vis, ""));
2015-07-31 09:04:06 +02:00
match header.constness {
2015-07-31 09:04:06 +02:00
hir::Constness::NotConst => {}
hir::Constness::Const => self.word_nbsp("const"),
2015-07-31 09:04:06 +02:00
}
match header.asyncness {
hir::IsAsync::NotAsync => {}
hir::IsAsync::Async => self.word_nbsp("async"),
}
self.print_unsafety(header.unsafety);
if header.abi != Abi::Rust {
self.word_nbsp("extern");
self.word_nbsp(header.abi.to_string());
2015-07-31 09:04:06 +02:00
}
self.s.word("fn")
2015-07-31 09:04:06 +02:00
}
pub fn print_unsafety(&mut self, s: hir::Unsafety) {
2015-07-31 09:04:06 +02:00
match s {
hir::Unsafety::Normal => {}
2015-07-31 09:04:06 +02:00
hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
}
}
pub fn print_is_auto(&mut self, s: hir::IsAuto) {
match s {
hir::IsAuto::Yes => self.word_nbsp("auto"),
2019-12-22 23:42:04 +01:00
hir::IsAuto::No => {}
}
}
2015-07-31 09:04:06 +02:00
}
/// 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
//
// Duplicated from `parse::classify`, but adapted for the HIR.
2019-11-29 13:43:03 +01:00
fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool {
match e.kind {
2019-12-22 23:42:04 +01:00
hir::ExprKind::Match(..) | hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) => false,
2015-09-27 21:23:31 +02:00
_ => true,
2015-07-31 09:04:06 +02:00
}
}
/// This statement requires a semicolon after it.
2015-07-31 09:04:06 +02:00
/// note that in one case (stmt_semi), we've already
/// seen the semicolon, and thus don't need another.
2019-11-29 13:43:03 +01:00
fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool {
2015-07-31 09:04:06 +02:00
match *stmt {
hir::StmtKind::Local(_) => true,
hir::StmtKind::Item(_) => false,
hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e),
hir::StmtKind::Semi(..) => false,
2015-07-31 09:04:06 +02:00
}
}
2018-07-11 12:44:53 +02:00
fn bin_op_to_assoc_op(op: hir::BinOpKind) -> AssocOp {
2019-02-05 18:20:45 +01:00
use crate::hir::BinOpKind::*;
match op {
2018-07-11 12:44:53 +02:00
Add => AssocOp::Add,
Sub => AssocOp::Subtract,
Mul => AssocOp::Multiply,
Div => AssocOp::Divide,
Rem => AssocOp::Modulus,
And => AssocOp::LAnd,
Or => AssocOp::LOr,
BitXor => AssocOp::BitXor,
BitAnd => AssocOp::BitAnd,
BitOr => AssocOp::BitOr,
Shl => AssocOp::ShiftLeft,
Shr => AssocOp::ShiftRight,
Eq => AssocOp::Equal,
Lt => AssocOp::Less,
Le => AssocOp::LessEqual,
Ne => AssocOp::NotEqual,
Ge => AssocOp::GreaterEqual,
Gt => AssocOp::Greater,
}
}
/// Expressions that syntactically contain an "exterior" struct literal, i.e., not surrounded by any
/// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
/// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
2019-11-29 13:43:03 +01:00
fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool {
match value.kind {
2018-07-11 14:05:29 +02:00
hir::ExprKind::Struct(..) => true,
hir::ExprKind::Assign(ref lhs, ref rhs, _)
2019-12-22 23:42:04 +01:00
| hir::ExprKind::AssignOp(_, ref lhs, ref rhs)
| hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
// `X { y: 1 } + X { y: 2 }`
contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs)
}
2019-12-22 23:42:04 +01:00
hir::ExprKind::Unary(_, ref x)
| hir::ExprKind::Cast(ref x, _)
| hir::ExprKind::Type(ref x, _)
| hir::ExprKind::Field(ref x, _)
| hir::ExprKind::Index(ref x, _) => {
// `&X { y: 1 }, X { y: 1 }.y`
contains_exterior_struct_lit(&x)
}
2018-07-11 14:05:29 +02:00
hir::ExprKind::MethodCall(.., ref exprs) => {
// `X { y: 1 }.bar(...)`
contains_exterior_struct_lit(&exprs[0])
}
_ => false,
}
}