X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Ftypes.rs;h=10b46959136e65c7386b66d6981a3fe1e1d4e0b2;hb=b58ba97780b087281ad738e8431d2338846026d5;hp=07794030ba8deab90d5071fc1011e4c0b20c6a75;hpb=01c14a2058924390543f072aeb5955a8d179df36;p=rust.git diff --git a/src/types.rs b/src/types.rs index 07794030ba8..10b46959136 100644 --- a/src/types.rs +++ b/src/types.rs @@ -11,22 +11,22 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; -use config::lists::*; use syntax::ast::{self, FunctionRetTy, Mutability}; use syntax::source_map::{self, BytePos, Span}; use syntax::symbol::keywords; -use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ToExpr}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use macros::{rewrite_macro, MacroPosition}; -use overflow; -use pairs::{rewrite_pair, PairParts}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use spanned::Spanned; -use utils::{ +use crate::config::lists::*; +use crate::config::{IndentStyle, TypeDensity}; +use crate::expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix}; +use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::macros::{rewrite_macro, MacroPosition}; +use crate::overflow; +use crate::pairs::{rewrite_pair, PairParts}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::utils::{ colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_extendable, last_line_width, mk_sp, rewrite_ident, }; @@ -40,7 +40,7 @@ pub enum PathContext { // Does not wrap on simple segments. pub fn rewrite_path( - context: &RewriteContext, + context: &RewriteContext<'_>, path_context: PathContext, qself: Option<&ast::QSelf>, path: &ast::Path, @@ -103,7 +103,7 @@ fn rewrite_path_segments<'a, I>( iter: I, mut span_lo: BytePos, span_hi: BytePos, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option where @@ -114,7 +114,7 @@ fn rewrite_path_segments<'a, I>( for segment in iter { // Indicates a global path, shouldn't be rendered. - if segment.ident.name == keywords::CrateRoot.name() { + if segment.ident.name == keywords::PathRoot.name() { continue; } if first { @@ -141,17 +141,18 @@ fn rewrite_path_segments<'a, I>( } #[derive(Debug)] -enum SegmentParam<'a> { +pub enum SegmentParam<'a> { LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), Binding(&'a ast::TypeBinding), } impl<'a> SegmentParam<'a> { - fn from_generic_arg(arg: &ast::GenericArg) -> SegmentParam { + fn from_generic_arg(arg: &ast::GenericArg) -> SegmentParam<'_> { match arg { ast::GenericArg::Lifetime(ref lt) => SegmentParam::LifeTime(lt), ast::GenericArg::Type(ref ty) => SegmentParam::Type(ty), + ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) } } } @@ -166,21 +167,8 @@ fn span(&self) -> Span { } } -impl<'a> ToExpr for SegmentParam<'a> { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - match *self { - SegmentParam::Type(ty) => ty.can_be_overflowed(context, len), - _ => false, - } - } -} - impl<'a> Rewrite for SegmentParam<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), @@ -217,7 +205,7 @@ fn rewrite_segment( segment: &ast::PathSegment, span_lo: &mut BytePos, span_hi: BytePos, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let mut result = String::with_capacity(128); @@ -242,7 +230,15 @@ fn rewrite_segment( .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let separator = if path_context == PathContext::Expr { + // HACK: squeeze out the span between the identifier and the parameters. + // The hack is requried so that we don't remove the separator inside macro calls. + // This does not work in the presence of comment, hoping that people are + // sane about where to put their comment. + let separator_snippet = context + .snippet(mk_sp(segment.ident.span.hi(), data.span.lo())) + .trim(); + let force_separator = context.inside_macro() && separator_snippet.starts_with("::"); + let separator = if path_context == PathContext::Expr || force_separator { "::" } else { "" @@ -252,7 +248,7 @@ fn rewrite_segment( let generics_str = overflow::rewrite_with_angle_brackets( context, "", - ¶m_list.iter().map(|e| &*e).collect::>(), + param_list.iter(), shape, mk_sp(*span_lo, span_hi), )?; @@ -290,7 +286,7 @@ fn format_function_type<'a, I>( output: &FunctionRetTy, variadic: bool, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option where @@ -300,6 +296,19 @@ fn format_function_type<'a, I>( { debug!("format_function_type {:#?}", shape); + let ty_shape = match context.config.indent_style() { + // 4 = " -> " + IndentStyle::Block => shape.offset_left(4)?, + IndentStyle::Visual => shape.block_left(4)?, + }; + let output = match *output { + FunctionRetTy::Ty(ref ty) => { + let type_str = ty.rewrite(context, ty_shape)?; + format!(" -> {}", type_str) + } + FunctionRetTy::Default(..) => String::new(), + }; + // Code for handling variadics is somewhat duplicated for items, but they // are different enough to need some serious refactoring to share code. enum ArgumentKind @@ -318,19 +327,18 @@ enum ArgumentKind None }; - // 2 for () - let budget = shape.width.checked_sub(2)?; - // 1 for ( - let offset = match context.config.indent_style() { - IndentStyle::Block => { - shape - .block() - .block_indent(context.config.tab_spaces()) - .indent - } - IndentStyle::Visual => shape.indent + 1, + let list_shape = if context.use_block_indent() { + Shape::indented( + shape.block().indent.block_indent(context.config), + context.config, + ) + } else { + // 2 for () + let budget = shape.width.checked_sub(2)?; + // 1 for ( + let offset = shape.indent + 1; + Shape::legacy(budget, offset) }; - let list_shape = Shape::legacy(budget, offset); let list_lo = context.snippet_provider.span_after(span, "("); let items = itemize_list( context.snippet_provider, @@ -356,12 +364,18 @@ enum ArgumentKind let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic( - &*item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - budget, - ); + // If the return type is multi-lined, then force to use multiple lines for + // arguments as well. + let tactic = if output.contains('\n') { + DefinitiveListTactic::Vertical + } else { + definitive_tactic( + &*item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + shape.width.saturating_sub(2 + output.len()), + ) + }; let trailing_separator = if !context.use_block_indent() || variadic { SeparatorTactic::Never } else { @@ -375,27 +389,12 @@ enum ArgumentKind .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; - let ty_shape = match context.config.indent_style() { - // 4 = " -> " - IndentStyle::Block => shape.offset_left(4)?, - IndentStyle::Visual => shape.block_left(4)?, - }; - let output = match *output { - FunctionRetTy::Ty(ref ty) => { - let type_str = ty.rewrite(context, ty_shape)?; - format!(" -> {}", type_str) - } - FunctionRetTy::Default(..) => String::new(), - }; - - let args = if (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n') - || !context.use_block_indent() - { + let args = if tactic == DefinitiveListTactic::Horizontal || !context.use_block_indent() { format!("({})", list_str) } else { format!( "({}{}{})", - offset.to_string_with_newline(context.config), + list_shape.indent.to_string_with_newline(context.config), list_str, shape.block().indent.to_string_with_newline(context.config), ) @@ -406,13 +405,13 @@ enum ArgumentKind Some(format!( "{}\n{}{}", args, - offset.to_string(context.config), - output.trim_left() + list_shape.indent.to_string(context.config), + output.trim_start() )) } } -fn type_bound_colon(context: &RewriteContext) -> &'static str { +fn type_bound_colon(context: &RewriteContext<'_>) -> &'static str { colon_spaces( context.config.space_before_colon(), context.config.space_after_colon(), @@ -420,7 +419,7 @@ fn type_bound_colon(context: &RewriteContext) -> &'static str { } impl Rewrite for ast::WherePredicate { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { // FIXME: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { @@ -430,7 +429,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { .. }) => { let type_str = bounded_ty.rewrite(context, shape)?; - let colon = type_bound_colon(context).trim_right(); + let colon = type_bound_colon(context).trim_end(); let lhs = if let Some(lifetime_str) = rewrite_lifetime_param(context, shape, bound_generic_params) { @@ -461,10 +460,11 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { } impl Rewrite for ast::GenericArg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { ast::GenericArg::Lifetime(ref lt) => lt.rewrite(context, shape), ast::GenericArg::Type(ref ty) => ty.rewrite(context, shape), + ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) } } } @@ -472,7 +472,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { fn rewrite_bounded_lifetime( lt: &ast::Lifetime, bounds: &[ast::GenericBound], - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let result = lt.rewrite(context, shape)?; @@ -493,22 +493,24 @@ fn rewrite_bounded_lifetime( } impl Rewrite for ast::Lifetime { - fn rewrite(&self, context: &RewriteContext, _: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option { Some(rewrite_ident(context, self.ident).to_owned()) } } impl Rewrite for ast::GenericBound { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { ast::GenericBound::Trait(ref poly_trait_ref, trait_bound_modifier) => { - match trait_bound_modifier { + let snippet = context.snippet(self.span()); + let has_paren = snippet.starts_with('(') && snippet.ends_with(')'); + let rewrite = match trait_bound_modifier { ast::TraitBoundModifier::None => poly_trait_ref.rewrite(context, shape), - ast::TraitBoundModifier::Maybe => { - let rw = poly_trait_ref.rewrite(context, shape.offset_left(1)?)?; - Some(format!("?{}", rw)) - } - } + ast::TraitBoundModifier::Maybe => poly_trait_ref + .rewrite(context, shape.offset_left(1)?) + .map(|s| format!("?{}", s)), + }; + rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape), } @@ -516,30 +518,17 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { } impl Rewrite for ast::GenericBounds { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if self.is_empty() { return Some(String::new()); } - let span = mk_sp(self.get(0)?.span().lo(), self.last()?.span().hi()); - let has_paren = context.snippet(span).starts_with('('); - let bounds_shape = if has_paren { - shape.offset_left(1)?.sub_width(1)? - } else { - shape - }; - join_bounds(context, bounds_shape, self, true).map(|s| { - if has_paren { - format!("({})", s) - } else { - s - } - }) + join_bounds(context, shape, self, true) } } impl Rewrite for ast::GenericParam { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let mut result = String::with_capacity(128); // FIXME: If there are more than one attributes, this will force multiline. match self.attrs.rewrite(context, shape) { @@ -571,7 +560,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { } impl Rewrite for ast::PolyTraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if let Some(lifetime_str) = rewrite_lifetime_param(context, shape, &self.bound_generic_params) { @@ -589,20 +578,26 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { } impl Rewrite for ast::TraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { rewrite_path(context, PathContext::Type, None, &self.path, shape) } } impl Rewrite for ast::Ty { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self.node { ast::TyKind::TraitObject(ref bounds, tobj_syntax) => { // we have to consider 'dyn' keyword is used or not!!! let is_dyn = tobj_syntax == ast::TraitObjectSyntax::Dyn; // 4 is length of 'dyn ' let shape = if is_dyn { shape.offset_left(4)? } else { shape }; - let res = bounds.rewrite(context, shape)?; + let mut res = bounds.rewrite(context, shape)?; + // We may have falsely removed a trailing `+` inside macro call. + if context.inside_macro() && bounds.len() == 1 { + if context.snippet(self.span).ends_with('+') && !res.ends_with('+') { + res.push('+'); + } + } if is_dyn { Some(format!("dyn {}", res)) } else { @@ -664,12 +659,9 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| format!("[{}]", ty_str)) } - ast::TyKind::Tup(ref items) => rewrite_tuple( - context, - &::utils::ptr_vec_to_ref_vec(items), - self.span, - shape, - ), + ast::TyKind::Tup(ref items) => { + rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1) + } ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } @@ -705,7 +697,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { fn rewrite_bare_fn( bare_fn: &ast::BareFnTy, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { debug!("rewrite_bare_fn {:#?}", shape); @@ -722,7 +714,7 @@ fn rewrite_bare_fn( result.push_str("> "); } - result.push_str(::utils::format_unsafety(bare_fn.unsafety)); + result.push_str(crate::utils::format_unsafety(bare_fn.unsafety)); result.push_str(&format_abi( bare_fn.abi, @@ -769,11 +761,13 @@ fn is_generic_bounds_in_order(generic_bounds: &[ast::GenericBound]) -> bool { } fn join_bounds( - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, items: &[ast::GenericBound], need_indent: bool, ) -> Option { + debug_assert!(!items.is_empty()); + // Try to join types in a single line let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", @@ -823,7 +817,7 @@ fn join_bounds( Some(result) } -pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { +pub fn can_be_overflowed_type(context: &RewriteContext<'_>, ty: &ast::Ty, len: usize) -> bool { match ty.node { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { @@ -835,7 +829,7 @@ pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize /// Returns `None` if there is no `LifetimeDef` in the given generic parameters. fn rewrite_lifetime_param( - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, generic_params: &[ast::GenericParam], ) -> Option { @@ -844,7 +838,8 @@ fn rewrite_lifetime_param( .filter(|p| match p.kind { ast::GenericParamKind::Lifetime => true, _ => false, - }).map(|lt| lt.rewrite(context, shape)) + }) + .map(|lt| lt.rewrite(context, shape)) .collect::>>()? .join(", "); if result.is_empty() {