Auto merge of #62561 - Centril:rollup-5pxj3bo, r=Centril
Rollup of 5 pull requests Successful merges: - #62275 (rustc_mir: treat DropAndReplace as Drop + Assign in qualify_consts.) - #62465 (Sometimes generate storage statements for temporaries with type `!`) - #62481 (Use `fold` in `Iterator::last` default implementation) - #62493 (#62357: doc(ptr): add example for {read,write}_unaligned) - #62532 (Some more cleanups to syntax::print) Failed merges: r? @ghost
This commit is contained in:
commit
35cacbce16
@ -263,9 +263,7 @@ pub trait Iterator {
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn last(self) -> Option<Self::Item> where Self: Sized {
|
||||
let mut last = None;
|
||||
for x in self { last = Some(x); }
|
||||
last
|
||||
self.fold(None, |_, x| Some(x))
|
||||
}
|
||||
|
||||
/// Returns the `n`th element of the iterator.
|
||||
|
@ -669,6 +669,22 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
||||
///
|
||||
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
|
||||
// FIXME: Update docs based on outcome of RFC #2582 and friends.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read an usize value from a byte buffer:
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// fn read_usize(x: &[u8]) -> usize {
|
||||
/// assert!(x.len() >= mem::size_of::<usize>());
|
||||
///
|
||||
/// let ptr = x.as_ptr() as *const usize;
|
||||
///
|
||||
/// unsafe { ptr.read_unaligned() }
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
||||
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
||||
@ -839,6 +855,22 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
||||
///
|
||||
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
|
||||
// FIXME: Update docs based on outcome of RFC #2582 and friends.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write an usize value to a byte buffer:
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// fn write_usize(x: &mut [u8], val: usize) {
|
||||
/// assert!(x.len() >= mem::size_of::<usize>());
|
||||
///
|
||||
/// let ptr = x.as_mut_ptr() as *mut usize;
|
||||
///
|
||||
/// unsafe { ptr.write_unaligned(val) }
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
||||
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
|
||||
|
@ -1212,10 +1212,8 @@ impl<'a> print::State<'a> {
|
||||
Node::Pat(a) => self.print_pat(&a),
|
||||
Node::Arm(a) => self.print_arm(&a),
|
||||
Node::Block(a) => {
|
||||
use syntax::print::pprust::PrintState;
|
||||
|
||||
// containing cbox, will be closed by print-block at }
|
||||
self.cbox(print::indent_unit);
|
||||
self.cbox(print::INDENT_UNIT);
|
||||
// head-ibox, will be closed by print-block after {
|
||||
self.ibox(0);
|
||||
self.print_block(&a)
|
||||
|
@ -2,10 +2,9 @@ use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::source_map::{SourceMap, Spanned};
|
||||
use syntax::parse::ParseSess;
|
||||
use syntax::parse::lexer::comments;
|
||||
use syntax::print::pp::{self, Breaks};
|
||||
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
|
||||
use syntax::print::pprust::{self, PrintState};
|
||||
use syntax::print::pprust::{Comments, PrintState};
|
||||
use syntax::symbol::kw;
|
||||
use syntax::util::parser::{self, AssocOp, Fixity};
|
||||
use syntax_pos::{self, BytePos, FileName};
|
||||
@ -17,7 +16,6 @@ use crate::hir::ptr::P;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
use std::io::Read;
|
||||
use std::vec;
|
||||
|
||||
pub enum AnnNode<'a> {
|
||||
@ -70,34 +68,31 @@ impl PpAnn for hir::Crate {
|
||||
}
|
||||
|
||||
pub struct State<'a> {
|
||||
pub s: pp::Printer<'a>,
|
||||
cm: Option<&'a SourceMap>,
|
||||
comments: Option<Vec<comments::Comment>>,
|
||||
cur_cmnt: usize,
|
||||
boxes: Vec<pp::Breaks>,
|
||||
pub s: pp::Printer,
|
||||
comments: Option<Comments<'a>>,
|
||||
ann: &'a (dyn 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(&mut self) -> &mut usize {
|
||||
&mut self.cur_cmnt
|
||||
impl std::ops::Deref for State<'_> {
|
||||
type Target = pp::Printer;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.s
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const indent_unit: usize = 4;
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
pub const INDENT_UNIT: usize = 4;
|
||||
|
||||
/// Requires you to pass an input filename and reader so that
|
||||
/// it can scan the input text for comments to copy forward.
|
||||
@ -105,11 +100,9 @@ pub fn print_crate<'a>(cm: &'a SourceMap,
|
||||
sess: &ParseSess,
|
||||
krate: &hir::Crate,
|
||||
filename: FileName,
|
||||
input: &mut dyn Read,
|
||||
out: &'a mut String,
|
||||
ann: &'a dyn PpAnn)
|
||||
{
|
||||
let mut s = State::new_from_input(cm, sess, filename, input, out, ann);
|
||||
input: String,
|
||||
ann: &'a dyn PpAnn) -> String {
|
||||
let mut s = State::new_from_input(cm, sess, filename, input, ann);
|
||||
|
||||
// When printing the AST, we sometimes need to inject `#[no_std]` here.
|
||||
// Since you can't compile the HIR, it's not necessary.
|
||||
@ -123,25 +116,12 @@ impl<'a> State<'a> {
|
||||
pub fn new_from_input(cm: &'a SourceMap,
|
||||
sess: &ParseSess,
|
||||
filename: FileName,
|
||||
input: &mut dyn Read,
|
||||
out: &'a mut String,
|
||||
input: String,
|
||||
ann: &'a dyn PpAnn)
|
||||
-> State<'a> {
|
||||
let comments = comments::gather_comments(sess, filename, input);
|
||||
State::new(cm, out, ann, Some(comments))
|
||||
}
|
||||
|
||||
pub fn new(cm: &'a SourceMap,
|
||||
out: &'a mut String,
|
||||
ann: &'a dyn PpAnn,
|
||||
comments: Option<Vec<comments::Comment>>)
|
||||
-> State<'a> {
|
||||
State {
|
||||
s: pp::mk_printer(out),
|
||||
cm: Some(cm),
|
||||
comments,
|
||||
cur_cmnt: 0,
|
||||
boxes: Vec::new(),
|
||||
s: pp::mk_printer(),
|
||||
comments: Some(Comments::new(cm, sess, filename, input)),
|
||||
ann,
|
||||
}
|
||||
}
|
||||
@ -150,20 +130,13 @@ impl<'a> State<'a> {
|
||||
pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
|
||||
where F: FnOnce(&mut State<'_>)
|
||||
{
|
||||
let mut wr = String::new();
|
||||
{
|
||||
let mut printer = State {
|
||||
s: pp::mk_printer(&mut wr),
|
||||
cm: None,
|
||||
comments: None,
|
||||
cur_cmnt: 0,
|
||||
boxes: Vec::new(),
|
||||
ann,
|
||||
};
|
||||
f(&mut printer);
|
||||
printer.s.eof();
|
||||
}
|
||||
wr
|
||||
let mut printer = State {
|
||||
s: pp::mk_printer(),
|
||||
comments: None,
|
||||
ann,
|
||||
};
|
||||
f(&mut printer);
|
||||
printer.s.eof()
|
||||
}
|
||||
|
||||
pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility, w: S) -> String {
|
||||
@ -175,7 +148,6 @@ pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility, w
|
||||
|
||||
impl<'a> State<'a> {
|
||||
pub fn cbox(&mut self, u: usize) {
|
||||
self.boxes.push(pp::Breaks::Consistent);
|
||||
self.s.cbox(u);
|
||||
}
|
||||
|
||||
@ -191,7 +163,7 @@ impl<'a> State<'a> {
|
||||
pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
|
||||
let w = w.into();
|
||||
// outer-box is consistent
|
||||
self.cbox(indent_unit);
|
||||
self.cbox(INDENT_UNIT);
|
||||
// head-box is inconsistent
|
||||
self.ibox(w.len() + 1);
|
||||
// keyword that starts the head
|
||||
@ -205,17 +177,12 @@ impl<'a> State<'a> {
|
||||
self.end(); // close the head-box
|
||||
}
|
||||
|
||||
pub fn bclose_(&mut self, span: syntax_pos::Span, indented: usize) {
|
||||
self.bclose_maybe_open(span, indented, true)
|
||||
}
|
||||
|
||||
pub fn bclose_maybe_open(&mut self,
|
||||
span: syntax_pos::Span,
|
||||
indented: usize,
|
||||
close_box: bool)
|
||||
{
|
||||
self.maybe_print_comment(span.hi());
|
||||
self.break_offset_if_not_bol(1, -(indented as isize));
|
||||
self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
|
||||
self.s.word("}");
|
||||
if close_box {
|
||||
self.end(); // close the outer-box
|
||||
@ -223,24 +190,17 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn bclose(&mut self, span: syntax_pos::Span) {
|
||||
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,
|
||||
}
|
||||
self.bclose_maybe_open(span, true)
|
||||
}
|
||||
|
||||
pub fn space_if_not_bol(&mut self) {
|
||||
if !self.is_bol() {
|
||||
if !self.s.is_beginning_of_line() {
|
||||
self.s.space();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
|
||||
if !self.is_bol() {
|
||||
if !self.s.is_beginning_of_line() {
|
||||
self.s.break_offset(n, off)
|
||||
} else {
|
||||
if off != 0 && self.s.last_token().is_hardbreak_tok() {
|
||||
@ -766,7 +726,7 @@ impl<'a> State<'a> {
|
||||
self.space_if_not_bol();
|
||||
self.maybe_print_comment(v.span.lo());
|
||||
self.print_outer_attributes(&v.node.attrs);
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.print_variant(v);
|
||||
self.s.word(",");
|
||||
self.end();
|
||||
@ -953,10 +913,10 @@ impl<'a> State<'a> {
|
||||
decl: impl Fn(&mut Self)
|
||||
) {
|
||||
self.space_if_not_bol();
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word_nbsp("let");
|
||||
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
decl(self);
|
||||
self.end();
|
||||
|
||||
@ -998,26 +958,18 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn print_block_unclosed(&mut self, blk: &hir::Block) {
|
||||
self.print_block_unclosed_indent(blk, indent_unit)
|
||||
}
|
||||
|
||||
pub fn print_block_unclosed_indent(&mut self,
|
||||
blk: &hir::Block,
|
||||
indented: usize)
|
||||
{
|
||||
self.print_block_maybe_unclosed(blk, indented, &[], false)
|
||||
self.print_block_maybe_unclosed(blk, &[], false)
|
||||
}
|
||||
|
||||
pub fn print_block_with_attrs(&mut self,
|
||||
blk: &hir::Block,
|
||||
attrs: &[ast::Attribute])
|
||||
{
|
||||
self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
|
||||
self.print_block_maybe_unclosed(blk, attrs, true)
|
||||
}
|
||||
|
||||
pub fn print_block_maybe_unclosed(&mut self,
|
||||
blk: &hir::Block,
|
||||
indented: usize,
|
||||
attrs: &[ast::Attribute],
|
||||
close_box: bool)
|
||||
{
|
||||
@ -1041,7 +993,7 @@ impl<'a> State<'a> {
|
||||
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.bclose_maybe_open(blk.span, close_box);
|
||||
self.ann.post(self, AnnNode::Block(blk))
|
||||
}
|
||||
|
||||
@ -1089,7 +1041,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
fn print_expr_vec(&mut self, exprs: &[hir::Expr]) {
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.s.word("[");
|
||||
self.commasep_exprs(Inconsistent, exprs);
|
||||
self.s.word("]");
|
||||
@ -1097,7 +1049,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::AnonConst) {
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.s.word("[");
|
||||
self.print_expr(element);
|
||||
self.word_space(";");
|
||||
@ -1116,7 +1068,7 @@ impl<'a> State<'a> {
|
||||
self.commasep_cmnt(Consistent,
|
||||
&fields[..],
|
||||
|s, field| {
|
||||
s.ibox(indent_unit);
|
||||
s.ibox(INDENT_UNIT);
|
||||
if !field.is_shorthand {
|
||||
s.print_ident(field.ident);
|
||||
s.word_space(":");
|
||||
@ -1127,7 +1079,7 @@ impl<'a> State<'a> {
|
||||
|f| f.span);
|
||||
match *wth {
|
||||
Some(ref expr) => {
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
if !fields.is_empty() {
|
||||
self.s.word(",");
|
||||
self.s.space();
|
||||
@ -1226,13 +1178,13 @@ impl<'a> State<'a> {
|
||||
|
||||
fn print_literal(&mut self, lit: &hir::Lit) {
|
||||
self.maybe_print_comment(lit.span.lo());
|
||||
self.writer().word(pprust::literal_to_string(lit.node.to_lit_token()))
|
||||
self.word(lit.node.to_lit_token().to_string())
|
||||
}
|
||||
|
||||
pub fn print_expr(&mut self, expr: &hir::Expr) {
|
||||
self.maybe_print_comment(expr.span.lo());
|
||||
self.print_outer_attributes(&expr.attrs);
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.ann.pre(self, AnnNode::Expr(expr));
|
||||
match expr.node {
|
||||
hir::ExprKind::Box(ref expr) => {
|
||||
@ -1284,7 +1236,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
hir::ExprKind::DropTemps(ref init) => {
|
||||
// Print `{`:
|
||||
self.cbox(indent_unit);
|
||||
self.cbox(INDENT_UNIT);
|
||||
self.ibox(0);
|
||||
self.bopen();
|
||||
|
||||
@ -1298,7 +1250,7 @@ impl<'a> State<'a> {
|
||||
self.print_ident(temp);
|
||||
|
||||
// Print `}`:
|
||||
self.bclose_maybe_open(expr.span, indent_unit, true);
|
||||
self.bclose_maybe_open(expr.span, true);
|
||||
}
|
||||
hir::ExprKind::Loop(ref blk, opt_label, _) => {
|
||||
if let Some(label) = opt_label {
|
||||
@ -1310,8 +1262,8 @@ impl<'a> State<'a> {
|
||||
self.print_block(&blk);
|
||||
}
|
||||
hir::ExprKind::Match(ref expr, ref arms, _) => {
|
||||
self.cbox(indent_unit);
|
||||
self.ibox(4);
|
||||
self.cbox(INDENT_UNIT);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word_nbsp("match");
|
||||
self.print_expr_as_cond(&expr);
|
||||
self.s.space();
|
||||
@ -1319,7 +1271,7 @@ impl<'a> State<'a> {
|
||||
for arm in arms {
|
||||
self.print_arm(arm);
|
||||
}
|
||||
self.bclose_(expr.span, indent_unit);
|
||||
self.bclose(expr.span);
|
||||
}
|
||||
hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => {
|
||||
self.print_capture_clause(capture_clause);
|
||||
@ -1342,7 +1294,7 @@ impl<'a> State<'a> {
|
||||
self.word_space(":");
|
||||
}
|
||||
// containing cbox, will be closed by print-block at }
|
||||
self.cbox(indent_unit);
|
||||
self.cbox(INDENT_UNIT);
|
||||
// head-box, will be closed by print-block after {
|
||||
self.ibox(0);
|
||||
self.print_block(&blk);
|
||||
@ -1712,7 +1664,7 @@ impl<'a> State<'a> {
|
||||
self.commasep_cmnt(Consistent,
|
||||
&fields[..],
|
||||
|s, f| {
|
||||
s.cbox(indent_unit);
|
||||
s.cbox(INDENT_UNIT);
|
||||
if !f.node.is_shorthand {
|
||||
s.print_ident(f.node.ident);
|
||||
s.word_nbsp(":");
|
||||
@ -1821,7 +1773,7 @@ impl<'a> State<'a> {
|
||||
if arm.attrs.is_empty() {
|
||||
self.s.space();
|
||||
}
|
||||
self.cbox(indent_unit);
|
||||
self.cbox(INDENT_UNIT);
|
||||
self.ann.pre(self, AnnNode::Arm(arm));
|
||||
self.ibox(0);
|
||||
self.print_outer_attributes(&arm.attrs);
|
||||
@ -1854,7 +1806,7 @@ impl<'a> State<'a> {
|
||||
self.word_space(":");
|
||||
}
|
||||
// the block will close the pattern's ibox
|
||||
self.print_block_unclosed_indent(&blk, indent_unit);
|
||||
self.print_block_unclosed(&blk);
|
||||
|
||||
// If it is a user-provided unsafe block, print a comma after it
|
||||
if let hir::UnsafeBlock(hir::UserProvided) = blk.rules {
|
||||
@ -1893,7 +1845,7 @@ impl<'a> State<'a> {
|
||||
// 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| {
|
||||
s.ibox(indent_unit);
|
||||
s.ibox(INDENT_UNIT);
|
||||
if let Some(arg_name) = arg_names.get(i) {
|
||||
s.s.word(arg_name.as_str().to_string());
|
||||
s.s.word(":");
|
||||
@ -1920,7 +1872,7 @@ impl<'a> State<'a> {
|
||||
self.s.word("|");
|
||||
let mut i = 0;
|
||||
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
|
||||
s.ibox(indent_unit);
|
||||
s.ibox(INDENT_UNIT);
|
||||
|
||||
s.ann.nested(s, Nested::BodyArgPat(body_id, i));
|
||||
i += 1;
|
||||
@ -2119,7 +2071,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
self.space_if_not_bol();
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word_space("->");
|
||||
match decl.output {
|
||||
hir::DefaultReturn(..) => unreachable!(),
|
||||
@ -2141,7 +2093,7 @@ impl<'a> State<'a> {
|
||||
generic_params: &[hir::GenericParam],
|
||||
arg_names: &[ast::Ident])
|
||||
{
|
||||
self.ibox(indent_unit);
|
||||
self.ibox(INDENT_UNIT);
|
||||
if !generic_params.is_empty() {
|
||||
self.s.word("for");
|
||||
self.print_generic_params(generic_params);
|
||||
@ -2174,23 +2126,9 @@ impl<'a> State<'a> {
|
||||
span: syntax_pos::Span,
|
||||
next_pos: Option<BytePos>)
|
||||
{
|
||||
let cm = match self.cm {
|
||||
Some(cm) => cm,
|
||||
_ => return,
|
||||
};
|
||||
if let Some(ref cmnt) = self.next_comment() {
|
||||
if (*cmnt).style != comments::Trailing {
|
||||
return;
|
||||
}
|
||||
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);
|
||||
if let Some(p) = next_pos {
|
||||
next = p;
|
||||
}
|
||||
if span.hi() < (*cmnt).pos && (*cmnt).pos < next &&
|
||||
span_line.line == comment_line.line {
|
||||
self.print_comment(cmnt);
|
||||
if let Some(cmnts) = self.comments() {
|
||||
if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
|
||||
self.print_comment(&cmnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ use rustc::cfg::CFGIndex;
|
||||
use rustc::ty::TyCtxt;
|
||||
use std::mem;
|
||||
use std::usize;
|
||||
use syntax::print::pprust::PrintState;
|
||||
use log::debug;
|
||||
|
||||
use rustc_data_structures::graph::implementation::OUTGOING;
|
||||
@ -530,7 +529,7 @@ impl<'tcx, O: DataFlowOperator + Clone + 'static> DataFlowContext<'tcx, O> {
|
||||
|
||||
debug!("Dataflow result for {}:", self.analysis_name);
|
||||
debug!("{}", pprust::to_string(self, |s| {
|
||||
s.cbox(pprust::indent_unit);
|
||||
s.cbox(pprust::INDENT_UNIT);
|
||||
s.ibox(0);
|
||||
s.print_expr(&body.value)
|
||||
}));
|
||||
|
@ -19,7 +19,6 @@ use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
|
||||
use syntax::ast;
|
||||
use syntax::mut_visit::MutVisitor;
|
||||
use syntax::print::{pprust};
|
||||
use syntax::print::pprust::PrintState;
|
||||
use syntax_pos::FileName;
|
||||
|
||||
use graphviz as dot;
|
||||
@ -687,16 +686,14 @@ pub fn visit_crate(sess: &Session, krate: &mut ast::Crate, ppm: PpMode) {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_source(input: &Input, sess: &Session) -> (Vec<u8>, FileName) {
|
||||
fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
|
||||
let src_name = source_name(input);
|
||||
let src = sess.source_map()
|
||||
let src = String::clone(&sess.source_map()
|
||||
.get_source_file(&src_name)
|
||||
.unwrap()
|
||||
.src
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_bytes()
|
||||
.to_vec();
|
||||
.unwrap());
|
||||
(src, src_name)
|
||||
}
|
||||
|
||||
@ -719,7 +716,6 @@ pub fn print_after_parsing(sess: &Session,
|
||||
ofile: Option<&Path>) {
|
||||
let (src, src_name) = get_source(input, sess);
|
||||
|
||||
let mut rdr = &*src;
|
||||
let mut out = String::new();
|
||||
|
||||
if let PpmSource(s) = ppm {
|
||||
@ -728,12 +724,11 @@ pub fn print_after_parsing(sess: &Session,
|
||||
s.call_with_pp_support(sess, None, move |annotation| {
|
||||
debug!("pretty printing source code {:?}", s);
|
||||
let sess = annotation.sess();
|
||||
pprust::print_crate(sess.source_map(),
|
||||
*out = pprust::print_crate(sess.source_map(),
|
||||
&sess.parse_sess,
|
||||
krate,
|
||||
src_name,
|
||||
&mut rdr,
|
||||
out,
|
||||
src,
|
||||
annotation.pp_ann(),
|
||||
false)
|
||||
})
|
||||
@ -764,22 +759,21 @@ pub fn print_after_hir_lowering<'tcx>(
|
||||
|
||||
let (src, src_name) = get_source(input, tcx.sess);
|
||||
|
||||
let mut rdr = &src[..];
|
||||
let mut out = String::new();
|
||||
|
||||
match (ppm, opt_uii) {
|
||||
(PpmSource(s), _) => {
|
||||
// Silently ignores an identified node.
|
||||
let out = &mut out;
|
||||
let src = src.clone();
|
||||
s.call_with_pp_support(tcx.sess, Some(tcx), move |annotation| {
|
||||
debug!("pretty printing source code {:?}", s);
|
||||
let sess = annotation.sess();
|
||||
pprust::print_crate(sess.source_map(),
|
||||
*out = pprust::print_crate(sess.source_map(),
|
||||
&sess.parse_sess,
|
||||
krate,
|
||||
src_name,
|
||||
&mut rdr,
|
||||
out,
|
||||
src,
|
||||
annotation.pp_ann(),
|
||||
true)
|
||||
})
|
||||
@ -787,15 +781,15 @@ pub fn print_after_hir_lowering<'tcx>(
|
||||
|
||||
(PpmHir(s), None) => {
|
||||
let out = &mut out;
|
||||
let src = src.clone();
|
||||
s.call_with_pp_support_hir(tcx, move |annotation, krate| {
|
||||
debug!("pretty printing source code {:?}", s);
|
||||
let sess = annotation.sess();
|
||||
pprust_hir::print_crate(sess.source_map(),
|
||||
*out = pprust_hir::print_crate(sess.source_map(),
|
||||
&sess.parse_sess,
|
||||
krate,
|
||||
src_name,
|
||||
&mut rdr,
|
||||
out,
|
||||
src,
|
||||
annotation.pp_ann())
|
||||
})
|
||||
}
|
||||
@ -810,6 +804,7 @@ pub fn print_after_hir_lowering<'tcx>(
|
||||
|
||||
(PpmHir(s), Some(uii)) => {
|
||||
let out = &mut out;
|
||||
let src = src.clone();
|
||||
s.call_with_pp_support_hir(tcx, move |annotation, _| {
|
||||
debug!("pretty printing source code {:?}", s);
|
||||
let sess = annotation.sess();
|
||||
@ -817,8 +812,7 @@ pub fn print_after_hir_lowering<'tcx>(
|
||||
let mut pp_state = pprust_hir::State::new_from_input(sess.source_map(),
|
||||
&sess.parse_sess,
|
||||
src_name,
|
||||
&mut rdr,
|
||||
out,
|
||||
src,
|
||||
annotation.pp_ann());
|
||||
for node_id in uii.all_matching_node_ids(hir_map) {
|
||||
let hir_id = tcx.hir().node_to_hir_id(node_id);
|
||||
@ -830,7 +824,7 @@ pub fn print_after_hir_lowering<'tcx>(
|
||||
pp_state.synth_comment(path);
|
||||
pp_state.s.hardbreak();
|
||||
}
|
||||
pp_state.s.eof();
|
||||
*out = pp_state.s.eof();
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1316,7 +1316,7 @@ impl EncodeContext<'tcx> {
|
||||
let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
|
||||
Entry {
|
||||
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
|
||||
body: pprust::tts_to_string(¯o_def.body.trees().collect::<Vec<_>>()),
|
||||
body: pprust::tokens_to_string(macro_def.body.clone()),
|
||||
legacy: macro_def.legacy,
|
||||
})),
|
||||
visibility: self.lazy(&ty::Visibility::Public),
|
||||
|
@ -73,13 +73,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let (usize_ty, bool_ty) = (this.hir.usize_ty(), this.hir.bool_ty());
|
||||
|
||||
let slice = unpack!(block = this.as_place(block, lhs));
|
||||
// region_scope=None so place indexes live forever. They are scalars so they
|
||||
// do not need storage annotations, and they are often copied between
|
||||
// places.
|
||||
// Making this a *fresh* temporary also means we do not have to worry about
|
||||
// the index changing later: Nothing will ever change this temporary.
|
||||
// The "retagging" transformation (for Stacked Borrows) relies on this.
|
||||
let idx = unpack!(block = this.as_temp(block, None, index, Mutability::Mut));
|
||||
let idx = unpack!(block = this.as_temp(
|
||||
block,
|
||||
expr.temp_lifetime,
|
||||
index,
|
||||
Mutability::Not,
|
||||
));
|
||||
|
||||
// bounds check:
|
||||
let (len, lt) = (
|
||||
|
@ -3,6 +3,7 @@
|
||||
use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use crate::build::scope::DropKind;
|
||||
use crate::hair::*;
|
||||
use rustc::hir;
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::*;
|
||||
|
||||
@ -66,32 +67,46 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
};
|
||||
let temp_place = &Place::from(temp);
|
||||
|
||||
if !expr_ty.is_never() {
|
||||
this.cfg.push(
|
||||
block,
|
||||
Statement {
|
||||
source_info,
|
||||
kind: StatementKind::StorageLive(temp),
|
||||
},
|
||||
);
|
||||
|
||||
// In constants, `temp_lifetime` is `None` for temporaries that live for the
|
||||
// `'static` lifetime. Thus we do not drop these temporaries and simply leak them.
|
||||
// This is equivalent to what `let x = &foo();` does in functions. The temporary
|
||||
// is lifted to their surrounding scope. In a function that means the temporary lives
|
||||
// until just before the function returns. In constants that means it outlives the
|
||||
// constant's initialization value computation. Anything outliving a constant
|
||||
// must have the `'static` lifetime and live forever.
|
||||
// Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
|
||||
// within a block will keep the regular drops just like runtime code.
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
this.schedule_drop(
|
||||
expr_span,
|
||||
temp_lifetime,
|
||||
temp,
|
||||
expr_ty,
|
||||
DropKind::Storage,
|
||||
match expr.kind {
|
||||
// Don't bother with StorageLive and Dead for these temporaries,
|
||||
// they are never assigned.
|
||||
ExprKind::Break { .. } |
|
||||
ExprKind::Continue { .. } |
|
||||
ExprKind::Return { .. } => (),
|
||||
ExprKind::Block {
|
||||
body: hir::Block { expr: None, targeted_by_break: false, .. }
|
||||
} if expr_ty.is_never() => (),
|
||||
_ => {
|
||||
this.cfg.push(
|
||||
block,
|
||||
Statement {
|
||||
source_info,
|
||||
kind: StatementKind::StorageLive(temp),
|
||||
},
|
||||
);
|
||||
|
||||
// In constants, `temp_lifetime` is `None` for temporaries that
|
||||
// live for the `'static` lifetime. Thus we do not drop these
|
||||
// temporaries and simply leak them.
|
||||
// This is equivalent to what `let x = &foo();` does in
|
||||
// functions. The temporary is lifted to their surrounding
|
||||
// scope. In a function that means the temporary lives until
|
||||
// just before the function returns. In constants that means it
|
||||
// outlives the constant's initialization value computation.
|
||||
// Anything outliving a constant must have the `'static`
|
||||
// lifetime and live forever.
|
||||
// Anything with a shorter lifetime (e.g the `&foo()` in
|
||||
// `bar(&foo())` or anything within a block will keep the
|
||||
// regular drops just like runtime code.
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
this.schedule_drop(
|
||||
expr_span,
|
||||
temp_lifetime,
|
||||
temp,
|
||||
expr_ty,
|
||||
DropKind::Storage,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,6 +142,7 @@ impl<'a, 'tcx> ConstCx<'a, 'tcx> {
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum ValueSource<'a, 'tcx> {
|
||||
Rvalue(&'a Rvalue<'tcx>),
|
||||
DropAndReplace(&'a Operand<'tcx>),
|
||||
Call {
|
||||
callee: &'a Operand<'tcx>,
|
||||
args: &'a [Operand<'tcx>],
|
||||
@ -298,6 +299,7 @@ trait Qualif {
|
||||
fn in_value(cx: &ConstCx<'_, 'tcx>, source: ValueSource<'_, 'tcx>) -> bool {
|
||||
match source {
|
||||
ValueSource::Rvalue(rvalue) => Self::in_rvalue(cx, rvalue),
|
||||
ValueSource::DropAndReplace(source) => Self::in_operand(cx, source),
|
||||
ValueSource::Call { callee, args, return_ty } => {
|
||||
Self::in_call(cx, callee, args, return_ty)
|
||||
}
|
||||
@ -889,6 +891,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||
let target = match body[bb].terminator().kind {
|
||||
TerminatorKind::Goto { target } |
|
||||
TerminatorKind::Drop { target, .. } |
|
||||
TerminatorKind::DropAndReplace { target, .. } |
|
||||
TerminatorKind::Assert { target, .. } |
|
||||
TerminatorKind::Call { destination: Some((_, target)), .. } => {
|
||||
Some(target)
|
||||
@ -900,7 +903,6 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||
}
|
||||
|
||||
TerminatorKind::SwitchInt {..} |
|
||||
TerminatorKind::DropAndReplace { .. } |
|
||||
TerminatorKind::Resume |
|
||||
TerminatorKind::Abort |
|
||||
TerminatorKind::GeneratorDrop |
|
||||
@ -1393,8 +1395,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||
for arg in args {
|
||||
self.visit_operand(arg, location);
|
||||
}
|
||||
} else if let TerminatorKind::Drop { location: ref place, .. } = *kind {
|
||||
self.super_terminator_kind(kind, location);
|
||||
} else if let TerminatorKind::Drop {
|
||||
location: ref place, ..
|
||||
} | TerminatorKind::DropAndReplace {
|
||||
location: ref place, ..
|
||||
} = *kind {
|
||||
match *kind {
|
||||
TerminatorKind::DropAndReplace { .. } => {}
|
||||
_ => self.super_terminator_kind(kind, location),
|
||||
}
|
||||
|
||||
// Deny *any* live drops anywhere other than functions.
|
||||
if self.mode.requires_const_checking() {
|
||||
@ -1423,6 +1432,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match *kind {
|
||||
TerminatorKind::DropAndReplace { ref value, .. } => {
|
||||
self.assign(place, ValueSource::DropAndReplace(value), location);
|
||||
self.visit_operand(value, location);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
// Qualify any operands inside other terminators.
|
||||
self.super_terminator_kind(kind, location);
|
||||
|
@ -50,11 +50,17 @@ impl fmt::Debug for Lifetime {
|
||||
f,
|
||||
"lifetime({}: {})",
|
||||
self.id,
|
||||
pprust::lifetime_to_string(self)
|
||||
self
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Lifetime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.ident.name.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
/// A "Path" is essentially Rust's notion of a name.
|
||||
///
|
||||
/// It's represented as a sequence of identifiers,
|
||||
|
@ -162,6 +162,7 @@ pub mod visit;
|
||||
pub mod print {
|
||||
pub mod pp;
|
||||
pub mod pprust;
|
||||
mod helpers;
|
||||
}
|
||||
|
||||
pub mod ext {
|
||||
|
@ -611,8 +611,6 @@ impl<'a> Parser<'a> {
|
||||
match ty.node {
|
||||
TyKind::Rptr(ref lifetime, ref mut_ty) => {
|
||||
let sum_with_parens = pprust::to_string(|s| {
|
||||
use crate::print::pprust::PrintState;
|
||||
|
||||
s.s.word("&");
|
||||
s.print_opt_lifetime(lifetime);
|
||||
s.print_mutability(mut_ty.mutbl);
|
||||
|
@ -8,7 +8,6 @@ use crate::parse::lexer::{self, ParseSess, StringReader};
|
||||
use syntax_pos::{BytePos, CharPos, Pos, FileName};
|
||||
use log::debug;
|
||||
|
||||
use std::io::Read;
|
||||
use std::usize;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
@ -340,10 +339,8 @@ fn consume_comment(rdr: &mut StringReader<'_>,
|
||||
|
||||
// it appears this function is called only from pprust... that's
|
||||
// probably not a good thing.
|
||||
pub fn gather_comments(sess: &ParseSess, path: FileName, srdr: &mut dyn Read) -> Vec<Comment>
|
||||
pub fn gather_comments(sess: &ParseSess, path: FileName, src: String) -> Vec<Comment>
|
||||
{
|
||||
let mut src = String::new();
|
||||
srdr.read_to_string(&mut src).unwrap();
|
||||
let cm = SourceMap::new(sess.source_map().path_mapping().clone());
|
||||
let source_file = cm.new_source_file(path, src);
|
||||
let mut rdr = lexer::StringReader::new(sess, source_file, None);
|
||||
|
@ -344,7 +344,7 @@ impl<'a> Parser<'a> {
|
||||
// Pack possible quotes and prefixes from the original literal into
|
||||
// the error literal's symbol so they can be pretty-printed faithfully.
|
||||
let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
|
||||
let symbol = Symbol::intern(&pprust::literal_to_string(suffixless_lit));
|
||||
let symbol = Symbol::intern(&suffixless_lit.to_string());
|
||||
let lit = token::Lit::new(token::Err, symbol, lit.suffix);
|
||||
Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
|
||||
}
|
||||
|
@ -2571,7 +2571,6 @@ impl<'a> Parser<'a> {
|
||||
None => continue,
|
||||
};
|
||||
let sugg = pprust::to_string(|s| {
|
||||
use crate::print::pprust::PrintState;
|
||||
s.popen();
|
||||
s.print_expr(&e);
|
||||
s.s.word( ".");
|
||||
@ -4588,11 +4587,11 @@ impl<'a> Parser<'a> {
|
||||
stmt_span = stmt_span.with_hi(self.prev_span.hi());
|
||||
}
|
||||
let sugg = pprust::to_string(|s| {
|
||||
use crate::print::pprust::{PrintState, INDENT_UNIT};
|
||||
use crate::print::pprust::INDENT_UNIT;
|
||||
s.ibox(INDENT_UNIT);
|
||||
s.bopen();
|
||||
s.print_stmt(&stmt);
|
||||
s.bclose_maybe_open(stmt.span, INDENT_UNIT, false)
|
||||
s.bclose_maybe_open(stmt.span, false)
|
||||
});
|
||||
e.span_suggestion(
|
||||
stmt_span,
|
||||
|
@ -80,6 +80,34 @@ pub struct Lit {
|
||||
pub suffix: Option<Symbol>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Lit {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Lit { kind, symbol, suffix } = *self;
|
||||
match kind {
|
||||
Byte => write!(f, "b'{}'", symbol)?,
|
||||
Char => write!(f, "'{}'", symbol)?,
|
||||
Str => write!(f, "\"{}\"", symbol)?,
|
||||
StrRaw(n) => write!(f, "r{delim}\"{string}\"{delim}",
|
||||
delim="#".repeat(n as usize),
|
||||
string=symbol)?,
|
||||
ByteStr => write!(f, "b\"{}\"", symbol)?,
|
||||
ByteStrRaw(n) => write!(f, "br{delim}\"{string}\"{delim}",
|
||||
delim="#".repeat(n as usize),
|
||||
string=symbol)?,
|
||||
Integer |
|
||||
Float |
|
||||
Bool |
|
||||
Err => write!(f, "{}", symbol)?,
|
||||
}
|
||||
|
||||
if let Some(suffix) = suffix {
|
||||
write!(f, "{}", suffix)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl LitKind {
|
||||
/// An English article for the literal token kind.
|
||||
crate fn article(self) -> &'static str {
|
||||
@ -788,7 +816,7 @@ fn prepend_attrs(sess: &ParseSess,
|
||||
assert_eq!(attr.style, ast::AttrStyle::Outer,
|
||||
"inner attributes should prevent cached tokens from existing");
|
||||
|
||||
let source = pprust::attr_to_string(attr);
|
||||
let source = pprust::attribute_to_string(attr);
|
||||
let macro_filename = FileName::macro_expansion_source_code(&source);
|
||||
if attr.is_sugared_doc {
|
||||
let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span));
|
||||
|
34
src/libsyntax/print/helpers.rs
Normal file
34
src/libsyntax/print/helpers.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use std::borrow::Cow;
|
||||
use crate::print::pp::Printer;
|
||||
|
||||
impl Printer {
|
||||
pub fn word_space<W: Into<Cow<'static, str>>>(&mut self, w: W) {
|
||||
self.word(w);
|
||||
self.space();
|
||||
}
|
||||
|
||||
pub fn popen(&mut self) {
|
||||
self.word("(");
|
||||
}
|
||||
|
||||
pub fn pclose(&mut self) {
|
||||
self.word(")");
|
||||
}
|
||||
|
||||
pub fn hardbreak_if_not_bol(&mut self) {
|
||||
if !self.is_beginning_of_line() {
|
||||
self.hardbreak()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn space_if_not_bol(&mut self) {
|
||||
if !self.is_beginning_of_line() { self.space(); }
|
||||
}
|
||||
|
||||
pub fn nbsp(&mut self) { self.word(" ") }
|
||||
|
||||
pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) {
|
||||
self.word(w);
|
||||
self.nbsp()
|
||||
}
|
||||
}
|
@ -131,7 +131,7 @@
|
||||
//! it.
|
||||
//!
|
||||
//! In this implementation (following the paper, again) the SCAN process is the
|
||||
//! methods called `Printer::pretty_print_*`, and the 'PRINT' process is the
|
||||
//! methods called `Printer::scan_*`, and the 'PRINT' process is the
|
||||
//! method called `Printer::print`.
|
||||
|
||||
use std::collections::VecDeque;
|
||||
@ -163,7 +163,7 @@ pub enum Token {
|
||||
// In practice a string token contains either a `&'static str` or a
|
||||
// `String`. `Cow` is overkill for this because we never modify the data,
|
||||
// but it's more convenient than rolling our own more specialized type.
|
||||
String(Cow<'static, str>, isize),
|
||||
String(Cow<'static, str>),
|
||||
Break(BreakToken),
|
||||
Begin(BeginToken),
|
||||
End,
|
||||
@ -194,7 +194,7 @@ impl Token {
|
||||
impl fmt::Display for Token {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Token::String(ref s, len) => write!(f, "STR({},{})", s, len),
|
||||
Token::String(ref s) => write!(f, "STR({},{})", s, s.len()),
|
||||
Token::Break(_) => f.write_str("BREAK"),
|
||||
Token::Begin(_) => f.write_str("BEGIN"),
|
||||
Token::End => f.write_str("END"),
|
||||
@ -222,26 +222,26 @@ fn buf_str(buf: &[BufEntry], left: usize, right: usize, lim: usize) -> String {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
crate enum PrintStackBreak {
|
||||
enum PrintStackBreak {
|
||||
Fits,
|
||||
Broken(Breaks),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
crate struct PrintStackElem {
|
||||
struct PrintStackElem {
|
||||
offset: isize,
|
||||
pbreak: PrintStackBreak
|
||||
}
|
||||
|
||||
const SIZE_INFINITY: isize = 0xffff;
|
||||
|
||||
pub fn mk_printer(out: &mut String) -> Printer<'_> {
|
||||
pub fn mk_printer() -> Printer {
|
||||
let linewidth = 78;
|
||||
// Yes 55, it makes the ring buffers big enough to never fall behind.
|
||||
let n: usize = 55 * linewidth;
|
||||
debug!("mk_printer {}", linewidth);
|
||||
Printer {
|
||||
out,
|
||||
out: String::new(),
|
||||
buf_max_len: n,
|
||||
margin: linewidth as isize,
|
||||
space: linewidth as isize,
|
||||
@ -258,8 +258,8 @@ pub fn mk_printer(out: &mut String) -> Printer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Printer<'a> {
|
||||
out: &'a mut String,
|
||||
pub struct Printer {
|
||||
out: String,
|
||||
buf_max_len: usize,
|
||||
/// Width of lines we're constrained to
|
||||
margin: isize,
|
||||
@ -300,8 +300,8 @@ impl Default for BufEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Printer<'a> {
|
||||
pub fn last_token(&mut self) -> Token {
|
||||
impl Printer {
|
||||
pub fn last_token(&self) -> Token {
|
||||
self.buf[self.right].token.clone()
|
||||
}
|
||||
|
||||
@ -310,15 +310,14 @@ impl<'a> Printer<'a> {
|
||||
self.buf[self.right].token = t;
|
||||
}
|
||||
|
||||
fn pretty_print_eof(&mut self) {
|
||||
fn scan_eof(&mut self) {
|
||||
if !self.scan_stack.is_empty() {
|
||||
self.check_stack(0);
|
||||
self.advance_left();
|
||||
}
|
||||
self.indent(0);
|
||||
}
|
||||
|
||||
fn pretty_print_begin(&mut self, b: BeginToken) {
|
||||
fn scan_begin(&mut self, b: BeginToken) {
|
||||
if self.scan_stack.is_empty() {
|
||||
self.left_total = 1;
|
||||
self.right_total = 1;
|
||||
@ -329,25 +328,21 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
debug!("pp Begin({})/buffer Vec<{},{}>",
|
||||
b.offset, self.left, self.right);
|
||||
self.buf[self.right] = BufEntry { token: Token::Begin(b), size: -self.right_total };
|
||||
let right = self.right;
|
||||
self.scan_push(right);
|
||||
self.scan_push(BufEntry { token: Token::Begin(b), size: -self.right_total });
|
||||
}
|
||||
|
||||
fn pretty_print_end(&mut self) {
|
||||
fn scan_end(&mut self) {
|
||||
if self.scan_stack.is_empty() {
|
||||
debug!("pp End/print Vec<{},{}>", self.left, self.right);
|
||||
self.print_end();
|
||||
} else {
|
||||
debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
|
||||
self.advance_right();
|
||||
self.buf[self.right] = BufEntry { token: Token::End, size: -1 };
|
||||
let right = self.right;
|
||||
self.scan_push(right);
|
||||
self.scan_push(BufEntry { token: Token::End, size: -1 });
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_print_break(&mut self, b: BreakToken) {
|
||||
fn scan_break(&mut self, b: BreakToken) {
|
||||
if self.scan_stack.is_empty() {
|
||||
self.left_total = 1;
|
||||
self.right_total = 1;
|
||||
@ -359,28 +354,27 @@ impl<'a> Printer<'a> {
|
||||
debug!("pp Break({})/buffer Vec<{},{}>",
|
||||
b.offset, self.left, self.right);
|
||||
self.check_stack(0);
|
||||
let right = self.right;
|
||||
self.scan_push(right);
|
||||
self.buf[self.right] = BufEntry { token: Token::Break(b), size: -self.right_total };
|
||||
self.scan_push(BufEntry { token: Token::Break(b), size: -self.right_total });
|
||||
self.right_total += b.blank_space;
|
||||
}
|
||||
|
||||
fn pretty_print_string(&mut self, s: Cow<'static, str>, len: isize) {
|
||||
fn scan_string(&mut self, s: Cow<'static, str>) {
|
||||
if self.scan_stack.is_empty() {
|
||||
debug!("pp String('{}')/print Vec<{},{}>",
|
||||
s, self.left, self.right);
|
||||
self.print_string(s, len);
|
||||
self.print_string(s);
|
||||
} else {
|
||||
debug!("pp String('{}')/buffer Vec<{},{}>",
|
||||
s, self.left, self.right);
|
||||
self.advance_right();
|
||||
self.buf[self.right] = BufEntry { token: Token::String(s, len), size: len };
|
||||
let len = s.len() as isize;
|
||||
self.buf[self.right] = BufEntry { token: Token::String(s), size: len };
|
||||
self.right_total += len;
|
||||
self.check_stream();
|
||||
}
|
||||
}
|
||||
|
||||
crate fn check_stream(&mut self) {
|
||||
fn check_stream(&mut self) {
|
||||
debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}",
|
||||
self.left, self.right, self.left_total, self.right_total);
|
||||
if self.right_total - self.left_total > self.space {
|
||||
@ -398,24 +392,25 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn scan_push(&mut self, x: usize) {
|
||||
debug!("scan_push {}", x);
|
||||
self.scan_stack.push_front(x);
|
||||
fn scan_push(&mut self, entry: BufEntry) {
|
||||
debug!("scan_push {}", self.right);
|
||||
self.buf[self.right] = entry;
|
||||
self.scan_stack.push_front(self.right);
|
||||
}
|
||||
|
||||
crate fn scan_pop(&mut self) -> usize {
|
||||
fn scan_pop(&mut self) -> usize {
|
||||
self.scan_stack.pop_front().unwrap()
|
||||
}
|
||||
|
||||
crate fn scan_top(&mut self) -> usize {
|
||||
fn scan_top(&mut self) -> usize {
|
||||
*self.scan_stack.front().unwrap()
|
||||
}
|
||||
|
||||
crate fn scan_pop_bottom(&mut self) -> usize {
|
||||
fn scan_pop_bottom(&mut self) -> usize {
|
||||
self.scan_stack.pop_back().unwrap()
|
||||
}
|
||||
|
||||
crate fn advance_right(&mut self) {
|
||||
fn advance_right(&mut self) {
|
||||
self.right += 1;
|
||||
self.right %= self.buf_max_len;
|
||||
// Extend the buf if necessary.
|
||||
@ -425,7 +420,7 @@ impl<'a> Printer<'a> {
|
||||
assert_ne!(self.right, self.left);
|
||||
}
|
||||
|
||||
crate fn advance_left(&mut self) {
|
||||
fn advance_left(&mut self) {
|
||||
debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
|
||||
self.left, self.buf[self.left].size);
|
||||
|
||||
@ -436,7 +431,8 @@ impl<'a> Printer<'a> {
|
||||
|
||||
let len = match left {
|
||||
Token::Break(b) => b.blank_space,
|
||||
Token::String(_, len) => {
|
||||
Token::String(ref s) => {
|
||||
let len = s.len() as isize;
|
||||
assert_eq!(len, left_size);
|
||||
len
|
||||
}
|
||||
@ -458,26 +454,26 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn check_stack(&mut self, k: isize) {
|
||||
fn check_stack(&mut self, k: usize) {
|
||||
if !self.scan_stack.is_empty() {
|
||||
let x = self.scan_top();
|
||||
match self.buf[x].token {
|
||||
Token::Begin(_) => {
|
||||
if k > 0 {
|
||||
let popped = self.scan_pop();
|
||||
self.buf[popped].size = self.buf[x].size + self.right_total;
|
||||
self.scan_pop();
|
||||
self.buf[x].size += self.right_total;
|
||||
self.check_stack(k - 1);
|
||||
}
|
||||
}
|
||||
Token::End => {
|
||||
// paper says + not =, but that makes no sense.
|
||||
let popped = self.scan_pop();
|
||||
self.buf[popped].size = 1;
|
||||
self.scan_pop();
|
||||
self.buf[x].size = 1;
|
||||
self.check_stack(k + 1);
|
||||
}
|
||||
_ => {
|
||||
let popped = self.scan_pop();
|
||||
self.buf[popped].size = self.buf[x].size + self.right_total;
|
||||
self.scan_pop();
|
||||
self.buf[x].size += self.right_total;
|
||||
if k > 0 {
|
||||
self.check_stack(k);
|
||||
}
|
||||
@ -486,19 +482,19 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn print_newline(&mut self, amount: isize) {
|
||||
fn print_newline(&mut self, amount: isize) {
|
||||
debug!("NEWLINE {}", amount);
|
||||
self.out.push('\n');
|
||||
self.pending_indentation = 0;
|
||||
self.indent(amount);
|
||||
}
|
||||
|
||||
crate fn indent(&mut self, amount: isize) {
|
||||
fn indent(&mut self, amount: isize) {
|
||||
debug!("INDENT {}", amount);
|
||||
self.pending_indentation += amount;
|
||||
}
|
||||
|
||||
crate fn get_top(&mut self) -> PrintStackElem {
|
||||
fn get_top(&mut self) -> PrintStackElem {
|
||||
match self.print_stack.last() {
|
||||
Some(el) => *el,
|
||||
None => PrintStackElem {
|
||||
@ -508,7 +504,7 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn print_begin(&mut self, b: BeginToken, l: isize) {
|
||||
fn print_begin(&mut self, b: BeginToken, l: isize) {
|
||||
if l > self.space {
|
||||
let col = self.margin - self.space + b.offset;
|
||||
debug!("print Begin -> push broken block at col {}", col);
|
||||
@ -525,14 +521,12 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn print_end(&mut self) {
|
||||
fn print_end(&mut self) {
|
||||
debug!("print End -> pop End");
|
||||
let print_stack = &mut self.print_stack;
|
||||
assert!(!print_stack.is_empty());
|
||||
print_stack.pop().unwrap();
|
||||
self.print_stack.pop().unwrap();
|
||||
}
|
||||
|
||||
crate fn print_break(&mut self, b: BreakToken, l: isize) {
|
||||
fn print_break(&mut self, b: BreakToken, l: isize) {
|
||||
let top = self.get_top();
|
||||
match top.pbreak {
|
||||
PrintStackBreak::Fits => {
|
||||
@ -562,7 +556,8 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn print_string(&mut self, s: Cow<'static, str>, len: isize) {
|
||||
fn print_string(&mut self, s: Cow<'static, str>) {
|
||||
let len = s.len() as isize;
|
||||
debug!("print String({})", s);
|
||||
// assert!(len <= space);
|
||||
self.space -= len;
|
||||
@ -579,7 +574,7 @@ impl<'a> Printer<'a> {
|
||||
self.out.push_str(&s);
|
||||
}
|
||||
|
||||
crate fn print(&mut self, token: Token, l: isize) {
|
||||
fn print(&mut self, token: Token, l: isize) {
|
||||
debug!("print {} {} (remaining line space={})", token, l,
|
||||
self.space);
|
||||
debug!("{}", buf_str(&self.buf,
|
||||
@ -590,9 +585,10 @@ impl<'a> Printer<'a> {
|
||||
Token::Begin(b) => self.print_begin(b, l),
|
||||
Token::End => self.print_end(),
|
||||
Token::Break(b) => self.print_break(b, l),
|
||||
Token::String(s, len) => {
|
||||
Token::String(s) => {
|
||||
let len = s.len() as isize;
|
||||
assert_eq!(len, l);
|
||||
self.print_string(s, len);
|
||||
self.print_string(s);
|
||||
}
|
||||
Token::Eof => panic!(), // Eof should never get here.
|
||||
}
|
||||
@ -601,15 +597,15 @@ impl<'a> Printer<'a> {
|
||||
// Convenience functions to talk to the printer.
|
||||
|
||||
/// "raw box"
|
||||
crate fn rbox(&mut self, indent: usize, b: Breaks) {
|
||||
self.pretty_print_begin(BeginToken {
|
||||
pub fn rbox(&mut self, indent: usize, b: Breaks) {
|
||||
self.scan_begin(BeginToken {
|
||||
offset: indent as isize,
|
||||
breaks: b
|
||||
})
|
||||
}
|
||||
|
||||
/// Inconsistent breaking box
|
||||
crate fn ibox(&mut self, indent: usize) {
|
||||
pub fn ibox(&mut self, indent: usize) {
|
||||
self.rbox(indent, Breaks::Inconsistent)
|
||||
}
|
||||
|
||||
@ -619,24 +615,24 @@ impl<'a> Printer<'a> {
|
||||
}
|
||||
|
||||
pub fn break_offset(&mut self, n: usize, off: isize) {
|
||||
self.pretty_print_break(BreakToken {
|
||||
self.scan_break(BreakToken {
|
||||
offset: off,
|
||||
blank_space: n as isize
|
||||
})
|
||||
}
|
||||
|
||||
crate fn end(&mut self) {
|
||||
self.pretty_print_end()
|
||||
pub fn end(&mut self) {
|
||||
self.scan_end()
|
||||
}
|
||||
|
||||
pub fn eof(&mut self) {
|
||||
self.pretty_print_eof()
|
||||
pub fn eof(mut self) -> String {
|
||||
self.scan_eof();
|
||||
self.out
|
||||
}
|
||||
|
||||
pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) {
|
||||
let s = wrd.into();
|
||||
let len = s.len() as isize;
|
||||
self.pretty_print_string(s, len)
|
||||
self.scan_string(s)
|
||||
}
|
||||
|
||||
fn spaces(&mut self, n: usize) {
|
||||
@ -655,6 +651,10 @@ impl<'a> Printer<'a> {
|
||||
self.spaces(SIZE_INFINITY as usize)
|
||||
}
|
||||
|
||||
pub fn is_beginning_of_line(&self) -> bool {
|
||||
self.last_token().is_eof() || self.last_token().is_hardbreak_tok()
|
||||
}
|
||||
|
||||
pub fn hardbreak_tok_offset(off: isize) -> Token {
|
||||
Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-filelength
|
||||
|
||||
use crate::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
||||
use crate::ast::{SelfKind, GenericBound, TraitBoundModifier};
|
||||
use crate::ast::{Attribute, MacDelimiter, GenericArg};
|
||||
@ -21,7 +19,6 @@ use syntax_pos::{self, BytePos};
|
||||
use syntax_pos::{DUMMY_SP, FileName, Span};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::io::Read;
|
||||
|
||||
pub enum AnnNode<'a> {
|
||||
Ident(&'a ast::Ident),
|
||||
@ -43,12 +40,53 @@ pub struct NoAnn;
|
||||
|
||||
impl PpAnn for NoAnn {}
|
||||
|
||||
pub struct Comments<'a> {
|
||||
cm: &'a SourceMap,
|
||||
comments: Vec<comments::Comment>,
|
||||
current: usize,
|
||||
}
|
||||
|
||||
impl<'a> Comments<'a> {
|
||||
pub fn new(
|
||||
cm: &'a SourceMap,
|
||||
sess: &ParseSess,
|
||||
filename: FileName,
|
||||
input: String,
|
||||
) -> Comments<'a> {
|
||||
let comments = comments::gather_comments(sess, filename, input);
|
||||
Comments {
|
||||
cm,
|
||||
comments,
|
||||
current: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next(&self) -> Option<comments::Comment> {
|
||||
self.comments.get(self.current).cloned()
|
||||
}
|
||||
|
||||
pub fn trailing_comment(
|
||||
&mut self,
|
||||
span: syntax_pos::Span,
|
||||
next_pos: Option<BytePos>,
|
||||
) -> Option<comments::Comment> {
|
||||
if let Some(cmnt) = self.next() {
|
||||
if cmnt.style != comments::Trailing { return None; }
|
||||
let span_line = self.cm.lookup_char_pos(span.hi());
|
||||
let comment_line = self.cm.lookup_char_pos(cmnt.pos);
|
||||
let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
|
||||
if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
|
||||
return Some(cmnt);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct State<'a> {
|
||||
pub s: pp::Printer<'a>,
|
||||
cm: Option<&'a SourceMap>,
|
||||
comments: Option<Vec<comments::Comment>>,
|
||||
cur_cmnt: usize,
|
||||
boxes: Vec<pp::Breaks>,
|
||||
pub s: pp::Printer,
|
||||
comments: Option<Comments<'a>>,
|
||||
ann: &'a (dyn PpAnn+'a),
|
||||
is_expanded: bool
|
||||
}
|
||||
@ -61,11 +99,15 @@ pub fn print_crate<'a>(cm: &'a SourceMap,
|
||||
sess: &ParseSess,
|
||||
krate: &ast::Crate,
|
||||
filename: FileName,
|
||||
input: &mut dyn Read,
|
||||
out: &mut String,
|
||||
input: String,
|
||||
ann: &'a dyn PpAnn,
|
||||
is_expanded: bool) {
|
||||
let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded);
|
||||
is_expanded: bool) -> String {
|
||||
let mut s = State {
|
||||
s: pp::mk_printer(),
|
||||
comments: Some(Comments::new(cm, sess, filename, input)),
|
||||
ann,
|
||||
is_expanded,
|
||||
};
|
||||
|
||||
if is_expanded && std_inject::injected_crate_name().is_some() {
|
||||
// We need to print `#![no_std]` (and its feature gate) so that
|
||||
@ -91,53 +133,17 @@ pub fn print_crate<'a>(cm: &'a SourceMap,
|
||||
s.s.eof()
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
pub fn new_from_input(cm: &'a SourceMap,
|
||||
sess: &ParseSess,
|
||||
filename: FileName,
|
||||
input: &mut dyn Read,
|
||||
out: &'a mut String,
|
||||
ann: &'a dyn PpAnn,
|
||||
is_expanded: bool) -> State<'a> {
|
||||
let comments = comments::gather_comments(sess, filename, input);
|
||||
State::new(cm, out, ann, Some(comments), is_expanded)
|
||||
}
|
||||
|
||||
pub fn new(cm: &'a SourceMap,
|
||||
out: &'a mut String,
|
||||
ann: &'a dyn PpAnn,
|
||||
comments: Option<Vec<comments::Comment>>,
|
||||
is_expanded: bool) -> State<'a> {
|
||||
State {
|
||||
s: pp::mk_printer(out),
|
||||
cm: Some(cm),
|
||||
comments,
|
||||
cur_cmnt: 0,
|
||||
boxes: Vec::new(),
|
||||
ann,
|
||||
is_expanded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string<F>(f: F) -> String where
|
||||
F: FnOnce(&mut State<'_>),
|
||||
{
|
||||
let mut wr = String::new();
|
||||
{
|
||||
let mut printer = State {
|
||||
s: pp::mk_printer(&mut wr),
|
||||
cm: None,
|
||||
comments: None,
|
||||
cur_cmnt: 0,
|
||||
boxes: Vec::new(),
|
||||
ann: &NoAnn,
|
||||
is_expanded: false
|
||||
};
|
||||
f(&mut printer);
|
||||
printer.s.eof();
|
||||
}
|
||||
wr
|
||||
let mut printer = State {
|
||||
s: pp::mk_printer(),
|
||||
comments: None,
|
||||
ann: &NoAnn,
|
||||
is_expanded: false
|
||||
};
|
||||
f(&mut printer);
|
||||
printer.s.eof()
|
||||
}
|
||||
|
||||
fn binop_to_string(op: BinOpToken) -> &'static str {
|
||||
@ -322,18 +328,10 @@ pub fn pat_to_string(pat: &ast::Pat) -> String {
|
||||
to_string(|s| s.print_pat(pat))
|
||||
}
|
||||
|
||||
pub fn arm_to_string(arm: &ast::Arm) -> String {
|
||||
to_string(|s| s.print_arm(arm))
|
||||
}
|
||||
|
||||
pub fn expr_to_string(e: &ast::Expr) -> String {
|
||||
to_string(|s| s.print_expr(e))
|
||||
}
|
||||
|
||||
pub fn lifetime_to_string(lt: &ast::Lifetime) -> String {
|
||||
to_string(|s| s.print_lifetime(*lt))
|
||||
}
|
||||
|
||||
pub fn tt_to_string(tt: tokenstream::TokenTree) -> String {
|
||||
to_string(|s| s.print_tt(tt, false))
|
||||
}
|
||||
@ -350,19 +348,15 @@ pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
|
||||
to_string(|s| s.print_stmt(stmt))
|
||||
}
|
||||
|
||||
pub fn attr_to_string(attr: &ast::Attribute) -> String {
|
||||
to_string(|s| s.print_attribute(attr))
|
||||
}
|
||||
|
||||
pub fn item_to_string(i: &ast::Item) -> String {
|
||||
to_string(|s| s.print_item(i))
|
||||
}
|
||||
|
||||
pub fn impl_item_to_string(i: &ast::ImplItem) -> String {
|
||||
fn impl_item_to_string(i: &ast::ImplItem) -> String {
|
||||
to_string(|s| s.print_impl_item(i))
|
||||
}
|
||||
|
||||
pub fn trait_item_to_string(i: &ast::TraitItem) -> String {
|
||||
fn trait_item_to_string(i: &ast::TraitItem) -> String {
|
||||
to_string(|s| s.print_trait_item(i))
|
||||
}
|
||||
|
||||
@ -370,14 +364,6 @@ pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String
|
||||
to_string(|s| s.print_generic_params(generic_params))
|
||||
}
|
||||
|
||||
pub fn where_clause_to_string(i: &ast::WhereClause) -> String {
|
||||
to_string(|s| s.print_where_clause(i))
|
||||
}
|
||||
|
||||
pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
|
||||
to_string(|s| s.print_fn_block_args(p))
|
||||
}
|
||||
|
||||
pub fn path_to_string(p: &ast::Path) -> String {
|
||||
to_string(|s| s.print_path(p, false, 0))
|
||||
}
|
||||
@ -390,7 +376,8 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
|
||||
to_string(|s| s.print_visibility(v))
|
||||
}
|
||||
|
||||
pub fn fun_to_string(decl: &ast::FnDecl,
|
||||
#[cfg(test)]
|
||||
fn fun_to_string(decl: &ast::FnDecl,
|
||||
header: ast::FnHeader,
|
||||
name: ast::Ident,
|
||||
generics: &ast::Generics)
|
||||
@ -404,7 +391,7 @@ pub fn fun_to_string(decl: &ast::FnDecl,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn block_to_string(blk: &ast::Block) -> String {
|
||||
fn block_to_string(blk: &ast::Block) -> String {
|
||||
to_string(|s| {
|
||||
// containing cbox, will be closed by print-block at }
|
||||
s.cbox(INDENT_UNIT);
|
||||
@ -426,11 +413,8 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String {
|
||||
to_string(|s| s.print_attribute(attr))
|
||||
}
|
||||
|
||||
pub fn lit_to_string(l: &ast::Lit) -> String {
|
||||
to_string(|s| s.print_literal(l))
|
||||
}
|
||||
|
||||
pub fn variant_to_string(var: &ast::Variant) -> String {
|
||||
#[cfg(test)]
|
||||
fn variant_to_string(var: &ast::Variant) -> String {
|
||||
to_string(|s| s.print_variant(var))
|
||||
}
|
||||
|
||||
@ -438,73 +422,29 @@ pub fn arg_to_string(arg: &ast::Arg) -> String {
|
||||
to_string(|s| s.print_arg(arg, false))
|
||||
}
|
||||
|
||||
pub fn mac_to_string(arg: &ast::Mac) -> String {
|
||||
to_string(|s| s.print_mac(arg))
|
||||
}
|
||||
|
||||
pub fn foreign_item_to_string(arg: &ast::ForeignItem) -> String {
|
||||
fn foreign_item_to_string(arg: &ast::ForeignItem) -> String {
|
||||
to_string(|s| s.print_foreign_item(arg))
|
||||
}
|
||||
|
||||
pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
|
||||
fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
|
||||
format!("{}{}", to_string(|s| s.print_visibility(vis)), s)
|
||||
}
|
||||
|
||||
pub trait PrintState<'a> {
|
||||
fn writer(&mut self) -> &mut pp::Printer<'a>;
|
||||
fn boxes(&mut self) -> &mut Vec<pp::Breaks>;
|
||||
fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>;
|
||||
fn cur_cmnt(&mut self) -> &mut usize;
|
||||
|
||||
fn word_space<S: Into<Cow<'static, str>>>(&mut self, w: S) {
|
||||
self.writer().word(w);
|
||||
self.writer().space()
|
||||
impl std::ops::Deref for State<'_> {
|
||||
type Target = pp::Printer;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.s
|
||||
}
|
||||
}
|
||||
|
||||
fn popen(&mut self) { self.writer().word("(") }
|
||||
|
||||
fn pclose(&mut self) { self.writer().word(")") }
|
||||
|
||||
fn is_begin(&mut self) -> bool {
|
||||
match self.writer().last_token() {
|
||||
pp::Token::Begin(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
impl std::ops::DerefMut for State<'_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.s
|
||||
}
|
||||
}
|
||||
|
||||
fn is_end(&mut self) -> bool {
|
||||
match self.writer().last_token() {
|
||||
pp::Token::End => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// is this the beginning of a line?
|
||||
fn is_bol(&mut self) -> bool {
|
||||
self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
|
||||
}
|
||||
|
||||
fn hardbreak_if_not_bol(&mut self) {
|
||||
if !self.is_bol() {
|
||||
self.writer().hardbreak()
|
||||
}
|
||||
}
|
||||
|
||||
// "raw box"
|
||||
fn rbox(&mut self, u: usize, b: pp::Breaks) {
|
||||
self.boxes().push(b);
|
||||
self.writer().rbox(u, b)
|
||||
}
|
||||
|
||||
fn ibox(&mut self, u: usize) {
|
||||
self.boxes().push(pp::Breaks::Inconsistent);
|
||||
self.writer().ibox(u);
|
||||
}
|
||||
|
||||
fn end(&mut self) {
|
||||
self.boxes().pop().unwrap();
|
||||
self.writer().end()
|
||||
}
|
||||
pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefMut {
|
||||
fn comments(&mut self) -> &mut Option<Comments<'a>>;
|
||||
|
||||
fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F)
|
||||
where F: FnMut(&mut Self, &T),
|
||||
@ -533,9 +473,9 @@ pub trait PrintState<'a> {
|
||||
match cmnt.style {
|
||||
comments::Mixed => {
|
||||
assert_eq!(cmnt.lines.len(), 1);
|
||||
self.writer().zerobreak();
|
||||
self.writer().word(cmnt.lines[0].clone());
|
||||
self.writer().zerobreak()
|
||||
self.zerobreak();
|
||||
self.word(cmnt.lines[0].clone());
|
||||
self.zerobreak()
|
||||
}
|
||||
comments::Isolated => {
|
||||
self.hardbreak_if_not_bol();
|
||||
@ -543,61 +483,55 @@ pub trait PrintState<'a> {
|
||||
// Don't print empty lines because they will end up as trailing
|
||||
// whitespace
|
||||
if !line.is_empty() {
|
||||
self.writer().word(line.clone());
|
||||
self.word(line.clone());
|
||||
}
|
||||
self.writer().hardbreak();
|
||||
self.hardbreak();
|
||||
}
|
||||
}
|
||||
comments::Trailing => {
|
||||
if !self.is_bol() {
|
||||
self.writer().word(" ");
|
||||
if !self.is_beginning_of_line() {
|
||||
self.word(" ");
|
||||
}
|
||||
if cmnt.lines.len() == 1 {
|
||||
self.writer().word(cmnt.lines[0].clone());
|
||||
self.writer().hardbreak()
|
||||
self.word(cmnt.lines[0].clone());
|
||||
self.hardbreak()
|
||||
} else {
|
||||
self.ibox(0);
|
||||
for line in &cmnt.lines {
|
||||
if !line.is_empty() {
|
||||
self.writer().word(line.clone());
|
||||
self.word(line.clone());
|
||||
}
|
||||
self.writer().hardbreak();
|
||||
self.hardbreak();
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
}
|
||||
comments::BlankLine => {
|
||||
// We need to do at least one, possibly two hardbreaks.
|
||||
let is_semi = match self.writer().last_token() {
|
||||
pp::Token::String(s, _) => ";" == s,
|
||||
let twice = match self.last_token() {
|
||||
pp::Token::String(s) => ";" == s,
|
||||
pp::Token::Begin(_) => true,
|
||||
pp::Token::End => true,
|
||||
_ => false
|
||||
};
|
||||
if is_semi || self.is_begin() || self.is_end() {
|
||||
self.writer().hardbreak();
|
||||
if twice {
|
||||
self.hardbreak();
|
||||
}
|
||||
self.writer().hardbreak();
|
||||
self.hardbreak();
|
||||
}
|
||||
}
|
||||
*self.cur_cmnt() = *self.cur_cmnt() + 1;
|
||||
if let Some(cm) = self.comments() {
|
||||
cm.current += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn next_comment(&mut self) -> Option<comments::Comment> {
|
||||
let cur_cmnt = *self.cur_cmnt();
|
||||
match *self.comments() {
|
||||
Some(ref cmnts) => {
|
||||
if cur_cmnt < cmnts.len() {
|
||||
Some(cmnts[cur_cmnt].clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
self.comments().as_mut().and_then(|c| c.next())
|
||||
}
|
||||
|
||||
fn print_literal(&mut self, lit: &ast::Lit) {
|
||||
self.maybe_print_comment(lit.span.lo());
|
||||
self.writer().word(literal_to_string(lit.token))
|
||||
self.word(lit.token.to_string())
|
||||
}
|
||||
|
||||
fn print_string(&mut self, st: &str,
|
||||
@ -612,7 +546,7 @@ pub trait PrintState<'a> {
|
||||
string=st))
|
||||
}
|
||||
};
|
||||
self.writer().word(st)
|
||||
self.word(st)
|
||||
}
|
||||
|
||||
fn print_inner_attributes(&mut self,
|
||||
@ -664,10 +598,10 @@ pub trait PrintState<'a> {
|
||||
fn print_attribute_path(&mut self, path: &ast::Path) {
|
||||
for (i, segment) in path.segments.iter().enumerate() {
|
||||
if i > 0 {
|
||||
self.writer().word("::");
|
||||
self.word("::");
|
||||
}
|
||||
if segment.ident.name != kw::PathRoot {
|
||||
self.writer().word(ident_to_string(segment.ident, segment.ident.is_raw_guess()));
|
||||
self.word(ident_to_string(segment.ident, segment.ident.is_raw_guess()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -683,21 +617,21 @@ pub trait PrintState<'a> {
|
||||
}
|
||||
self.maybe_print_comment(attr.span.lo());
|
||||
if attr.is_sugared_doc {
|
||||
self.writer().word(attr.value_str().unwrap().as_str().to_string());
|
||||
self.writer().hardbreak()
|
||||
self.word(attr.value_str().unwrap().as_str().to_string());
|
||||
self.hardbreak()
|
||||
} else {
|
||||
match attr.style {
|
||||
ast::AttrStyle::Inner => self.writer().word("#!["),
|
||||
ast::AttrStyle::Outer => self.writer().word("#["),
|
||||
ast::AttrStyle::Inner => self.word("#!["),
|
||||
ast::AttrStyle::Outer => self.word("#["),
|
||||
}
|
||||
if let Some(mi) = attr.meta() {
|
||||
self.print_meta_item(&mi);
|
||||
} else {
|
||||
self.print_attribute_path(&attr.path);
|
||||
self.writer().space();
|
||||
self.space();
|
||||
self.print_tts(attr.tokens.clone());
|
||||
}
|
||||
self.writer().word("]");
|
||||
self.word("]");
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,7 +652,7 @@ pub trait PrintState<'a> {
|
||||
ast::MetaItemKind::Word => self.print_attribute_path(&item.path),
|
||||
ast::MetaItemKind::NameValue(ref value) => {
|
||||
self.print_attribute_path(&item.path);
|
||||
self.writer().space();
|
||||
self.space();
|
||||
self.word_space("=");
|
||||
self.print_literal(value);
|
||||
}
|
||||
@ -744,20 +678,20 @@ pub trait PrintState<'a> {
|
||||
fn print_tt(&mut self, tt: tokenstream::TokenTree, convert_dollar_crate: bool) {
|
||||
match tt {
|
||||
TokenTree::Token(ref token) => {
|
||||
self.writer().word(token_to_string_ext(&token, convert_dollar_crate));
|
||||
self.word(token_to_string_ext(&token, convert_dollar_crate));
|
||||
match token.kind {
|
||||
token::DocComment(..) => {
|
||||
self.writer().hardbreak()
|
||||
self.hardbreak()
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
TokenTree::Delimited(_, delim, tts) => {
|
||||
self.writer().word(token_kind_to_string(&token::OpenDelim(delim)));
|
||||
self.writer().space();
|
||||
self.word(token_kind_to_string(&token::OpenDelim(delim)));
|
||||
self.space();
|
||||
self.print_tts(tts);
|
||||
self.writer().space();
|
||||
self.writer().word(token_kind_to_string(&token::CloseDelim(delim)))
|
||||
self.space();
|
||||
self.word(token_kind_to_string(&token::CloseDelim(delim)))
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -770,49 +704,21 @@ pub trait PrintState<'a> {
|
||||
self.ibox(0);
|
||||
for (i, tt) in tts.into_trees().enumerate() {
|
||||
if i != 0 {
|
||||
self.writer().space();
|
||||
self.space();
|
||||
}
|
||||
self.print_tt(tt, convert_dollar_crate);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
fn space_if_not_bol(&mut self) {
|
||||
if !self.is_bol() { self.writer().space(); }
|
||||
}
|
||||
|
||||
fn nbsp(&mut self) { self.writer().word(" ") }
|
||||
}
|
||||
|
||||
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>> {
|
||||
fn comments(&mut self) -> &mut Option<Comments<'a>> {
|
||||
&mut self.comments
|
||||
}
|
||||
|
||||
fn cur_cmnt(&mut self) -> &mut usize {
|
||||
&mut self.cur_cmnt
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
pub fn cbox(&mut self, u: usize) {
|
||||
self.boxes.push(pp::Breaks::Consistent);
|
||||
self.s.cbox(u);
|
||||
}
|
||||
|
||||
crate fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) {
|
||||
self.s.word(w);
|
||||
self.nbsp()
|
||||
}
|
||||
|
||||
crate fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
|
||||
let w = w.into();
|
||||
// outer-box is consistent
|
||||
@ -830,26 +736,21 @@ impl<'a> State<'a> {
|
||||
self.end(); // close the head-box
|
||||
}
|
||||
|
||||
crate fn bclose_(&mut self, span: syntax_pos::Span,
|
||||
indented: usize) {
|
||||
self.bclose_maybe_open(span, indented, true)
|
||||
}
|
||||
crate fn bclose_maybe_open(&mut self, span: syntax_pos::Span,
|
||||
indented: usize, close_box: bool) {
|
||||
crate fn bclose_maybe_open(&mut self, span: syntax_pos::Span, close_box: bool) {
|
||||
self.maybe_print_comment(span.hi());
|
||||
self.break_offset_if_not_bol(1, -(indented as isize));
|
||||
self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
|
||||
self.s.word("}");
|
||||
if close_box {
|
||||
self.end(); // close the outer-box
|
||||
}
|
||||
}
|
||||
crate fn bclose(&mut self, span: syntax_pos::Span) {
|
||||
self.bclose_(span, INDENT_UNIT)
|
||||
self.bclose_maybe_open(span, true)
|
||||
}
|
||||
|
||||
crate fn break_offset_if_not_bol(&mut self, n: usize,
|
||||
off: isize) {
|
||||
if !self.is_bol() {
|
||||
if !self.s.is_beginning_of_line() {
|
||||
self.s.break_offset(n, off)
|
||||
} else {
|
||||
if off != 0 && self.s.last_token().is_hardbreak_tok() {
|
||||
@ -1650,20 +1551,18 @@ impl<'a> State<'a> {
|
||||
self.print_block_with_attrs(blk, &[])
|
||||
}
|
||||
|
||||
crate fn print_block_unclosed_indent(&mut self, blk: &ast::Block,
|
||||
indented: usize) {
|
||||
self.print_block_maybe_unclosed(blk, indented, &[], false)
|
||||
crate fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
|
||||
self.print_block_maybe_unclosed(blk, &[], false)
|
||||
}
|
||||
|
||||
crate fn print_block_with_attrs(&mut self,
|
||||
blk: &ast::Block,
|
||||
attrs: &[ast::Attribute]) {
|
||||
self.print_block_maybe_unclosed(blk, INDENT_UNIT, attrs, true)
|
||||
self.print_block_maybe_unclosed(blk, attrs, true)
|
||||
}
|
||||
|
||||
crate fn print_block_maybe_unclosed(&mut self,
|
||||
blk: &ast::Block,
|
||||
indented: usize,
|
||||
attrs: &[ast::Attribute],
|
||||
close_box: bool) {
|
||||
match blk.rules {
|
||||
@ -1688,7 +1587,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
self.bclose_maybe_open(blk.span, indented, close_box);
|
||||
self.bclose_maybe_open(blk.span, close_box);
|
||||
self.ann.post(self, AnnNode::Block(blk))
|
||||
}
|
||||
|
||||
@ -2070,7 +1969,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
ast::ExprKind::Match(ref expr, ref arms) => {
|
||||
self.cbox(INDENT_UNIT);
|
||||
self.ibox(4);
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.word_nbsp("match");
|
||||
self.print_expr_as_cond(expr);
|
||||
self.s.space();
|
||||
@ -2079,7 +1978,7 @@ impl<'a> State<'a> {
|
||||
for arm in arms {
|
||||
self.print_arm(arm);
|
||||
}
|
||||
self.bclose_(expr.span, INDENT_UNIT);
|
||||
self.bclose(expr.span);
|
||||
}
|
||||
ast::ExprKind::Closure(
|
||||
capture_clause, asyncness, movability, ref decl, ref body, _) => {
|
||||
@ -2610,7 +2509,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
// the block will close the pattern's ibox
|
||||
self.print_block_unclosed_indent(blk, INDENT_UNIT);
|
||||
self.print_block_unclosed_indent(blk);
|
||||
|
||||
// If it is a user-provided unsafe block, print a comma after it
|
||||
if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
|
||||
@ -2963,18 +2862,10 @@ impl<'a> State<'a> {
|
||||
|
||||
crate fn maybe_print_trailing_comment(&mut self, span: syntax_pos::Span,
|
||||
next_pos: Option<BytePos>)
|
||||
{
|
||||
let cm = match self.cm {
|
||||
Some(cm) => cm,
|
||||
_ => return,
|
||||
};
|
||||
if let Some(ref cmnt) = self.next_comment() {
|
||||
if cmnt.style != comments::Trailing { return; }
|
||||
let span_line = cm.lookup_char_pos(span.hi());
|
||||
let comment_line = cm.lookup_char_pos(cmnt.pos);
|
||||
let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
|
||||
if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
|
||||
self.print_comment(cmnt);
|
||||
{
|
||||
if let Some(cmnts) = self.comments() {
|
||||
if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
|
||||
self.print_comment(&cmnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ fn main() {
|
||||
// _1 = ();
|
||||
// StorageDead(_2);
|
||||
// StorageDead(_1);
|
||||
// StorageLive(_4);
|
||||
// goto -> bb5;
|
||||
// }
|
||||
// ...
|
||||
|
14
src/test/ui/borrowck/assign-never-type.rs
Normal file
14
src/test/ui/borrowck/assign-never-type.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// Regression test for issue 62165
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(never_type)]
|
||||
|
||||
pub fn main() {
|
||||
loop {
|
||||
match None {
|
||||
None => return,
|
||||
Some(val) => val,
|
||||
};
|
||||
};
|
||||
}
|
@ -9,10 +9,21 @@ impl Drop for FakeNeedsDrop {
|
||||
// ok
|
||||
const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x };
|
||||
|
||||
// ok (used to incorrectly error, see #62273)
|
||||
const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x };
|
||||
|
||||
// error
|
||||
const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
||||
//~^ ERROR constant contains unimplemented expression type
|
||||
//~^ ERROR destructors cannot be evaluated at compile-time
|
||||
|
||||
// error
|
||||
const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
||||
//~^ ERROR destructors cannot be evaluated at compile-time
|
||||
|
||||
// error
|
||||
const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
|
||||
//~^ ERROR constant contains unimplemented expression type
|
||||
//~^ ERROR destructors cannot be evaluated at compile-time
|
||||
|
||||
// error
|
||||
const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
|
||||
//~^ ERROR destructors cannot be evaluated at compile-time
|
||||
|
@ -1,15 +1,26 @@
|
||||
error[E0019]: constant contains unimplemented expression type
|
||||
--> $DIR/const_let.rs:13:55
|
||||
error[E0493]: destructors cannot be evaluated at compile-time
|
||||
--> $DIR/const_let.rs:16:32
|
||||
|
|
||||
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
||||
| ^
|
||||
| ^^^^^ constants cannot evaluate destructors
|
||||
|
||||
error[E0019]: constant contains unimplemented expression type
|
||||
--> $DIR/const_let.rs:17:35
|
||||
error[E0493]: destructors cannot be evaluated at compile-time
|
||||
--> $DIR/const_let.rs:20:33
|
||||
|
|
||||
LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
|
||||
| ^^^^^ constants cannot evaluate destructors
|
||||
|
||||
error[E0493]: destructors cannot be evaluated at compile-time
|
||||
--> $DIR/const_let.rs:24:21
|
||||
|
|
||||
LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
|
||||
| ^
|
||||
| ^^^^^ constants cannot evaluate destructors
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0493]: destructors cannot be evaluated at compile-time
|
||||
--> $DIR/const_let.rs:28:22
|
||||
|
|
||||
LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
|
||||
| ^^^^^ constants cannot evaluate destructors
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0019`.
|
||||
|
Loading…
Reference in New Issue
Block a user