diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 6eddac672c158..7e941267ce824 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -263,9 +263,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn last(self) -> Option 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. diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 2a6c2b1331e5c..df66a2978de41 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -669,6 +669,22 @@ pub unsafe fn read(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::()); +/// +/// 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(src: *const T) -> T { @@ -839,6 +855,22 @@ pub unsafe fn write(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::()); +/// +/// 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(dst: *mut T, src: T) { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 63f60d0ab9528..9fb85410fc77a 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -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) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 6817107635a60..5a14b30e699be 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -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>, - cur_cmnt: usize, - boxes: Vec, + pub s: pp::Printer, + comments: Option>, ann: &'a (dyn PpAnn + 'a), } -impl<'a> PrintState<'a> for State<'a> { - fn writer(&mut self) -> &mut pp::Printer<'a> { - &mut self.s +impl std::ops::Deref for State<'_> { + type Target = pp::Printer; + fn deref(&self) -> &Self::Target { + &self.s } +} - fn boxes(&mut self) -> &mut Vec { - &mut self.boxes +impl std::ops::DerefMut for State<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.s } +} - fn comments(&mut self) -> &mut Option> { +impl<'a> PrintState<'a> for State<'a> { + fn comments(&mut self) -> &mut Option> { &mut self.comments } - - fn cur_cmnt(&mut self) -> &mut usize { - &mut self.cur_cmnt - } } -#[allow(non_upper_case_globals)] -pub const indent_unit: usize = 4; +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>) - -> 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(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>>(vis: &hir::Visibility, w: S) -> String { @@ -175,7 +148,6 @@ pub fn visibility_qualified>>(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>>(&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) { - 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); } } } diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs index f1f9f3f71e4a3..94849728a9319 100644 --- a/src/librustc_borrowck/dataflow.rs +++ b/src/librustc_borrowck/dataflow.rs @@ -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) })); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index fc55d5ac3559a..51b161c376802 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -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, 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(); }) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c7f57be642618..567b6b1a891bf 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -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::>()), + body: pprust::tokens_to_string(macro_def.body.clone()), legacy: macro_def.legacy, })), visibility: self.lazy(&ty::Visibility::Public), diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 0640c01d255c2..82accb47437c6 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -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) = ( diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 1fe6be8bbc82e..dbcc330eca382 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -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, + ); + } } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 2dffafd6e54c0..1fa539f8a2aee 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c627596bbdf20..8801e89a0cfc4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index a7c5ed158e028..ee7fb97ffd718 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -162,6 +162,7 @@ pub mod visit; pub mod print { pub mod pp; pub mod pprust; + mod helpers; } pub mod ext { diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index edcdb18a037d8..ae24047ac8249 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -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); diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 988f1aa38d926..6ed2a7adad1c2 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -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 +pub fn gather_comments(sess: &ParseSess, path: FileName, src: String) -> Vec { - 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); diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index ef55bf6b92933..683d164156540 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -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!()) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a95b6891fb9d5..83dbff6b2d574 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index ebd0decacb59f..472e4b474d627 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -80,6 +80,34 @@ pub struct Lit { pub suffix: Option, } +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)); diff --git a/src/libsyntax/print/helpers.rs b/src/libsyntax/print/helpers.rs new file mode 100644 index 0000000000000..3449e07f4562d --- /dev/null +++ b/src/libsyntax/print/helpers.rs @@ -0,0 +1,34 @@ +use std::borrow::Cow; +use crate::print::pp::Printer; + +impl Printer { + pub fn word_space>>(&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>>(&mut self, w: S) { + self.word(w); + self.nbsp() + } +} diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index f64e95aee5bca..660e77f77d0f2 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -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>>(&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}) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 7e099bc4d5095..8050026a00d9e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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, + 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 { + self.comments.get(self.current).cloned() + } + + pub fn trailing_comment( + &mut self, + span: syntax_pos::Span, + next_pos: Option, + ) -> Option { + 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>, - cur_cmnt: usize, - boxes: Vec, + pub s: pp::Printer, + comments: Option>, 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>, - 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) -> 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; - fn comments(&mut self) -> &mut Option>; - fn cur_cmnt(&mut self) -> &mut usize; - - fn word_space>>(&mut self, w: S) { - self.writer().word(w); - self.writer().space() - } - - 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, - } - } - - 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) +impl std::ops::Deref for State<'_> { + type Target = pp::Printer; + fn deref(&self) -> &Self::Target { + &self.s } +} - fn ibox(&mut self, u: usize) { - self.boxes().push(pp::Breaks::Inconsistent); - self.writer().ibox(u); +impl std::ops::DerefMut for State<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.s } +} - fn end(&mut self) { - self.boxes().pop().unwrap(); - self.writer().end() - } +pub trait PrintState<'a>: std::ops::Deref + std::ops::DerefMut { + fn comments(&mut self) -> &mut Option>; fn commasep(&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 { - 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 { - &mut self.boxes - } - - fn comments(&mut self) -> &mut Option> { + fn comments(&mut self) -> &mut Option> { &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>>(&mut self, w: S) { - self.s.word(w); - self.nbsp() - } - crate fn head>>(&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) - { - 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); } } } diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs index 177080c04f972..418febbdc01eb 100644 --- a/src/test/mir-opt/loop_test.rs +++ b/src/test/mir-opt/loop_test.rs @@ -26,6 +26,7 @@ fn main() { // _1 = (); // StorageDead(_2); // StorageDead(_1); +// StorageLive(_4); // goto -> bb5; // } // ... diff --git a/src/test/ui/borrowck/assign-never-type.rs b/src/test/ui/borrowck/assign-never-type.rs new file mode 100644 index 0000000000000..4f30ea1467023 --- /dev/null +++ b/src/test/ui/borrowck/assign-never-type.rs @@ -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, + }; + }; +} diff --git a/src/test/ui/consts/const-eval/const_let.rs b/src/test/ui/consts/const-eval/const_let.rs index 63321b9120076..18692dbced679 100644 --- a/src/test/ui/consts/const-eval/const_let.rs +++ b/src/test/ui/consts/const-eval/const_let.rs @@ -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 diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr index 00de97e6fb3a0..0a6a222ae2963 100644 --- a/src/test/ui/consts/const-eval/const_let.stderr +++ b/src/test/ui/consts/const-eval/const_let.stderr @@ -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[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 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0019`.