diff --git a/Cargo.lock b/Cargo.lock index 8385f1a18e5cd..f861e1934649c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -265,6 +265,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" +[[package]] +name = "camino" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" +dependencies = [ + "serde", +] + [[package]] name = "cargo" version = "0.58.0" @@ -272,7 +281,7 @@ dependencies = [ "anyhow", "atty", "bytesize", - "cargo-platform", + "cargo-platform 0.1.2", "cargo-test-macro", "cargo-test-support", "cargo-util", @@ -374,6 +383,15 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + [[package]] name = "cargo-test-macro" version = "0.1.0" @@ -421,23 +439,24 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.8.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" +checksum = "d5a5f7b42f606b7f23674f6f4d877628350682bc40687d3fae65679a58d55345" dependencies = [ - "semver 0.9.0", + "semver 0.11.0", "serde", - "serde_derive", "serde_json", ] [[package]] name = "cargo_metadata" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5a5f7b42f606b7f23674f6f4d877628350682bc40687d3fae65679a58d55345" +checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a" dependencies = [ - "semver 0.11.0", + "camino", + "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 1.0.3", "serde", "serde_json", ] @@ -1069,9 +1088,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ "atty", "humantime 1.3.0", @@ -1082,12 +1101,12 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.7.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "atty", - "humantime 1.3.0", + "humantime 2.0.1", "log", "regex", "termcolor", @@ -1688,15 +1707,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" -[[package]] -name = "itertools" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.9.0" @@ -4663,19 +4673,19 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.37" +version = "1.4.38" dependencies = [ "annotate-snippets", "anyhow", "bytecount", - "cargo_metadata 0.8.2", + "cargo_metadata 0.14.0", "derive-new", "diff", "dirs", - "env_logger 0.6.2", + "env_logger 0.8.4", "getopts", "ignore", - "itertools 0.8.2", + "itertools 0.9.0", "lazy_static", "log", "regex", @@ -4758,23 +4768,13 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser 0.7.0", - "serde", -] - [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser 0.10.2", + "semver-parser", "serde", ] @@ -4787,12 +4787,6 @@ dependencies = [ "serde", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "semver-parser" version = "0.10.2" diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index df4cc295fac5f..80551518d3c5d 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -1,6 +1,5 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; @@ -44,8 +43,8 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } else { false } - } else if let Some(fn_like) = FnLikeNode::from_node(node) { - if fn_like.constness() == hir::Constness::Const { + } else if let Some(fn_kind) = node.fn_kind() { + if fn_kind.constness() == hir::Constness::Const { return true; } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b5c1e31c258ef..6f25715fbecc4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ use crate::def::{CtorKind, DefKind, Res}; use crate::def_id::DefId; crate use crate::hir_id::{HirId, ItemLocalId}; +use crate::intravisit::FnKind; use crate::LangItem; use rustc_ast::util::parser::ExprPrecedence; @@ -3258,6 +3259,32 @@ impl<'hir> Node<'hir> { _ => None, } } + + pub fn fn_kind(self) -> Option> { + match self { + Node::Item(i) => match i.kind { + ItemKind::Fn(ref sig, ref generics, _) => { + Some(FnKind::ItemFn(i.ident, generics, sig.header, &i.vis)) + } + _ => None, + }, + Node::TraitItem(ti) => match ti.kind { + TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => { + Some(FnKind::Method(ti.ident, sig, None)) + } + _ => None, + }, + Node::ImplItem(ii) => match ii.kind { + ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig, Some(&ii.vis))), + _ => None, + }, + Node::Expr(e) => match e.kind { + ExprKind::Closure(..) => Some(FnKind::Closure), + _ => None, + }, + _ => None, + } + } } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3e58af1f167aa..cff543760f42a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -117,6 +117,14 @@ impl<'a> FnKind<'a> { FnKind::Closure => None, } } + + pub fn constness(self) -> Constness { + self.header().map_or(Constness::NotConst, |header| header.constness) + } + + pub fn asyncness(self) -> IsAsync { + self.header().map_or(IsAsync::NotAsync, |header| header.asyncness) + } } /// An abstract representation of the HIR `rustc_middle::hir::map::Map`. diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 8dcdd4b149ea6..90bc5b3b2fed1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -143,9 +143,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // similar to the asyncness fn in rustc_ty_utils::ty let hir_id = self.tcx().hir().local_def_id_to_hir_id(local_def_id); let node = self.tcx().hir().get(hir_id); - let fn_like = rustc_middle::hir::map::blocks::FnLikeNode::from_node(node)?; - - Some(fn_like.asyncness()) + let fn_kind = node.fn_kind()?; + Some(fn_kind.asyncness()) } // Here, we check for the case where the anonymous region diff --git a/compiler/rustc_middle/src/hir/map/blocks.rs b/compiler/rustc_middle/src/hir/map/blocks.rs deleted file mode 100644 index 8efec8ef5674d..0000000000000 --- a/compiler/rustc_middle/src/hir/map/blocks.rs +++ /dev/null @@ -1,239 +0,0 @@ -//! This module provides a simplified abstraction for working with -//! code blocks identified by their integer `NodeId`. In particular, -//! it captures a common set of attributes that all "function-like -//! things" (represented by `FnLike` instances) share. For example, -//! all `FnLike` instances have a type signature (be it explicit or -//! inferred). And all `FnLike` instances have a body, i.e., the code -//! that is run when the function-like thing it represents is invoked. -//! -//! With the above abstraction in place, one can treat the program -//! text as a collection of blocks of code (and most such blocks are -//! nested within a uniquely determined `FnLike`), and users can ask -//! for the `Code` associated with a particular NodeId. - -use crate::hir::map::Map; -use rustc_hir as hir; -use rustc_hir::intravisit::FnKind; -use rustc_hir::{Expr, FnDecl, Node}; -use rustc_span::symbol::Ident; -use rustc_span::Span; - -/// An FnLikeNode is a Node that is like a fn, in that it has a decl -/// and a body (as well as a NodeId, a span, etc). -/// -/// More specifically, it is one of either: -/// -/// - A function item, -/// - A closure expr (i.e., an ExprKind::Closure), or -/// - The default implementation for a trait method. -/// -/// To construct one, use the `Code::from_node` function. -#[derive(Copy, Clone, Debug)] -pub struct FnLikeNode<'a> { - node: Node<'a>, -} - -/// MaybeFnLike wraps a method that indicates if an object -/// corresponds to some FnLikeNode. -trait MaybeFnLike { - fn is_fn_like(&self) -> bool; -} - -impl MaybeFnLike for hir::Item<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::ItemKind::Fn(..)) - } -} - -impl MaybeFnLike for hir::ImplItem<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::ImplItemKind::Fn(..)) - } -} - -impl MaybeFnLike for hir::TraitItem<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_))) - } -} - -impl MaybeFnLike for hir::Expr<'_> { - fn is_fn_like(&self) -> bool { - matches!(self.kind, hir::ExprKind::Closure(..)) - } -} - -/// Carries either an FnLikeNode or an Expr, as these are the two -/// constructs that correspond to "code" (as in, something from which -/// we can construct a control-flow graph). -#[derive(Copy, Clone)] -pub enum Code<'a> { - FnLike(FnLikeNode<'a>), - Expr(&'a Expr<'a>), -} - -impl<'a> Code<'a> { - pub fn id(&self) -> hir::HirId { - match *self { - Code::FnLike(node) => node.id(), - Code::Expr(block) => block.hir_id, - } - } - - /// Attempts to construct a Code from presumed FnLike or Expr node input. - pub fn from_node(map: &Map<'a>, id: hir::HirId) -> Option> { - match map.get(id) { - Node::Block(_) => { - // Use the parent, hopefully an expression node. - Code::from_node(map, map.get_parent_node(id)) - } - Node::Expr(expr) => Some(Code::Expr(expr)), - node => FnLikeNode::from_node(node).map(Code::FnLike), - } - } -} - -/// These are all the components one can extract from a fn item for -/// use when implementing FnLikeNode operations. -struct ItemFnParts<'a> { - ident: Ident, - decl: &'a hir::FnDecl<'a>, - header: hir::FnHeader, - vis: &'a hir::Visibility<'a>, - generics: &'a hir::Generics<'a>, - body: hir::BodyId, - id: hir::HirId, - span: Span, -} - -/// These are all the components one can extract from a closure expr -/// for use when implementing FnLikeNode operations. -struct ClosureParts<'a> { - decl: &'a FnDecl<'a>, - body: hir::BodyId, - id: hir::HirId, - span: Span, -} - -impl<'a> ClosureParts<'a> { - fn new(d: &'a FnDecl<'a>, b: hir::BodyId, id: hir::HirId, s: Span) -> Self { - ClosureParts { decl: d, body: b, id, span: s } - } -} - -impl<'a> FnLikeNode<'a> { - /// Attempts to construct a FnLikeNode from presumed FnLike node input. - pub fn from_node(node: Node<'_>) -> Option> { - let fn_like = match node { - Node::Item(item) => item.is_fn_like(), - Node::TraitItem(tm) => tm.is_fn_like(), - Node::ImplItem(it) => it.is_fn_like(), - Node::Expr(e) => e.is_fn_like(), - _ => false, - }; - fn_like.then_some(FnLikeNode { node }) - } - - pub fn body(self) -> hir::BodyId { - self.handle( - |i: ItemFnParts<'a>| i.body, - |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _| body, - |c: ClosureParts<'a>| c.body, - ) - } - - pub fn decl(self) -> &'a FnDecl<'a> { - self.handle( - |i: ItemFnParts<'a>| &*i.decl, - |_, _, sig: &'a hir::FnSig<'a>, _, _, _| &sig.decl, - |c: ClosureParts<'a>| c.decl, - ) - } - - pub fn span(self) -> Span { - self.handle( - |i: ItemFnParts<'_>| i.span, - |_, _, _: &'a hir::FnSig<'a>, _, _, span| span, - |c: ClosureParts<'_>| c.span, - ) - } - - pub fn id(self) -> hir::HirId { - self.handle( - |i: ItemFnParts<'_>| i.id, - |id, _, _: &'a hir::FnSig<'a>, _, _, _| id, - |c: ClosureParts<'_>| c.id, - ) - } - - pub fn constness(self) -> hir::Constness { - self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness) - } - - pub fn asyncness(self) -> hir::IsAsync { - self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness) - } - - pub fn unsafety(self) -> hir::Unsafety { - self.kind().header().map_or(hir::Unsafety::Normal, |header| header.unsafety) - } - - pub fn kind(self) -> FnKind<'a> { - let item = |p: ItemFnParts<'a>| -> FnKind<'a> { - FnKind::ItemFn(p.ident, p.generics, p.header, p.vis) - }; - let closure = |_: ClosureParts<'a>| FnKind::Closure; - let method = - |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _| FnKind::Method(ident, sig, vis); - self.handle(item, method, closure) - } - - fn handle(self, item_fn: I, method: M, closure: C) -> A - where - I: FnOnce(ItemFnParts<'a>) -> A, - M: FnOnce( - hir::HirId, - Ident, - &'a hir::FnSig<'a>, - Option<&'a hir::Visibility<'a>>, - hir::BodyId, - Span, - ) -> A, - C: FnOnce(ClosureParts<'a>) -> A, - { - match self.node { - Node::Item(i) => match i.kind { - hir::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts { - id: i.hir_id(), - ident: i.ident, - decl: &sig.decl, - body: block, - vis: &i.vis, - span: i.span, - header: sig.header, - generics, - }), - _ => bug!("item FnLikeNode that is not fn-like"), - }, - Node::TraitItem(ti) => match ti.kind { - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - method(ti.hir_id(), ti.ident, sig, None, body, ti.span) - } - _ => bug!("trait method FnLikeNode that is not fn-like"), - }, - Node::ImplItem(ii) => match ii.kind { - hir::ImplItemKind::Fn(ref sig, body) => { - method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span) - } - _ => bug!("impl method FnLikeNode that is not fn-like"), - }, - Node::Expr(e) => match e.kind { - hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => { - closure(ClosureParts::new(&decl, block, e.hir_id, e.span)) - } - _ => bug!("expr FnLikeNode that is not fn-like"), - }, - _ => bug!("other FnLikeNode that is not fn-like"), - } - } -} diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 38bc01b9b53d8..fad7e875fa1c0 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -20,8 +20,6 @@ use rustc_span::Span; use rustc_target::spec::abi::Abi; use std::collections::VecDeque; -pub mod blocks; - fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { match node { Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. }) diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index ef8bd20d51098..e4c2d2dce67c7 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -2,7 +2,6 @@ use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; use rustc_hir::intravisit::FnKind; -use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::mir::{BasicBlock, Body, Operand, TerminatorKind}; use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; use rustc_middle::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt}; @@ -14,8 +13,8 @@ crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id().expect_local(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) { - if let FnKind::Closure = fn_like_node.kind() { + if let Some(fn_kind) = tcx.hir().get(hir_id).fn_kind() { + if let FnKind::Closure = fn_kind { // closures can't recur, so they don't matter. return; } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 17790ec91c8a3..63c637af5c21a 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -68,11 +68,10 @@ impl<'tcx> MirPass<'tcx> for ConstProp { return; } - use rustc_middle::hir::map::blocks::FnLikeNode; let def_id = body.source.def_id().expect_local(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some(); + let is_fn_like = tcx.hir().get(hir_id).fn_kind().is_some(); let is_assoc_const = tcx.def_kind(def_id.to_def_id()) == DefKind::AssocConst; // Only run const prop on functions, methods, closures and associated constants diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index e980d3d884f56..4ac93f7161923 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -19,7 +19,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_index::vec::IndexVec; use rustc_middle::hir; -use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::*; use rustc_middle::mir::dump_enabled; @@ -64,7 +63,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { } let hir_id = tcx.hir().local_def_id_to_hir_id(mir_source.def_id().expect_local()); - let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some(); + let is_fn_like = tcx.hir().get(hir_id).fn_kind().is_some(); // Only instrument functions, methods, and closures (not constants since they are evaluated // at compile time by Miri). @@ -74,7 +73,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { // be tricky if const expressions have no corresponding statements in the enclosing MIR. // Closures are carved out by their initial `Assign` statement.) if !is_fn_like { - trace!("InstrumentCoverage skipped for {:?} (not an FnLikeNode)", mir_source.def_id()); + trace!("InstrumentCoverage skipped for {:?} (not an fn-like)", mir_source.def_id()); return; } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 60135ef2d8571..ab1fe6fe077a7 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -429,8 +429,7 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( } let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - use rustc_middle::hir::map::blocks::FnLikeNode; - let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some(); + let is_fn_like = tcx.hir().get(hir_id).fn_kind().is_some(); if is_fn_like { let did = def.did.to_def_id(); let def = ty::WithOptConstParam::unknown(did); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ae3a9c71c5968..4d4e9432e876d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -23,7 +23,7 @@ use rustc_middle::span_bug; use rustc_middle::thir::abstract_const::Node as ACNode; use rustc_middle::ty::fold::TypeVisitor; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::hygiene::Transparency; @@ -153,11 +153,8 @@ where tcx: TyCtxt<'tcx>, ct: AbstractConst<'tcx>, ) -> ControlFlow { - const_evaluatable::walk_abstract_const(tcx, ct, |node| match node.root() { - ACNode::Leaf(leaf) => { - let leaf = leaf.subst(tcx, ct.substs); - self.visit_const(leaf) - } + const_evaluatable::walk_abstract_const(tcx, ct, |node| match node.root(tcx) { + ACNode::Leaf(leaf) => self.visit_const(leaf), ACNode::Cast(_, _, ty) => self.visit_ty(ty), ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { ControlFlow::CONTINUE diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 1193d10d6a7d7..8edb7069fc45f 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -80,9 +80,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>( Concrete, } let mut failure_kind = FailureKind::Concrete; - walk_abstract_const::(tcx, ct, |node| match node.root() { + walk_abstract_const::(tcx, ct, |node| match node.root(tcx) { Node::Leaf(leaf) => { - let leaf = leaf.subst(tcx, ct.substs); if leaf.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; } else if leaf.definitely_has_param_types_or_consts(tcx) { @@ -92,7 +91,6 @@ pub fn is_const_evaluatable<'cx, 'tcx>( ControlFlow::CONTINUE } Node::Cast(_, _, ty) => { - let ty = ty.subst(tcx, ct.substs); if ty.has_infer_types_or_consts() { failure_kind = FailureKind::MentionsInfer; } else if ty.definitely_has_param_types_or_consts(tcx) { @@ -187,8 +185,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>( pub struct AbstractConst<'tcx> { // FIXME: Consider adding something like `IndexSlice` // and use this here. - pub inner: &'tcx [Node<'tcx>], - pub substs: SubstsRef<'tcx>, + inner: &'tcx [Node<'tcx>], + substs: SubstsRef<'tcx>, } impl<'tcx> AbstractConst<'tcx> { @@ -218,8 +216,14 @@ impl<'tcx> AbstractConst<'tcx> { } #[inline] - pub fn root(self) -> Node<'tcx> { - self.inner.last().copied().unwrap() + pub fn root(self, tcx: TyCtxt<'tcx>) -> Node<'tcx> { + let node = self.inner.last().copied().unwrap(); + match node { + Node::Leaf(leaf) => Node::Leaf(leaf.subst(tcx, self.substs)), + Node::Cast(kind, operand, ty) => Node::Cast(kind, operand, ty.subst(tcx, self.substs)), + // Don't perform substitution on the following as they can't directly contain generic params + Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => node, + } } } @@ -542,7 +546,7 @@ where f: &mut dyn FnMut(AbstractConst<'tcx>) -> ControlFlow, ) -> ControlFlow { f(ct)?; - let root = ct.root(); + let root = ct.root(tcx); match root { Node::Leaf(_) => ControlFlow::CONTINUE, Node::Binop(_, l, r) => { @@ -570,16 +574,14 @@ pub(super) fn try_unify<'tcx>( // We substitute generics repeatedly to allow AbstractConsts to unify where a // ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g. // Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])] - while let Node::Leaf(a_ct) = a.root() { - let a_ct = a_ct.subst(tcx, a.substs); + while let Node::Leaf(a_ct) = a.root(tcx) { match AbstractConst::from_const(tcx, a_ct) { Ok(Some(a_act)) => a = a_act, Ok(None) => break, Err(_) => return true, } } - while let Node::Leaf(b_ct) = b.root() { - let b_ct = b_ct.subst(tcx, b.substs); + while let Node::Leaf(b_ct) = b.root(tcx) { match AbstractConst::from_const(tcx, b_ct) { Ok(Some(b_act)) => b = b_act, Ok(None) => break, @@ -587,10 +589,8 @@ pub(super) fn try_unify<'tcx>( } } - match (a.root(), b.root()) { + match (a.root(tcx), b.root(tcx)) { (Node::Leaf(a_ct), Node::Leaf(b_ct)) => { - let a_ct = a_ct.subst(tcx, a.substs); - let b_ct = b_ct.subst(tcx, b.substs); if a_ct.ty != b_ct.ty { return false; } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index ad9fd0ca62cfa..afc546540d2e2 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -837,14 +837,13 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // constants which are not considered const evaluatable. use rustc_middle::thir::abstract_const::Node; if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) { - const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() { - Node::Leaf(leaf) => { - let leaf = leaf.subst(self.tcx, ct.substs); - self.visit_const(leaf) - } - Node::Cast(_, _, ty) => self.visit_ty(ty), - Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { - ControlFlow::CONTINUE + const_evaluatable::walk_abstract_const(self.tcx, ct, |node| { + match node.root(self.tcx) { + Node::Leaf(leaf) => self.visit_const(leaf), + Node::Cast(_, _, ty) => self.visit_ty(ty), + Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => { + ControlFlow::CONTINUE + } } }) } else { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 3d3b274370091..bc77c94809eb5 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,7 +1,6 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::hir::map as hir_map; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{ self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, @@ -478,11 +477,11 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { let node = tcx.hir().get(hir_id); - let fn_like = hir_map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| { + let fn_kind = node.fn_kind().unwrap_or_else(|| { bug!("asyncness: expected fn-like node but got `{:?}`", def_id); }); - fn_like.asyncness() + fn_kind.asyncness() } /// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead. diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index caad28ff2b21f..9c7b0b2cacb06 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -883,8 +883,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.get_diagnostic_item(sym::unwind_safe_trait), self.tcx.get_diagnostic_item(sym::ref_unwind_safe_trait), ]; - let auto_traits = - vec!["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"]; + const AUTO_TRAITS: [&str; 6] = + ["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"]; let root_var_min_capture_list = min_captures.and_then(|m| m.get(&var_hir_id))?; @@ -957,7 +957,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // by the root variable but not by the capture for (idx, _) in obligations_should_hold.iter().enumerate() { if !obligations_holds_for_capture[idx] && obligations_should_hold[idx] { - capture_problems.insert(auto_traits[idx]); + capture_problems.insert(AUTO_TRAITS[idx]); } } @@ -1074,7 +1074,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, ) -> (Vec, String) { let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) else { - return (Vec::new(), format!("")); + return (Vec::new(), String::new()); }; let mut need_migrations = Vec::new(); diff --git a/config.toml.example b/config.toml.example index 61e57eee782b8..2128fdea2eb46 100644 --- a/config.toml.example +++ b/config.toml.example @@ -68,6 +68,12 @@ changelog-seen = 2 # Indicates whether the LLVM assertions are enabled or not #assertions = false +# Indicates whether the LLVM testsuite is enabled in the build or not. Does +# not execute the tests as part of the build as part of x.py build et al, +# just makes it possible to do `ninja check-llvm` in the staged LLVM build +# directory when doing LLVM development as part of Rust development. +#tests = false + # Indicates whether the LLVM plugin is enabled or not #plugins = false diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c890ff4ac5e2b..de607c8fdab31 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -543,9 +543,9 @@ impl VecDeque { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque { + assert!(capacity < 1_usize << usize::BITS - 1, "capacity overflow"); // +1 since the ringbuffer always leaves one space empty let cap = cmp::max(capacity + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); - assert!(cap > capacity, "capacity overflow"); VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity_in(cap, alloc) } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 20a16869cb3f8..d52c78eedf3fa 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1305,10 +1305,11 @@ impl Vec { // We replace self[index] with the last element. Note that if the // bounds check above succeeds there must be a last element (which // can be self[index] itself). - let last = ptr::read(self.as_ptr().add(len - 1)); - let hole = self.as_mut_ptr().add(index); + let value = ptr::read(self.as_ptr().add(index)); + let base_ptr = self.as_mut_ptr(); + ptr::copy(base_ptr.add(len - 1), base_ptr.add(index), 1); self.set_len(len - 1); - ptr::replace(hole, last) + value } } diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 75ef873abc965..2b6ea90bf0430 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -390,7 +390,8 @@ use crate::num::NonZeroUsize; macro_rules! nzint_impl_from { ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { #[$attr] - impl From<$Small> for $Large { + #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] + impl const From<$Small> for $Large { // Rustdocs on the impl block show a "[+] show undocumented items" toggle. // Rustdocs on functions do not. #[doc = $doc] @@ -398,7 +399,7 @@ macro_rules! nzint_impl_from { fn from(small: $Small) -> Self { // SAFETY: input type guarantees the value is non-zero unsafe { - Self::new_unchecked(small.get().into()) + Self::new_unchecked(From::from(small.get())) } } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 13b80c05dbb30..58a170401e7c1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -115,6 +115,7 @@ #![feature(const_likely)] #![feature(const_maybe_uninit_as_ptr)] #![feature(const_maybe_uninit_assume_init)] +#![feature(const_num_from_num)] #![feature(const_option)] #![feature(const_pin)] #![feature(const_replace)] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d28474c29232c..9b1a4de5d8037 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -82,7 +82,7 @@ macro_rules! nonzero_integers { } #[stable(feature = "from_nonzero", since = "1.31.0")] - #[rustc_const_unstable(feature = "const_convert", issue = "88674")] + #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] impl const From<$Ty> for $Int { #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] #[inline] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 0915dcffe6ef0..1dd3b2d8e3c8d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1365,7 +1365,7 @@ macro_rules! atomic_int { } #[$stable_from] - #[rustc_const_unstable(feature = "const_convert", issue = "88674")] + #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] impl const From<$int_type> for $atomic_type { #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")] #[inline] diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs index 4817d86ca6eb0..a0ca919a851c3 100644 --- a/library/core/tests/nonzero.rs +++ b/library/core/tests/nonzero.rs @@ -204,9 +204,9 @@ fn nonzero_const() { // test that the methods of `NonZeroX>` are usable in a const context // Note: only tests NonZero8 - const NONZERO: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) }; + const NONZERO_U8: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(5) }; - const GET: u8 = NONZERO.get(); + const GET: u8 = NONZERO_U8.get(); assert_eq!(GET, 5); const ZERO: Option = NonZeroU8::new(0); @@ -215,8 +215,11 @@ fn nonzero_const() { const ONE: Option = NonZeroU8::new(1); assert!(ONE.is_some()); - const FROM_NONZERO: u8 = u8::from(NONZERO); - assert_eq!(FROM_NONZERO, 5); + const FROM_NONZERO_U8: u8 = u8::from(NONZERO_U8); + assert_eq!(FROM_NONZERO_U8, 5); + + const NONZERO_CONVERT: NonZeroU32 = NonZeroU32::from(NONZERO_U8); + assert_eq!(NONZERO_CONVERT.get(), 5); } #[test] diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 6827d3a8d2448..cb09717bde577 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -251,13 +251,12 @@ pub struct FromBytesWithNulError { /// # Examples /// /// ``` -/// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::{CString, FromVecWithNulError}; /// /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err(); /// ``` #[derive(Clone, PartialEq, Eq, Debug)] -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub struct FromVecWithNulError { error_kind: FromBytesWithNulErrorKind, bytes: Vec, @@ -278,7 +277,7 @@ impl FromBytesWithNulError { } } -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl FromVecWithNulError { /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`]. /// @@ -287,7 +286,6 @@ impl FromVecWithNulError { /// Basic usage: /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// /// // Some invalid bytes in a vector @@ -298,6 +296,7 @@ impl FromVecWithNulError { /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); /// ``` #[must_use] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } @@ -313,7 +312,6 @@ impl FromVecWithNulError { /// Basic usage: /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// /// // Some invalid bytes in a vector @@ -324,6 +322,7 @@ impl FromVecWithNulError { /// assert_eq!(bytes, value.unwrap_err().into_bytes()); /// ``` #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub fn into_bytes(self) -> Vec { self.bytes } @@ -704,7 +703,6 @@ impl CString { /// # Example /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) }, @@ -712,7 +710,7 @@ impl CString { /// ); /// ``` #[must_use] - #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { Self { inner: v.into_boxed_slice() } } @@ -733,7 +731,6 @@ impl CString { /// when called without the ending nul byte. /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::CString; /// assert_eq!( /// CString::from_vec_with_nul(b"abc\0".to_vec()) @@ -745,14 +742,13 @@ impl CString { /// An incorrectly formatted [`Vec`] will produce an error. /// /// ``` - /// #![feature(cstring_from_vec_with_nul)] /// use std::ffi::{CString, FromVecWithNulError}; /// // Interior nul byte /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err(); /// // No nul byte /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); /// ``` - #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] + #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub fn from_vec_with_nul(v: Vec) -> Result { let nul_pos = memchr::memchr(0, &v); match nul_pos { @@ -1084,10 +1080,10 @@ impl fmt::Display for FromBytesWithNulError { } } -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl Error for FromVecWithNulError {} -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] impl fmt::Display for FromVecWithNulError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.error_kind { diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 82a76aa73c583..7f3bb836754ed 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -145,7 +145,7 @@ #[stable(feature = "cstr_from_bytes", since = "1.10.0")] pub use self::c_str::FromBytesWithNulError; -#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub use self::c_str::FromVecWithNulError; #[stable(feature = "rust1", since = "1.0.0")] pub use self::c_str::{CStr, CString, IntoStringError, NulError}; diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index e5e9fedb61eaf..c080f783cbb36 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -59,7 +59,8 @@ pub enum IpAddr { /// /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal /// notation, divided by `.` (this is called "dot-decimal notation"). -/// Notably, octal numbers and hexadecimal numbers are not allowed per [IETF RFC 6943]. +/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which +/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943]. /// /// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1 /// [`FromStr`]: crate::str::FromStr @@ -72,6 +73,9 @@ pub enum IpAddr { /// let localhost = Ipv4Addr::new(127, 0, 0, 1); /// assert_eq!("127.0.0.1".parse(), Ok(localhost)); /// assert_eq!(localhost.is_loopback(), true); +/// assert!("012.004.002.000".parse::().is_err()); // all octets are in octal +/// assert!("0000000.0.0.0".parse::().is_err()); // first octet is a zero in octal +/// assert!("0xcb.0x0.0x71.0x00".parse::().is_err()); // all octets are in hex /// ``` #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index babc854cd1d33..17581f330266d 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -20,6 +20,14 @@ fn test_from_str_ipv4() { // no number between dots let none: Option = "255.0..1".parse().ok(); assert_eq!(None, none); + // octal + let none: Option = "255.0.0.01".parse().ok(); + assert_eq!(None, none); + // octal zero + let none: Option = "255.0.0.00".parse().ok(); + assert_eq!(None, none); + let none: Option = "255.0.00.0".parse().ok(); + assert_eq!(None, none); } #[test] diff --git a/library/std/src/net/parser.rs b/library/std/src/net/parser.rs index 88a8cb76befbf..4e16a55edece2 100644 --- a/library/std/src/net/parser.rs +++ b/library/std/src/net/parser.rs @@ -111,10 +111,12 @@ impl<'a> Parser<'a> { &mut self, radix: u32, max_digits: Option, + allow_zero_prefix: bool, ) -> Option { self.read_atomically(move |p| { let mut result = T::ZERO; let mut digit_count = 0; + let has_leading_zero = p.peek_char() == Some('0'); while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { result = result.checked_mul(radix)?; @@ -127,7 +129,13 @@ impl<'a> Parser<'a> { } } - if digit_count == 0 { None } else { Some(result) } + if digit_count == 0 { + None + } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { + None + } else { + Some(result) + } }) } @@ -140,10 +148,7 @@ impl<'a> Parser<'a> { *slot = p.read_separator('.', i, |p| { // Disallow octal number in IP string. // https://tools.ietf.org/html/rfc6943#section-3.1.1 - match (p.peek_char(), p.read_number(10, None)) { - (Some('0'), Some(number)) if number != 0 => None, - (_, number) => number, - } + p.read_number(10, Some(3), false) })?; } @@ -175,7 +180,7 @@ impl<'a> Parser<'a> { } } - let group = p.read_separator(':', i, |p| p.read_number(16, Some(4))); + let group = p.read_separator(':', i, |p| p.read_number(16, Some(4), true)); match group { Some(g) => *slot = g, @@ -227,7 +232,7 @@ impl<'a> Parser<'a> { fn read_port(&mut self) -> Option { self.read_atomically(|p| { p.read_given_char(':')?; - p.read_number(10, None) + p.read_number(10, None, true) }) } @@ -235,7 +240,7 @@ impl<'a> Parser<'a> { fn read_scope_id(&mut self) -> Option { self.read_atomically(|p| { p.read_given_char('%')?; - p.read_number(10, None) + p.read_number(10, None, true) }) } @@ -281,7 +286,12 @@ impl FromStr for IpAddr { impl FromStr for Ipv4Addr { type Err = AddrParseError; fn from_str(s: &str) -> Result { - Parser::new(s).parse_with(|p| p.read_ipv4_addr()) + // don't try to parse if too long + if s.len() > 15 { + Err(AddrParseError(())) + } else { + Parser::new(s).parse_with(|p| p.read_ipv4_addr()) + } } } diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index 133c3e46cd8a6..11836b7b694b3 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -130,7 +130,7 @@ impl Barrier { if lock.count < self.num_threads { // We need a while loop to guard against spurious wakeups. // https://en.wikipedia.org/wiki/Spurious_wakeup - while local_gen == lock.generation_id && lock.count < self.num_threads { + while local_gen == lock.generation_id { lock = self.cvar.wait(lock).unwrap(); } BarrierWaitResult(false) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 9a48b768cb37d..8d03aade3413a 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -90,6 +90,7 @@ pub struct Config { // llvm codegen options pub llvm_skip_rebuild: bool, pub llvm_assertions: bool, + pub llvm_tests: bool, pub llvm_plugins: bool, pub llvm_optimize: bool, pub llvm_thin_lto: bool, @@ -422,6 +423,7 @@ struct Llvm { thin_lto: Option, release_debuginfo: Option, assertions: Option, + tests: Option, plugins: Option, ccache: Option, version_check: Option, @@ -715,6 +717,7 @@ impl Config { // Store off these values as options because if they're not provided // we'll infer default values for them later let mut llvm_assertions = None; + let mut llvm_tests = None; let mut llvm_plugins = None; let mut debug = None; let mut debug_assertions = None; @@ -740,6 +743,7 @@ impl Config { } set(&mut config.ninja_in_file, llvm.ninja); llvm_assertions = llvm.assertions; + llvm_tests = llvm.tests; llvm_plugins = llvm.plugins; llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild); set(&mut config.llvm_optimize, llvm.optimize); @@ -991,6 +995,7 @@ impl Config { config.llvm_skip_rebuild = llvm_skip_rebuild.unwrap_or(false); config.llvm_assertions = llvm_assertions.unwrap_or(false); + config.llvm_tests = llvm_tests.unwrap_or(false); config.llvm_plugins = llvm_plugins.unwrap_or(false); config.rust_optimize = optimize.unwrap_or(true); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 27c9bb2504f6d..6bfaeffa80705 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -170,6 +170,7 @@ impl Step for Llvm { let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" }; let plugins = if builder.config.llvm_plugins { "ON" } else { "OFF" }; + let enable_tests = if builder.config.llvm_tests { "ON" } else { "OFF" }; cfg.out_dir(&out_dir) .profile(profile) @@ -180,7 +181,7 @@ impl Step for Llvm { .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") .define("LLVM_INCLUDE_BENCHMARKS", "OFF") - .define("LLVM_INCLUDE_TESTS", "OFF") + .define("LLVM_INCLUDE_TESTS", enable_tests) .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") .define("LLVM_ENABLE_BINDINGS", "OFF") diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index adc970c66d688..ba4e1ca31148c 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.4.3 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.4.5 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/test/incremental/auxiliary/rustc-rust-log-aux.rs b/src/test/incremental/auxiliary/rustc-rust-log-aux.rs new file mode 100644 index 0000000000000..a361373dc1955 --- /dev/null +++ b/src/test/incremental/auxiliary/rustc-rust-log-aux.rs @@ -0,0 +1,8 @@ +// rustc-env:RUSTC_LOG=debug +#[cfg(rpass1)] +pub fn foo() {} + +#[cfg(rpass2)] +pub fn foo() { + println!(); +} diff --git a/src/test/incremental/rustc-rust-log.rs b/src/test/incremental/rustc-rust-log.rs new file mode 100644 index 0000000000000..566f0d96d9732 --- /dev/null +++ b/src/test/incremental/rustc-rust-log.rs @@ -0,0 +1,16 @@ +// revisions: rpass1 rpass2 +// This test is just checking that we won't ICE if logging is turned +// on; don't bother trying to compare that (copious) output. +// +// dont-check-compiler-stdout +// dont-check-compiler-stderr +// aux-build: rustc-rust-log-aux.rs +// rustc-env:RUSTC_LOG=debug + +#[cfg(rpass1)] +fn main() {} + +#[cfg(rpass2)] +fn main() { + println!(); +} diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml new file mode 100644 index 0000000000000..7e6607b55ea8b --- /dev/null +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -0,0 +1,22 @@ +// Checks that the setting "line numbers" is working as expected. +goto: file://|DOC_PATH|/test_docs/fn.foo.html + +// We check that without this setting, there is no line number displayed. +assert-false: "pre.line-number" + +// We now set the setting to show the line numbers on code examples. +local-storage: {"rustdoc-line-numbers": "true" } +// We reload to make the line numbers appear. +reload: + +// We wait for them to be added into the DOM by the JS... +wait-for: "pre.line-number" +// If the test didn't fail, it means that it was found! +// Let's now check some CSS properties... +assert-css: ("pre.line-number", { + "margin": "0px", + "padding": "13px 8px", + "text-align": "right" +}) +// The first code block has two lines so let's check its `
` elements lists both of them.
+assert-text: ("pre.line-number", "1\n2")
diff --git a/src/test/rustdoc-gui/sidebar-macro-reexport.goml b/src/test/rustdoc-gui/sidebar-macro-reexport.goml
new file mode 100644
index 0000000000000..a3a62fe54465e
--- /dev/null
+++ b/src/test/rustdoc-gui/sidebar-macro-reexport.goml
@@ -0,0 +1,5 @@
+// This test ensures that the reexport of a macro doesn't make the original macro
+// displayed twice in the sidebar.
+goto: file://|DOC_PATH|/test_docs/macro.repro.html
+wait-for: ".sidebar-elems .macro .macro"
+assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[text()='repro']", 1)
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index c8ebb8c56f535..62dc76a40bcf5 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -7,12 +7,13 @@ assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
 assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
 assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Macros")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Structs")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Enums")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Traits")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Functions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Type Definitions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(8)", "Keywords")
 assert-text: ("#structs + .item-table .item-left > a", "Foo")
 click: "#structs + .item-table .item-left > a"
 
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 2a147e64d8bf2..652308a71cb85 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -12,6 +12,7 @@ use std::fmt;
 ///
 /// ```
 /// println!("nothing fancy");
+/// println!("but with two lines!");
 /// ```
 ///
 /// A failing to compile one:
@@ -123,3 +124,10 @@ pub mod huge_amount_of_consts {
 
 /// Very long code text `hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`.
 pub mod long_code_block {}
+
+#[macro_export]
+macro_rules! repro {
+    () => {};
+}
+
+pub use crate::repro as repro2;
diff --git a/src/test/rustdoc-ui/doc-without-codeblock.rs b/src/test/rustdoc-ui/doc-without-codeblock.rs
index 6812a454157b9..315fca195873a 100644
--- a/src/test/rustdoc-ui/doc-without-codeblock.rs
+++ b/src/test/rustdoc-ui/doc-without-codeblock.rs
@@ -11,3 +11,12 @@ pub mod foo {
     //~^ ERROR missing code example in this documentation
     pub fn bar() {}
 }
+
+// This impl is here to ensure the lint isn't emitted for foreign traits implementations.
+impl std::ops::Neg for Foo {
+    type Output = Self;
+
+    fn neg(self) -> Self::Output {
+        Self
+    }
+}
diff --git a/src/test/rustdoc-ui/doc-without-codeblock.stderr b/src/test/rustdoc-ui/doc-without-codeblock.stderr
index aac537e9783cd..1c138044165f2 100644
--- a/src/test/rustdoc-ui/doc-without-codeblock.stderr
+++ b/src/test/rustdoc-ui/doc-without-codeblock.stderr
@@ -6,7 +6,7 @@ LL | |
 LL | | /// Some docs.
 LL | |
 ...  |
-LL | |     pub fn bar() {}
+LL | |     }
 LL | | }
    | |_^
    |
diff --git a/src/test/ui/rustc-rust-log.rs b/src/test/ui/rustc-rust-log.rs
index 8ceb24dd2afd2..52e7dcf4499a8 100644
--- a/src/test/ui/rustc-rust-log.rs
+++ b/src/test/ui/rustc-rust-log.rs
@@ -1,9 +1,6 @@
 // run-pass
 // This test is just checking that we won't ICE if logging is turned
-// on; don't bother trying to compare that (copious) output. (Note
-// also that this test potentially silly, since we do not build+test
-// debug versions of rustc as part of our continuous integration
-// process...)
+// on; don't bother trying to compare that (copious) output.
 //
 // dont-check-compiler-stdout
 // dont-check-compiler-stderr
diff --git a/src/tools/rustfmt/.github/workflows/upload-assets.yml b/src/tools/rustfmt/.github/workflows/upload-assets.yml
index 9a5fd0dd1d31b..f4dd394445301 100644
--- a/src/tools/rustfmt/.github/workflows/upload-assets.yml
+++ b/src/tools/rustfmt/.github/workflows/upload-assets.yml
@@ -1,8 +1,10 @@
 name: upload
 
 on:
+  push:
   release:
     types: [created]
+  workflow_dispatch:
 
 jobs:
   build-release:
@@ -14,42 +16,40 @@ jobs:
           - build: linux-x86_64
             os: ubuntu-latest
             rust: nightly
+            target: x86_64-unknown-linux-gnu
           - build: macos-x86_64
             os: macos-latest
             rust: nightly
+            target: x86_64-apple-darwin
           - build: windows-x86_64-gnu
             os: windows-latest
             rust: nightly-x86_64-gnu
+            target: x86_64-pc-windows-gnu
           - build: windows-x86_64-msvc
             os: windows-latest
             rust: nightly-x86_64-msvc
+            target: x86_64-pc-windows-msvc
     runs-on: ${{ matrix.os }}
     steps:
       - uses: actions/checkout@v2
 
-      - name: Install Rust
-        uses: actions-rs/toolchain@v1
-        with:
-          profile: minimal
-          toolchain: ${{ matrix.rust }}
-          override: true
+        # Run build
+      - name: install rustup
+        run: |
+          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
+          sh rustup-init.sh -y --default-toolchain none
+          rustup target add ${{ matrix.target }}
 
       - name: Add mingw64 to path for x86_64-gnu
         run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH
         if: matrix.rust == 'nightly-x86_64-gnu'
         shell: bash
 
-      - name: Install cargo-make
-        uses: actions-rs/cargo@v1
-        with:
-          command: install
-          args: --force cargo-make
-
       - name: Build release binaries
         uses: actions-rs/cargo@v1
         with:
-          command: make
-          args: release
+          command: build
+          args: --release
 
       - name: Build archive
         shell: bash
@@ -70,6 +70,7 @@ jobs:
           fi
 
       - name: Upload Release Asset
+        if: github.event_name == 'release'
         uses: actions/upload-release-asset@v1
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/src/tools/rustfmt/.github/workflows/windows.yml b/src/tools/rustfmt/.github/workflows/windows.yml
index 08cb52eedaea7..c05e8d4896ac7 100644
--- a/src/tools/rustfmt/.github/workflows/windows.yml
+++ b/src/tools/rustfmt/.github/workflows/windows.yml
@@ -54,9 +54,6 @@ jobs:
       if: matrix.target == 'x86_64-pc-windows-gnu' && matrix.channel == 'nightly'
       shell: bash
 
-    - name: cargo-make
-      run: cargo install --force cargo-make
-
     - name: build
       run: |
         rustc -Vv
diff --git a/src/tools/rustfmt/.gitignore b/src/tools/rustfmt/.gitignore
index 37adf8751ca8f..71cf88f79e67b 100644
--- a/src/tools/rustfmt/.gitignore
+++ b/src/tools/rustfmt/.gitignore
@@ -5,6 +5,7 @@
 # Generated by Cargo
 # will have compiled files and executables
 /target
+tests/cargo-fmt/**/target
 
 # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
 # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md
index 68354b6ceaf25..b59438dc4fe78 100644
--- a/src/tools/rustfmt/CHANGELOG.md
+++ b/src/tools/rustfmt/CHANGELOG.md
@@ -2,6 +2,73 @@
 
 ## [Unreleased]
 
+## [1.4.38] 2021-10-20
+
+### Changed
+
+- Switched from `rustc-ap-*` crates to `rustc_private` for consumption model of rustc internals
+- `annotate-snippets` updated to v0.8 [PR #4762](https://github.com/rust-lang/rustfmt/pull/4762)
+- Greatly improved the performance of `cargo fmt` in large workspaces utilizing the `--all` flag by updating to a newer version of `cargo_metadata` that leverages updated `cargo` output from v1.51+ [PR #4997](https://github.com/rust-lang/rustfmt/pull/4997)
+- Improved formatting of long slice patterns [#4530](https://github.com/rust-lang/rustfmt/issues/4530)
+  - **Note you must have `version = Two` in your configuration to take advantage of the new formatting**
+- Stabilized `match_block_trailing_comma` configuration option [#3380](https://github.com/rust-lang/rustfmt/issues/3380) - [https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#match_block_trailing_comma](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#match_block_trailing_comma)
+- Stabilized `disable_all_formatting` configuration option [#5026](https://github.com/rust-lang/rustfmt/pull/5026) - [https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#disable_all_formatting)
+- Various improvements to the configuration documentation website [https://rust-lang.github.io/rustfmt/?version=v1.4.38]([https://rust-lang.github.io/rustfmt/?version=v1.4.38])
+- Addressed various clippy and rustc warnings
+
+
+### Fixed
+
+- Resolved issue where specious whitespace would be inserted when a block style comment was terminated within string literal processing [#4312](https://github.com/rust-lang/rustfmt/issues/4312)
+- Nested out-of-line mods are again parsed and formatted [#4874](https://github.com/rust-lang/rustfmt/issues/4874)
+- Accepts `2021` for edition value from rustfmt command line [PR #4847](https://github.com/rust-lang/rustfmt/pull/4847)
+- Unstable command line options are no longer displayed in `--help` text on stable [PR #4798](https://github.com/rust-lang/rustfmt/issues/4798)
+- Stopped panicking on patterns in match arms which start with non-ascii characters [#4868](https://github.com/rust-lang/rustfmt/issues/4868)
+- Stopped stripping defaults on const params [#4816](https://github.com/rust-lang/rustfmt/issues/4816)
+- Fixed issue with dropped content with GAT aliases with self bounds in impls [#4911](https://github.com/rust-lang/rustfmt/issues/4911)
+- Stopped removing generic args on associated type constraints [#4943](https://github.com/rust-lang/rustfmt/issues/4943)
+- Stopped dropping visibility on certain trait and impl items [#4960](https://github.com/rust-lang/rustfmt/issues/4960)
+- Fixed dropping of qualified paths in struct patterns [#4908](https://github.com/rust-lang/rustfmt/issues/4908) and [#5005](https://github.com/rust-lang/rustfmt/issues/5005)
+- Fixed bug in line width calculation that was causing specious formatting of certain patterns [#4031](https://github.com/rust-lang/rustfmt/issues/4031)
+  - **Note that this bug fix may cause observable formatting changes in cases where code had been formatted with prior versions of rustfmt that contained the bug**
+- Fixed bug where rustfmt would drop parameter attributes if they were too long in certain cases [#4579](https://github.com/rust-lang/rustfmt/issues/4579)
+- Resolved idempotency issue with extern body elements [#4963](https://github.com/rust-lang/rustfmt/issues/4963)
+- rustfmt will now handle doc-style comments on function parameters, since they could appear with certain macro usage patterns even though it's generally invalid syntax [#4936](https://github.com/rust-lang/rustfmt/issues/4936)
+- Fixed bug in `match_block_trailing_comma` where commas were not added to the blocks of bodies whose arm had a guard that did not fit on the same line as the pattern [#4998](https://github.com/rust-lang/rustfmt/pull/4998)
+- Fixed bug in cases where derive attributes started with a block style comment [#4984](https://github.com/rust-lang/rustfmt/issues/4984)
+- Fixed issue where the struct rest could be lost when `struct_field_align_threshold` was enabled [#4926](https://github.com/rust-lang/rustfmt/issues/4926)
+- Handles cases where certain control flow type expressions have comments between patterns/keywords and the pattern ident contains the keyword [#5009](https://github.com/rust-lang/rustfmt/issues/5009)
+- Handles tuple structs that have explicit visibilities and start with a block style comment [#5011](https://github.com/rust-lang/rustfmt/issues/5011)
+- Handles leading line-style comments in certain types of macro calls [#4615](https://github.com/rust-lang/rustfmt/issues/4615)
+
+
+### Added
+- Granular width heuristic options made available for user control [PR #4782](https://github.com/rust-lang/rustfmt/pull/4782). This includes the following:
+  - [`array_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#array_width)
+  - [`attr_fn_like_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#attr_fn_like_width)
+  - [`chain_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#chain_width)
+  - [`fn_call_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#fn_call_width)
+  - [`single_line_if_else_max_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#single_line_if_else_max_width)
+  - [`struct_lit_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#struct_lit_width)
+  - [`struct_variant_width`](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#struct_variant_width)
+
+Note this hit the rustup distributions prior to the v1.4.38 release as part of an out-of-cycle updates, but is listed in this version because the feature was not in the other v1.4.37 releases. See also the `use_small_heuristics` section on the configuration site for more information
+[https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#use_small_heuristics](https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#use_small_heuristics)
+
+- New `One` variant added to `imports_granularity` configuration option which can be used to reformat all imports into a single use statement [#4669](https://github.com/rust-lang/rustfmt/issues/4669)
+- rustfmt will now skip files that are annotated with `@generated` at the top of the file [#3958](https://github.com/rust-lang/rustfmt/issues/3958)
+- New configuration option `hex_literal_case` that allows user to control the casing utilized for hex literals [PR #4903](https://github.com/rust-lang/rustfmt/pull/4903)
+
+See the section on the configuration site for more information
+https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#hex_literal_case
+
+- `cargo fmt` now directly supports the `--check` flag, which means it's now possible to run `cargo fmt --check` instead of the more verbose `cargo fmt -- --check` [#3888](https://github.com/rust-lang/rustfmt/issues/3888)
+
+### Install/Download Options
+- **rustup (nightly)** - *pending*
+- **GitHub Release Binaries** - [Release v1.4.38](https://github.com/rust-lang/rustfmt/releases/tag/v1.4.38)
+- **Build from source** - [Tag v1.4.38](https://github.com/rust-lang/rustfmt/tree/v1.4.38), see instructions for how to [install rustfmt from source][install-from-source]
+
 ## [1.4.37] 2021-04-03
 
 ### Changed
diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock
index 03bb5598007ce..2ef83ddd1ae6c 100644
--- a/src/tools/rustfmt/Cargo.lock
+++ b/src/tools/rustfmt/Cargo.lock
@@ -35,21 +35,6 @@ version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14"
 
-[[package]]
-name = "arrayref"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
-
-[[package]]
-name = "arrayvec"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
-dependencies = [
- "nodrop",
-]
-
 [[package]]
 name = "atty"
 version = "0.2.13"
@@ -62,40 +47,9 @@ dependencies = [
 
 [[package]]
 name = "autocfg"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
-
-[[package]]
-name = "backtrace"
-version = "0.3.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
-dependencies = [
- "backtrace-sys",
- "cfg-if 0.1.10",
- "libc",
- "rustc-demangle",
-]
-
-[[package]]
-name = "backtrace-sys"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "base64"
-version = "0.10.1"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
-dependencies = [
- "byteorder",
-]
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
 [[package]]
 name = "bitflags"
@@ -103,17 +57,6 @@ version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
-[[package]]
-name = "blake2b_simd"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
-dependencies = [
- "arrayref",
- "arrayvec",
- "constant_time_eq",
-]
-
 [[package]]
 name = "bstr"
 version = "0.2.8"
@@ -125,36 +68,43 @@ dependencies = [
 
 [[package]]
 name = "bytecount"
-version = "0.6.0"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e"
+checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
 dependencies = [
- "packed_simd",
+ "packed_simd_2",
 ]
 
 [[package]]
-name = "byteorder"
-version = "1.3.2"
+name = "camino"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
+dependencies = [
+ "serde",
+]
 
 [[package]]
-name = "cargo_metadata"
-version = "0.8.2"
+name = "cargo-platform"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426"
+checksum = "0226944a63d1bf35a3b5f948dd7c59e263db83695c9e8bffc4037de02e30f1d7"
 dependencies = [
- "semver",
  "serde",
- "serde_derive",
- "serde_json",
 ]
 
 [[package]]
-name = "cc"
-version = "1.0.46"
+name = "cargo_metadata"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c"
+checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+]
 
 [[package]]
 name = "cfg-if"
@@ -183,48 +133,14 @@ dependencies = [
  "vec_map",
 ]
 
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "constant_time_eq"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
-dependencies = [
- "crossbeam-utils 0.7.0",
-]
-
 [[package]]
 name = "crossbeam-utils"
-version = "0.6.6"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
-dependencies = [
- "cfg-if 0.1.10",
- "lazy_static",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
+checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
 dependencies = [
  "autocfg",
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "lazy_static",
 ]
 
@@ -257,11 +173,10 @@ dependencies = [
 
 [[package]]
 name = "dirs-sys"
-version = "0.3.4"
+version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
+checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
 dependencies = [
- "cfg-if 0.1.10",
  "libc",
  "redox_users",
  "winapi",
@@ -275,9 +190,9 @@ checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
 
 [[package]]
 name = "env_logger"
-version = "0.6.2"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
+checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd"
 dependencies = [
  "atty",
  "humantime",
@@ -286,40 +201,12 @@ dependencies = [
  "termcolor",
 ]
 
-[[package]]
-name = "failure"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
-dependencies = [
- "backtrace",
- "failure_derive",
-]
-
-[[package]]
-name = "failure_derive"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
 [[package]]
 name = "fnv"
 version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
 [[package]]
 name = "getopts"
 version = "0.2.21"
@@ -329,11 +216,22 @@ dependencies = [
  "unicode-width",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi",
+]
+
 [[package]]
 name = "globset"
-version = "0.4.4"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2"
+checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
 dependencies = [
  "aho-corasick",
  "bstr",
@@ -353,36 +251,33 @@ dependencies = [
 
 [[package]]
 name = "humantime"
-version = "1.3.0"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error",
-]
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "ignore"
-version = "0.4.11"
+version = "0.4.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e"
+checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"
 dependencies = [
- "crossbeam-channel",
+ "crossbeam-utils",
  "globset",
  "lazy_static",
  "log",
  "memchr",
  "regex",
  "same-file",
- "thread_local 1.0.1",
+ "thread_local",
  "walkdir",
  "winapi-util",
 ]
 
 [[package]]
 name = "itertools"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
+checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
 dependencies = [
  "either",
 ]
@@ -405,6 +300,12 @@ version = "0.2.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
 
+[[package]]
+name = "libm"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
+
 [[package]]
 name = "log"
 version = "0.4.14"
@@ -421,18 +322,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
 
 [[package]]
-name = "nodrop"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
-
-[[package]]
-name = "packed_simd"
-version = "0.3.3"
+name = "packed_simd_2"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220"
+checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
 dependencies = [
  "cfg-if 0.1.10",
+ "libm",
 ]
 
 [[package]]
@@ -463,19 +359,13 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.6"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
+checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
 dependencies = [
  "unicode-xid",
 ]
 
-[[package]]
-name = "quick-error"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
-
 [[package]]
 name = "quote"
 version = "1.0.6"
@@ -486,95 +376,41 @@ dependencies = [
 ]
 
 [[package]]
-name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
-[[package]]
-name = "rand_os"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
-dependencies = [
- "cloudabi",
- "fuchsia-cprng",
- "libc",
- "rand_core 0.4.2",
- "rdrand",
- "winapi",
-]
-
-[[package]]
-name = "rdrand"
-version = "0.4.0"
+name = "redox_syscall"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
 dependencies = [
- "rand_core 0.3.1",
+ "bitflags",
 ]
 
-[[package]]
-name = "redox_syscall"
-version = "0.1.56"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
-
 [[package]]
 name = "redox_users"
-version = "0.3.1"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
+checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
 dependencies = [
- "failure",
- "rand_os",
+ "getrandom",
  "redox_syscall",
- "rust-argon2",
 ]
 
 [[package]]
 name = "regex"
-version = "1.3.1"
+version = "1.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
+checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
 dependencies = [
  "aho-corasick",
  "memchr",
  "regex-syntax",
- "thread_local 0.3.6",
+ "thread_local",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
-
-[[package]]
-name = "rust-argon2"
-version = "0.5.1"
+version = "0.6.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
-dependencies = [
- "base64",
- "blake2b_simd",
- "crossbeam-utils 0.6.6",
-]
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
+checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
 
 [[package]]
 name = "rustc-workspace-hack"
@@ -593,7 +429,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.37"
+version = "1.4.38"
 dependencies = [
  "annotate-snippets",
  "anyhow",
@@ -639,34 +475,27 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "0.9.0"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
 dependencies = [
- "semver-parser",
  "serde",
 ]
 
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-
 [[package]]
 name = "serde"
-version = "1.0.101"
+version = "1.0.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
+checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.101"
+version = "1.0.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e"
+checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -675,9 +504,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.41"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2"
+checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
 dependencies = [
  "itoa",
  "ryu",
@@ -716,9 +545,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.11"
+version = "1.0.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
+checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -736,18 +565,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "synstructure"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "unicode-xid",
-]
-
 [[package]]
 name = "term"
 version = "0.6.1"
@@ -796,15 +613,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "thread_local"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
-dependencies = [
- "lazy_static",
-]
-
 [[package]]
 name = "thread_local"
 version = "1.0.1"
@@ -870,6 +678,12 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
 [[package]]
 name = "winapi"
 version = "0.3.8"
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index 7b4667c17c864..8d9c4a7fb20cd 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "rustfmt-nightly"
-version = "1.4.37"
+version = "1.4.38"
 description = "Tool to find and fix Rust formatting issues"
 repository = "https://github.com/rust-lang/rustfmt"
 readme = "README.md"
@@ -33,7 +33,7 @@ rustfmt-format-diff = []
 generic-simd = ["bytecount/generic-simd"]
 
 [dependencies]
-itertools = "0.8"
+itertools = "0.9"
 toml = "0.5"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
@@ -42,15 +42,15 @@ regex = "1.0"
 term = "0.6"
 diff = "0.1"
 log = "0.4.14"
-env_logger = "0.6"
+env_logger = "0.8"
 getopts = "0.2"
 derive-new = "0.5"
-cargo_metadata = "0.8"
+cargo_metadata = "0.14"
 bytecount = "0.6"
 unicode-width = "0.1.5"
 unicode_categories = "0.1.1"
 dirs = "2.0.1"
-ignore = "0.4.11"
+ignore = "0.4.17"
 annotate-snippets = { version = "0.8", features = ["color"] }
 structopt = "0.3"
 rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" }
diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md
index d2e5613eba964..7a77dbe154b60 100644
--- a/src/tools/rustfmt/Configurations.md
+++ b/src/tools/rustfmt/Configurations.md
@@ -521,11 +521,13 @@ fn main() {
 
 ## `disable_all_formatting`
 
-Don't reformat anything
+Don't reformat anything.
+
+Note that this option may be soft-deprecated in the future once the [ignore](#ignore) option is stabilized. Nightly toolchain users are encouraged to use [ignore](#ignore) instead when possible.
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3388)
+- **Stable**: Yes
 
 ## `edition`
 
@@ -924,6 +926,15 @@ fn add_one(x: i32) -> i32 {
 }
 ```
 
+## `format_generated_files`
+
+Format generated files. A file is considered generated
+if any of the first five lines contains `@generated` marker.
+
+- **Default value**: `false`
+- **Possible values**: `true`, `false`
+- **Stable**: No
+
 ## `format_macro_matchers`
 
 Format the metavariable matching patterns in macros.
@@ -1047,6 +1058,13 @@ fn lorem() -> usize {
 
 See also: [`tab_spaces`](#tab_spaces).
 
+## `hex_literal_case`
+
+Control the case of the letters in hexadecimal literal values
+
+- **Default value**: `Preserve`
+- **Possible values**: `Upper`, `Lower`
+- **Stable**: No
 
 ## `hide_parse_errors`
 
@@ -1610,7 +1628,7 @@ Put a trailing comma after a block based match arm (non-block arms are not affec
 
 - **Default value**: `false`
 - **Possible values**: `true`, `false`
-- **Stable**: No (tracking issue: #3380)
+- **Stable**: Yes
 
 #### `false` (default):
 
@@ -1668,6 +1686,9 @@ pub enum Foo {}
 #### `false`:
 
 ```rust
+#[derive(Eq, PartialEq, Debug, Copy, Clone)]
+pub enum Bar {}
+
 #[derive(Eq, PartialEq)]
 #[derive(Debug)]
 #[derive(Copy, Clone)]
@@ -1679,7 +1700,7 @@ pub enum Foo {}
 How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity.
 
 - **Default value**: `Preserve`
-- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`
+- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One`
 - **Stable**: No
 
 #### `Preserve` (default):
@@ -1733,6 +1754,23 @@ use qux::h;
 use qux::i;
 ```
 
+#### `One`:
+
+Merge all imports into a single `use` statement as long as they have the same visibility.
+
+```rust
+pub use foo::{x, y};
+use {
+    bar::{
+        a,
+        b::{self, f, g},
+        c,
+        d::e,
+    },
+    qux::{h, i},
+};
+```
+
 ## `merge_imports`
 
 This option is deprecated. Use `imports_granularity = "Crate"` instead.
@@ -1824,6 +1862,9 @@ Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments.
 #![doc = "Example documentation"]
 
 #[doc = "Example item documentation"]
+pub enum Bar {}
+
+/// Example item documentation
 pub enum Foo {}
 ```
 
@@ -1938,6 +1979,8 @@ fn main() {
 #### `false`:
 ```rust
 fn main() {
+    (foo());
+
     ((((foo()))));
 }
 ```
@@ -1963,6 +2006,14 @@ impl Iterator for Dummy {
 
     type Item = i32;
 }
+
+impl Iterator for Dummy {
+    type Item = i32;
+
+    fn next(&mut self) -> Option {
+        None
+    }
+}
 ```
 
 #### `true`
@@ -2519,7 +2570,8 @@ fn main() {
     let x = 1;
     let y = 2;
     let z = 3;
-    let a = Foo { x: x, y: y, z: z };
+    let a = Foo { x, y, z };
+    let b = Foo { x: x, y: y, z: z };
 }
 ```
 
@@ -2688,6 +2740,8 @@ Replace uses of the try! macro by the ? shorthand
 
 ```rust
 fn main() {
+    let lorem = ipsum.map(|dolor| dolor.sit())?;
+
     let lorem = try!(ipsum.map(|dolor| dolor.sit()));
 }
 ```
@@ -2759,6 +2813,12 @@ Break comments to fit on the line
 #### `false` (default):
 
 ```rust
+// Lorem ipsum dolor sit amet, consectetur adipiscing elit,
+// sed do eiusmod tempor incididunt ut labore et dolore
+// magna aliqua. Ut enim ad minim veniam, quis nostrud
+// exercitation ullamco laboris nisi ut aliquip ex ea
+// commodo consequat.
+
 // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
 ```
 
diff --git a/src/tools/rustfmt/appveyor.yml b/src/tools/rustfmt/appveyor.yml
index 5ac99fd71f8f8..b3dda091e0a96 100644
--- a/src/tools/rustfmt/appveyor.yml
+++ b/src/tools/rustfmt/appveyor.yml
@@ -1,55 +1,8 @@
-# This is based on https://github.com/japaric/rust-everywhere/blob/master/appveyor.yml
-# and modified (mainly removal of deployment) to suit rustfmt.
-
 environment:
   global:
     PROJECT_NAME: rustfmt
-  matrix:
-    # Stable channel
-    # - TARGET: i686-pc-windows-gnu
-    #   CHANNEL: stable
-    # - TARGET: i686-pc-windows-msvc
-    #   CHANNEL: stable
-    # - TARGET: x86_64-pc-windows-gnu
-    #   CHANNEL: stable
-    # - TARGET: x86_64-pc-windows-msvc
-    #   CHANNEL: stable
-    # Beta channel
-    # - TARGET: i686-pc-windows-gnu
-    #   CHANNEL: beta
-    # - TARGET: i686-pc-windows-msvc
-    #   CHANNEL: beta
-    # - TARGET: x86_64-pc-windows-gnu
-    #   CHANNEL: beta
-    # - TARGET: x86_64-pc-windows-msvc
-    #   CHANNEL: beta
-    # Nightly channel
-    - TARGET: i686-pc-windows-gnu
-      CHANNEL: nightly
-    - TARGET: i686-pc-windows-msvc
-      CHANNEL: nightly
-    - TARGET: x86_64-pc-windows-gnu
-      CHANNEL: nightly
-    - TARGET: x86_64-pc-windows-msvc
-      CHANNEL: nightly
-
-# Install Rust and Cargo
-# (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml)
-install:
-  - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
-  - if "%TARGET%" == "i686-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw32\bin
-  - if "%TARGET%" == "x86_64-pc-windows-gnu" set PATH=%PATH%;C:\msys64\mingw64\bin
-  - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
-  - rustup-init.exe --default-host %TARGET% --default-toolchain %CHANNEL% -y
-  - rustc -Vv
-  - cargo -V
 
-# ???
 build: false
 
 test_script:
-  - set CFG_RELEASE_CHANNEL=nightly
-  - set CFG_RELEASE=nightly
-  - cargo build --verbose
-  - cargo test
-  - cargo test -- --ignored
+  - echo Why does no one have access to delete me?
diff --git a/src/tools/rustfmt/docs/index.html b/src/tools/rustfmt/docs/index.html
index 56d1917e2b61b..4fa932d4c762e 100644
--- a/src/tools/rustfmt/docs/index.html
+++ b/src/tools/rustfmt/docs/index.html
@@ -2,9 +2,13 @@
 
     
       
+      Rustfmt
       
+      
       
       
+      
+      
       
       
     
     
@@ -59,6 +72,14 @@
                   
                   
               
+              
+ + +
@@ -66,63 +87,155 @@ - \ No newline at end of file + diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain index b0cd4464df8e5..b19ecbdb07c4f 100644 --- a/src/tools/rustfmt/rust-toolchain +++ b/src/tools/rustfmt/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-07-23" +channel = "nightly-2021-10-20" components = ["rustc-dev"] diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 315eb10a9dbc0..a5982820e3ded 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -13,6 +13,7 @@ use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::Shape; +use crate::source_map::SpanUtils; use crate::types::{rewrite_path, PathContext}; use crate::utils::{count_newlines, mk_sp}; @@ -116,7 +117,9 @@ fn format_derive( |span| span.lo(), |span| span.hi(), |span| Some(context.snippet(*span).to_owned()), - attr.span.lo(), + // We update derive attribute spans to start after the opening '(' + // This helps us focus parsing to just what's inside #[derive(...)] + context.snippet_provider.span_after(attr.span, "("), attr.span.hi(), false, ); diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index 4b4aa42d93596..1bcc5c0dada3b 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -121,7 +121,7 @@ fn make_opts() -> Options { found reverts to the input file path", "[Path for the configuration file]", ); - opts.optopt("", "edition", "Rust edition to use", "[2015|2018]"); + opts.optopt("", "edition", "Rust edition to use", "[2015|2018|2021]"); opts.optopt( "", "color", diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs index 90ffad927e2c4..1d423ac34919b 100644 --- a/src/tools/rustfmt/src/cargo-fmt/main.rs +++ b/src/tools/rustfmt/src/cargo-fmt/main.rs @@ -17,6 +17,10 @@ use std::str; use structopt::StructOpt; +#[path = "test/mod.rs"] +#[cfg(test)] +mod cargo_fmt_tests; + #[derive(StructOpt, Debug)] #[structopt( bin_name = "cargo fmt", @@ -36,7 +40,7 @@ pub struct Opts { #[structopt(long = "version")] version: bool, - /// Specify package to format (only usable in workspaces) + /// Specify package to format #[structopt(short = "p", long = "package", value_name = "package")] packages: Vec, @@ -53,9 +57,13 @@ pub struct Opts { #[structopt(name = "rustfmt_options", raw(true))] rustfmt_options: Vec, - /// Format all packages (only usable in workspaces) + /// Format all packages, and also their local path-based dependencies #[structopt(long = "all")] format_all: bool, + + /// Run rustfmt in check mode + #[structopt(long = "check")] + check: bool, } fn main() { @@ -104,6 +112,12 @@ fn execute() -> i32 { let strategy = CargoFmtStrategy::from_opts(&opts); let mut rustfmt_args = opts.rustfmt_options; + if opts.check { + let check_flag = "--check"; + if !rustfmt_args.iter().any(|o| o == check_flag) { + rustfmt_args.push(check_flag.to_owned()); + } + } if let Some(message_format) = opts.message_format { if let Err(msg) = convert_message_format_to_rustfmt_args(&message_format, &mut rustfmt_args) { @@ -346,7 +360,7 @@ fn get_targets_root_only( manifest_path: Option<&Path>, targets: &mut BTreeSet, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path, false)?; + let metadata = get_cargo_metadata(manifest_path)?; let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; let (in_workspace_root, current_dir_manifest) = if let Some(target_manifest) = manifest_path { ( @@ -390,34 +404,29 @@ fn get_targets_recursive( mut targets: &mut BTreeSet, visited: &mut BTreeSet, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path, false)?; - let metadata_with_deps = get_cargo_metadata(manifest_path, true)?; - - for package in metadata.packages { + let metadata = get_cargo_metadata(manifest_path)?; + for package in &metadata.packages { add_targets(&package.targets, &mut targets); - // Look for local dependencies. - for dependency in package.dependencies { - if dependency.source.is_some() || visited.contains(&dependency.name) { + // Look for local dependencies using information available since cargo v1.51 + // It's theoretically possible someone could use a newer version of rustfmt with + // a much older version of `cargo`, but we don't try to explicitly support that scenario. + // If someone reports an issue with path-based deps not being formatted, be sure to + // confirm their version of `cargo` (not `cargo-fmt`) is >= v1.51 + // https://github.com/rust-lang/cargo/pull/8994 + for dependency in &package.dependencies { + if dependency.path.is_none() || visited.contains(&dependency.name) { continue; } - let dependency_package = metadata_with_deps - .packages - .iter() - .find(|p| p.name == dependency.name && p.source.is_none()); - let manifest_path = if let Some(dep_pkg) = dependency_package { - PathBuf::from(&dep_pkg.manifest_path) - } else { - let mut package_manifest_path = PathBuf::from(&package.manifest_path); - package_manifest_path.pop(); - package_manifest_path.push(&dependency.name); - package_manifest_path.push("Cargo.toml"); - package_manifest_path - }; - - if manifest_path.exists() { - visited.insert(dependency.name); + let manifest_path = PathBuf::from(dependency.path.as_ref().unwrap()).join("Cargo.toml"); + if manifest_path.exists() + && !metadata + .packages + .iter() + .any(|p| p.manifest_path.eq(&manifest_path)) + { + visited.insert(dependency.name.to_owned()); get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; } } @@ -431,8 +440,7 @@ fn get_targets_with_hitlist( hitlist: &[String], targets: &mut BTreeSet, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path, false)?; - + let metadata = get_cargo_metadata(manifest_path)?; let mut workspace_hitlist: BTreeSet<&String> = BTreeSet::from_iter(hitlist); for package in metadata.packages { @@ -517,18 +525,13 @@ fn run_rustfmt( .unwrap_or(SUCCESS)) } -fn get_cargo_metadata( - manifest_path: Option<&Path>, - include_deps: bool, -) -> Result { +fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { let mut cmd = cargo_metadata::MetadataCommand::new(); - if !include_deps { - cmd.no_deps(); - } + cmd.no_deps(); if let Some(manifest_path) = manifest_path { cmd.manifest_path(manifest_path); } - cmd.other_options(&[String::from("--offline")]); + cmd.other_options(vec![String::from("--offline")]); match cmd.exec() { Ok(metadata) => Ok(metadata), @@ -541,221 +544,3 @@ fn get_cargo_metadata( } } } - -#[cfg(test)] -mod cargo_fmt_tests { - use super::*; - - #[test] - fn default_options() { - let empty: Vec = vec![]; - let o = Opts::from_iter(&empty); - assert_eq!(false, o.quiet); - assert_eq!(false, o.verbose); - assert_eq!(false, o.version); - assert_eq!(empty, o.packages); - assert_eq!(empty, o.rustfmt_options); - assert_eq!(false, o.format_all); - assert_eq!(None, o.manifest_path); - assert_eq!(None, o.message_format); - } - - #[test] - fn good_options() { - let o = Opts::from_iter(&[ - "test", - "-q", - "-p", - "p1", - "-p", - "p2", - "--message-format", - "short", - "--", - "--edition", - "2018", - ]); - assert_eq!(true, o.quiet); - assert_eq!(false, o.verbose); - assert_eq!(false, o.version); - assert_eq!(vec!["p1", "p2"], o.packages); - assert_eq!(vec!["--edition", "2018"], o.rustfmt_options); - assert_eq!(false, o.format_all); - assert_eq!(Some(String::from("short")), o.message_format); - } - - #[test] - fn unexpected_option() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "unexpected"]) - .is_err() - ); - } - - #[test] - fn unexpected_flag() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "--flag"]) - .is_err() - ); - } - - #[test] - fn mandatory_separator() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "--check"]) - .is_err() - ); - assert!( - !Opts::clap() - .get_matches_from_safe(&["test", "--", "--check"]) - .is_err() - ); - } - - #[test] - fn multiple_packages_one_by_one() { - let o = Opts::from_iter(&[ - "test", - "-p", - "package1", - "--package", - "package2", - "-p", - "package3", - ]); - assert_eq!(3, o.packages.len()); - } - - #[test] - fn multiple_packages_grouped() { - let o = Opts::from_iter(&[ - "test", - "--package", - "package1", - "package2", - "-p", - "package3", - "package4", - ]); - assert_eq!(4, o.packages.len()); - } - - #[test] - fn empty_packages_1() { - assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err()); - } - - #[test] - fn empty_packages_2() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "-p", "--", "--check"]) - .is_err() - ); - } - - #[test] - fn empty_packages_3() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "-p", "--verbose"]) - .is_err() - ); - } - - #[test] - fn empty_packages_4() { - assert!( - Opts::clap() - .get_matches_from_safe(&["test", "-p", "--check"]) - .is_err() - ); - } - - mod convert_message_format_to_rustfmt_args_tests { - use super::*; - - #[test] - fn invalid_message_format() { - assert_eq!( - convert_message_format_to_rustfmt_args("awesome", &mut vec![]), - Err(String::from( - "invalid --message-format value: awesome. Allowed values are: short|json|human" - )), - ); - } - - #[test] - fn json_message_format_and_check_arg() { - let mut args = vec![String::from("--check")]; - assert_eq!( - convert_message_format_to_rustfmt_args("json", &mut args), - Err(String::from( - "cannot include --check arg when --message-format is set to json" - )), - ); - } - - #[test] - fn json_message_format_and_emit_arg() { - let mut args = vec![String::from("--emit"), String::from("checkstyle")]; - assert_eq!( - convert_message_format_to_rustfmt_args("json", &mut args), - Err(String::from( - "cannot include --emit arg when --message-format is set to json" - )), - ); - } - - #[test] - fn json_message_format() { - let mut args = vec![String::from("--edition"), String::from("2018")]; - assert!(convert_message_format_to_rustfmt_args("json", &mut args).is_ok()); - assert_eq!( - args, - vec![ - String::from("--edition"), - String::from("2018"), - String::from("--emit"), - String::from("json") - ] - ); - } - - #[test] - fn human_message_format() { - let exp_args = vec![String::from("--emit"), String::from("json")]; - let mut act_args = exp_args.clone(); - assert!(convert_message_format_to_rustfmt_args("human", &mut act_args).is_ok()); - assert_eq!(act_args, exp_args); - } - - #[test] - fn short_message_format() { - let mut args = vec![String::from("--check")]; - assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); - assert_eq!(args, vec![String::from("--check"), String::from("-l")]); - } - - #[test] - fn short_message_format_included_short_list_files_flag() { - let mut args = vec![String::from("--check"), String::from("-l")]; - assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); - assert_eq!(args, vec![String::from("--check"), String::from("-l")]); - } - - #[test] - fn short_message_format_included_long_list_files_flag() { - let mut args = vec![String::from("--check"), String::from("--files-with-diff")]; - assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); - assert_eq!( - args, - vec![String::from("--check"), String::from("--files-with-diff")] - ); - } - } -} diff --git a/src/tools/rustfmt/src/cargo-fmt/test/message_format.rs b/src/tools/rustfmt/src/cargo-fmt/test/message_format.rs new file mode 100644 index 0000000000000..bf44924f13c31 --- /dev/null +++ b/src/tools/rustfmt/src/cargo-fmt/test/message_format.rs @@ -0,0 +1,80 @@ +use super::*; + +#[test] +fn invalid_message_format() { + assert_eq!( + convert_message_format_to_rustfmt_args("awesome", &mut vec![]), + Err(String::from( + "invalid --message-format value: awesome. Allowed values are: short|json|human" + )), + ); +} + +#[test] +fn json_message_format_and_check_arg() { + let mut args = vec![String::from("--check")]; + assert_eq!( + convert_message_format_to_rustfmt_args("json", &mut args), + Err(String::from( + "cannot include --check arg when --message-format is set to json" + )), + ); +} + +#[test] +fn json_message_format_and_emit_arg() { + let mut args = vec![String::from("--emit"), String::from("checkstyle")]; + assert_eq!( + convert_message_format_to_rustfmt_args("json", &mut args), + Err(String::from( + "cannot include --emit arg when --message-format is set to json" + )), + ); +} + +#[test] +fn json_message_format() { + let mut args = vec![String::from("--edition"), String::from("2018")]; + assert!(convert_message_format_to_rustfmt_args("json", &mut args).is_ok()); + assert_eq!( + args, + vec![ + String::from("--edition"), + String::from("2018"), + String::from("--emit"), + String::from("json") + ] + ); +} + +#[test] +fn human_message_format() { + let exp_args = vec![String::from("--emit"), String::from("json")]; + let mut act_args = exp_args.clone(); + assert!(convert_message_format_to_rustfmt_args("human", &mut act_args).is_ok()); + assert_eq!(act_args, exp_args); +} + +#[test] +fn short_message_format() { + let mut args = vec![String::from("--check")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!(args, vec![String::from("--check"), String::from("-l")]); +} + +#[test] +fn short_message_format_included_short_list_files_flag() { + let mut args = vec![String::from("--check"), String::from("-l")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!(args, vec![String::from("--check"), String::from("-l")]); +} + +#[test] +fn short_message_format_included_long_list_files_flag() { + let mut args = vec![String::from("--check"), String::from("--files-with-diff")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!( + args, + vec![String::from("--check"), String::from("--files-with-diff")] + ); +} diff --git a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs new file mode 100644 index 0000000000000..360503632c7ed --- /dev/null +++ b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs @@ -0,0 +1,137 @@ +use super::*; + +mod message_format; +mod targets; + +#[test] +fn default_options() { + let empty: Vec = vec![]; + let o = Opts::from_iter(&empty); + assert_eq!(false, o.quiet); + assert_eq!(false, o.verbose); + assert_eq!(false, o.version); + assert_eq!(false, o.check); + assert_eq!(empty, o.packages); + assert_eq!(empty, o.rustfmt_options); + assert_eq!(false, o.format_all); + assert_eq!(None, o.manifest_path); + assert_eq!(None, o.message_format); +} + +#[test] +fn good_options() { + let o = Opts::from_iter(&[ + "test", + "-q", + "-p", + "p1", + "-p", + "p2", + "--message-format", + "short", + "--check", + "--", + "--edition", + "2018", + ]); + assert_eq!(true, o.quiet); + assert_eq!(false, o.verbose); + assert_eq!(false, o.version); + assert_eq!(true, o.check); + assert_eq!(vec!["p1", "p2"], o.packages); + assert_eq!(vec!["--edition", "2018"], o.rustfmt_options); + assert_eq!(false, o.format_all); + assert_eq!(Some(String::from("short")), o.message_format); +} + +#[test] +fn unexpected_option() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "unexpected"]) + .is_err() + ); +} + +#[test] +fn unexpected_flag() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "--flag"]) + .is_err() + ); +} + +#[test] +fn mandatory_separator() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "--emit"]) + .is_err() + ); + assert!( + !Opts::clap() + .get_matches_from_safe(&["test", "--", "--emit"]) + .is_err() + ); +} + +#[test] +fn multiple_packages_one_by_one() { + let o = Opts::from_iter(&[ + "test", + "-p", + "package1", + "--package", + "package2", + "-p", + "package3", + ]); + assert_eq!(3, o.packages.len()); +} + +#[test] +fn multiple_packages_grouped() { + let o = Opts::from_iter(&[ + "test", + "--package", + "package1", + "package2", + "-p", + "package3", + "package4", + ]); + assert_eq!(4, o.packages.len()); +} + +#[test] +fn empty_packages_1() { + assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err()); +} + +#[test] +fn empty_packages_2() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--", "--check"]) + .is_err() + ); +} + +#[test] +fn empty_packages_3() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--verbose"]) + .is_err() + ); +} + +#[test] +fn empty_packages_4() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--check"]) + .is_err() + ); +} diff --git a/src/tools/rustfmt/src/cargo-fmt/test/targets.rs b/src/tools/rustfmt/src/cargo-fmt/test/targets.rs new file mode 100644 index 0000000000000..b7e7fabdf7156 --- /dev/null +++ b/src/tools/rustfmt/src/cargo-fmt/test/targets.rs @@ -0,0 +1,134 @@ +use super::*; + +struct ExpTarget { + path: &'static str, + edition: &'static str, + kind: &'static str, +} + +mod all_targets { + use super::*; + + fn assert_correct_targets_loaded( + manifest_suffix: &str, + source_root: &str, + exp_targets: &[ExpTarget], + exp_num_targets: usize, + ) { + let root_path = Path::new("tests/cargo-fmt/source").join(source_root); + let get_path = |exp: &str| PathBuf::from(&root_path).join(exp).canonicalize().unwrap(); + let manifest_path = Path::new(&root_path).join(manifest_suffix); + let targets = get_targets(&CargoFmtStrategy::All, Some(manifest_path.as_path())) + .expect("Targets should have been loaded"); + + assert_eq!(targets.len(), exp_num_targets); + + for target in exp_targets { + assert!(targets.contains(&Target { + path: get_path(target.path), + edition: target.edition.to_owned(), + kind: target.kind.to_owned(), + })); + } + } + + mod different_crate_and_dir_names { + use super::*; + + fn assert_correct_targets_loaded(manifest_suffix: &str) { + let exp_targets = vec![ + ExpTarget { + path: "dependency-dir-name/subdep-dir-name/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "dependency-dir-name/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "src/main.rs", + edition: "2018", + kind: "main", + }, + ]; + super::assert_correct_targets_loaded( + manifest_suffix, + "divergent-crate-dir-names", + &exp_targets, + 3, + ); + } + + #[test] + fn correct_targets_from_root() { + assert_correct_targets_loaded("Cargo.toml"); + } + + #[test] + fn correct_targets_from_sub_local_dep() { + assert_correct_targets_loaded("dependency-dir-name/Cargo.toml"); + } + } + + mod workspaces { + use super::*; + + fn assert_correct_targets_loaded(manifest_suffix: &str) { + let exp_targets = vec![ + ExpTarget { + path: "ws/a/src/main.rs", + edition: "2018", + kind: "bin", + }, + ExpTarget { + path: "ws/b/src/main.rs", + edition: "2018", + kind: "bin", + }, + ExpTarget { + path: "ws/c/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "ws/a/d/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ExpTarget { + path: "e/src/main.rs", + edition: "2018", + kind: "main", + }, + ExpTarget { + path: "ws/a/d/f/src/lib.rs", + edition: "2018", + kind: "lib", + }, + ]; + super::assert_correct_targets_loaded( + manifest_suffix, + "workspaces/path-dep-above", + &exp_targets, + 6, + ); + } + + #[test] + fn includes_outside_workspace_deps() { + assert_correct_targets_loaded("ws/Cargo.toml"); + } + + #[test] + fn includes_workspace_from_dep_above() { + assert_correct_targets_loaded("e/Cargo.toml"); + } + + #[test] + fn includes_all_packages_from_workspace_subdir() { + assert_correct_targets_loaded("ws/a/d/f/Cargo.toml"); + } + } +} diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs index 58a2b5e6aecf3..6082542485856 100644 --- a/src/tools/rustfmt/src/comment.rs +++ b/src/tools/rustfmt/src/comment.rs @@ -10,7 +10,8 @@ use crate::rewrite::RewriteContext; use crate::shape::{Indent, Shape}; use crate::string::{rewrite_string, StringFormat}; use crate::utils::{ - count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, unicode_str_width, + count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, + trimmed_last_line_width, unicode_str_width, }; use crate::{ErrorKind, FormattingError}; @@ -171,11 +172,12 @@ pub(crate) fn combine_strs_with_missing_comments( String::with_capacity(prev_str.len() + next_str.len() + shape.indent.width() + 128); result.push_str(prev_str); let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); - let first_sep = if prev_str.is_empty() || next_str.is_empty() { - "" - } else { - " " - }; + let first_sep = + if prev_str.is_empty() || next_str.is_empty() || trimmed_last_line_width(prev_str) == 0 { + "" + } else { + " " + }; let mut one_line_width = last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); @@ -184,7 +186,7 @@ pub(crate) fn combine_strs_with_missing_comments( let missing_comment = rewrite_missing_comment(span, shape, context)?; if missing_comment.is_empty() { - if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { + if allow_extend && one_line_width <= shape.width { result.push_str(first_sep); } else if !prev_str.is_empty() { result.push_str(&indent.to_string_with_newline(config)) @@ -392,28 +394,26 @@ fn identify_comment( } } -/// Attributes for code blocks in rustdoc. -/// See . +/// Enum indicating if the code block contains rust based on attributes enum CodeBlockAttribute { Rust, - Ignore, - Text, - ShouldPanic, - NoRun, - CompileFail, + NotRust, } impl CodeBlockAttribute { - fn new(attribute: &str) -> CodeBlockAttribute { - match attribute { - "rust" | "" => CodeBlockAttribute::Rust, - "ignore" => CodeBlockAttribute::Ignore, - "text" => CodeBlockAttribute::Text, - "should_panic" => CodeBlockAttribute::ShouldPanic, - "no_run" => CodeBlockAttribute::NoRun, - "compile_fail" => CodeBlockAttribute::CompileFail, - _ => CodeBlockAttribute::Text, + /// Parse comma separated attributes list. Return rust only if all + /// attributes are valid rust attributes + /// See https://doc.rust-lang.org/rustdoc/print.html#attributes + fn new(attributes: &str) -> CodeBlockAttribute { + for attribute in attributes.split(",") { + match attribute.trim() { + "" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018" + | "edition2021" => (), + "ignore" | "compile_fail" | "text" => return CodeBlockAttribute::NotRust, + _ => return CodeBlockAttribute::NotRust, + } } + CodeBlockAttribute::Rust } } @@ -647,25 +647,21 @@ impl<'a> CommentRewrite<'a> { } else if self.code_block_attr.is_some() { if line.starts_with("```") { let code_block = match self.code_block_attr.as_ref().unwrap() { - CodeBlockAttribute::Ignore | CodeBlockAttribute::Text => { - trim_custom_comment_prefix(&self.code_block_buffer) - } - _ if self.code_block_buffer.is_empty() => String::new(), - _ => { + CodeBlockAttribute::Rust + if self.fmt.config.format_code_in_doc_comments() + && !self.code_block_buffer.is_empty() => + { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); - if config.format_code_in_doc_comments() { - if let Some(s) = - crate::format_code_block(&self.code_block_buffer, &config, false) - { - trim_custom_comment_prefix(&s.snippet) - } else { - trim_custom_comment_prefix(&self.code_block_buffer) - } + if let Some(s) = + crate::format_code_block(&self.code_block_buffer, &config, false) + { + trim_custom_comment_prefix(&s.snippet) } else { trim_custom_comment_prefix(&self.code_block_buffer) } } + _ => trim_custom_comment_prefix(&self.code_block_buffer), }; if !code_block.is_empty() { self.result.push_str(&self.comment_line_separator); diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index 8c04363b1fd4b..c5419d860c943 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -69,6 +69,8 @@ create_config! { format_macro_matchers: bool, false, false, "Format the metavariable matching patterns in macros"; format_macro_bodies: bool, true, false, "Format the bodies of macros"; + hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false, + "Format hexadecimal integer literals"; // Single line expressions and items empty_item_single_line: bool, true, false, @@ -125,7 +127,7 @@ create_config! { "Add trailing semicolon after break, continue and return"; trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, "How to handle trailing commas for lists"; - match_block_trailing_comma: bool, false, false, + match_block_trailing_comma: bool, false, true, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; blank_lines_upper_bound: usize, 1, false, "Maximum number of blank lines which can be put between items"; @@ -136,6 +138,7 @@ create_config! { inline_attribute_width: usize, 0, false, "Write an item and its attribute on the same line \ if their combined width is below a threshold"; + format_generated_files: bool, false, false, "Format generated files"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; @@ -152,7 +155,7 @@ create_config! { "Require a specific version of rustfmt"; unstable_features: bool, false, false, "Enables unstable features. Only available on nightly channel"; - disable_all_formatting: bool, false, false, "Don't reformat anything"; + disable_all_formatting: bool, false, true, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; hide_parse_errors: bool, false, false, "Hide errors from the parser"; error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width"; @@ -569,6 +572,7 @@ license_template_path = "" format_strings = false format_macro_matchers = false format_macro_bodies = true +hex_literal_case = "Preserve" empty_item_single_line = true struct_lit_single_line = true fn_single_line = false @@ -604,6 +608,7 @@ blank_lines_lower_bound = 0 edition = "2015" version = "One" inline_attribute_width = 0 +format_generated_files = false merge_derives = true use_try_shorthand = false use_field_init_shorthand = false diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs index 3b91021813c16..e92f8e8a53152 100644 --- a/src/tools/rustfmt/src/config/options.rs +++ b/src/tools/rustfmt/src/config/options.rs @@ -125,6 +125,19 @@ pub enum ImportGranularity { Module, /// Use one `use` statement per imported item. Item, + /// Use one `use` statement including all items. + One, +} + +/// Controls how rustfmt should handle case in hexadecimal literals. +#[config_type] +pub enum HexLiteralCase { + /// Leave the literal as-is + Preserve, + /// Ensure all literals use uppercase lettering + Upper, + /// Ensure all literals use lowercase lettering + Lower, } #[config_type] diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 975af6c02947a..7f1dd363f9379 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -13,7 +13,7 @@ use crate::comment::{ rewrite_missing_comment, CharClasses, FindUncommented, }; use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; +use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, Version}; use crate::lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, Separator, @@ -822,7 +822,7 @@ impl<'a> ControlFlow<'a> { let pat_string = pat.rewrite(context, pat_shape)?; let comments_lo = context .snippet_provider - .span_after(self.span, self.connector.trim()); + .span_after(self.span.with_lo(pat.span.hi()), self.connector.trim()); let comments_span = mk_sp(comments_lo, expr.span.lo()); return rewrite_assign_rhs_with_comments( context, @@ -1168,6 +1168,7 @@ pub(crate) fn rewrite_literal( ) -> Option { match l.kind { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), + ast::LitKind::Int(..) => rewrite_int_lit(context, l, shape), _ => wrap_str( context.snippet(l.span).to_owned(), context.config.max_width(), @@ -1202,6 +1203,36 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> ) } +fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -> Option { + let span = lit.span; + let symbol = lit.token.symbol.as_str(); + + if symbol.starts_with("0x") { + let hex_lit = match context.config.hex_literal_case() { + HexLiteralCase::Preserve => None, + HexLiteralCase::Upper => Some(symbol[2..].to_ascii_uppercase()), + HexLiteralCase::Lower => Some(symbol[2..].to_ascii_lowercase()), + }; + if let Some(hex_lit) = hex_lit { + return wrap_str( + format!( + "0x{}{}", + hex_lit, + lit.token.suffix.map_or(String::new(), |s| s.to_string()) + ), + context.config.max_width(), + shape, + ); + } + } + + wrap_str( + context.snippet(span).to_owned(), + context.config.max_width(), + shape, + ) +} + fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option { if context.inside_macro() { if span_ends_with_comma(context, span) { @@ -1497,12 +1528,12 @@ fn rewrite_struct_lit<'a>( let path_shape = shape.sub_width(2)?; let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - let has_base = match struct_rest { + let has_base_or_rest = match struct_rest { ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)), ast::StructRest::Rest(_) if fields.is_empty() => { return Some(format!("{} {{ .. }}", path_str)); } - ast::StructRest::Base(_) => true, + ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true, _ => false, }; @@ -1511,7 +1542,7 @@ fn rewrite_struct_lit<'a>( let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, has_base) + let fields_str = if struct_lit_can_be_aligned(fields, has_base_or_rest) && context.config.struct_field_align_threshold() > 0 { rewrite_with_alignment( @@ -1583,10 +1614,7 @@ fn rewrite_struct_lit<'a>( nested_shape, tactic, context, - force_no_trailing_comma - || has_base - || !context.use_block_indent() - || matches!(struct_rest, ast::StructRest::Rest(_)), + force_no_trailing_comma || has_base_or_rest || !context.use_block_indent(), ); write_list(&item_vec, &fmt)? diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs index e0403574eebc1..9ef47b887cadb 100644 --- a/src/tools/rustfmt/src/formatting.rs +++ b/src/tools/rustfmt/src/formatting.rs @@ -10,6 +10,7 @@ use rustc_span::Span; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; +use crate::formatting::generated::is_generated_file; use crate::issues::BadIssueSeeker; use crate::modules::Module; use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; @@ -18,6 +19,7 @@ use crate::utils::count_newlines; use crate::visitor::FmtVisitor; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; +mod generated; mod newline_style; // A map of the files of a crate, with their new content @@ -103,7 +105,12 @@ fn format_project( context.parse_session.set_silent_emitter(); for (path, module) in files { - let should_ignore = !input_is_stdin && context.ignore_file(&path); + let source_file = context.parse_session.span_to_file_contents(module.span); + let src = source_file.src.as_ref().expect("SourceFile without src"); + + let should_ignore = (!input_is_stdin && context.ignore_file(&path)) + || (!config.format_generated_files() && is_generated_file(src)); + if (config.skip_children() && path != main_file) || should_ignore { continue; } diff --git a/src/tools/rustfmt/src/formatting/generated.rs b/src/tools/rustfmt/src/formatting/generated.rs new file mode 100644 index 0000000000000..58f43f17ee15f --- /dev/null +++ b/src/tools/rustfmt/src/formatting/generated.rs @@ -0,0 +1,7 @@ +/// Returns `true` if the given span is a part of generated files. +pub(super) fn is_generated_file(original_snippet: &str) -> bool { + original_snippet + .lines() + .take(5) // looking for marker only in the beginning of the file + .any(|line| line.contains("@generated")) +} diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs index 64d78605f0c5f..5ac799366894d 100644 --- a/src/tools/rustfmt/src/imports.rs +++ b/src/tools/rustfmt/src/imports.rs @@ -138,6 +138,29 @@ impl UseSegment { } } + // Check if self == other with their aliases removed. + fn equal_except_alias(&self, other: &Self) -> bool { + match (self, other) { + (UseSegment::Ident(ref s1, _), UseSegment::Ident(ref s2, _)) => s1 == s2, + (UseSegment::Slf(_), UseSegment::Slf(_)) + | (UseSegment::Super(_), UseSegment::Super(_)) + | (UseSegment::Crate(_), UseSegment::Crate(_)) + | (UseSegment::Glob, UseSegment::Glob) => true, + (UseSegment::List(ref list1), UseSegment::List(ref list2)) => list1 == list2, + _ => false, + } + } + + fn get_alias(&self) -> Option<&str> { + match self { + UseSegment::Ident(_, a) + | UseSegment::Slf(a) + | UseSegment::Super(a) + | UseSegment::Crate(a) => a.as_deref(), + _ => None, + } + } + fn from_path_segment( context: &RewriteContext<'_>, path_seg: &ast::PathSegment, @@ -558,6 +581,7 @@ impl UseTree { SharedPrefix::Module => { self.path[..self.path.len() - 1] == other.path[..other.path.len() - 1] } + SharedPrefix::One => true, } } } @@ -598,7 +622,7 @@ impl UseTree { fn merge(&mut self, other: &UseTree, merge_by: SharedPrefix) { let mut prefix = 0; for (a, b) in self.path.iter().zip(other.path.iter()) { - if *a == *b { + if a.equal_except_alias(b) { prefix += 1; } else { break; @@ -633,14 +657,20 @@ fn merge_rest( return Some(new_path); } } else if len == 1 { - let rest = if a.len() == len { &b[1..] } else { &a[1..] }; - return Some(vec![ - b[0].clone(), - UseSegment::List(vec![ - UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP), - UseTree::from_path(rest.to_vec(), DUMMY_SP), - ]), - ]); + let (common, rest) = if a.len() == len { + (&a[0], &b[1..]) + } else { + (&b[0], &a[1..]) + }; + let mut list = vec![UseTree::from_path( + vec![UseSegment::Slf(common.get_alias().map(ToString::to_string))], + DUMMY_SP, + )]; + match rest { + [UseSegment::List(rest_list)] => list.extend(rest_list.clone()), + _ => list.push(UseTree::from_path(rest.to_vec(), DUMMY_SP)), + } + return Some(vec![b[0].clone(), UseSegment::List(list)]); } else { len -= 1; } @@ -655,18 +685,54 @@ fn merge_rest( } fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree, merge_by: SharedPrefix) { - let similar_trees = trees - .iter_mut() - .filter(|tree| tree.share_prefix(&use_tree, merge_by)); + struct SimilarTree<'a> { + similarity: usize, + path_len: usize, + tree: &'a mut UseTree, + } + + let similar_trees = trees.iter_mut().filter_map(|tree| { + if tree.share_prefix(&use_tree, merge_by) { + // In the case of `SharedPrefix::One`, `similarity` is used for deciding with which + // tree `use_tree` should be merge. + // In other cases `similarity` won't be used, so set it to `0` as a dummy value. + let similarity = if merge_by == SharedPrefix::One { + tree.path + .iter() + .zip(&use_tree.path) + .take_while(|(a, b)| a.equal_except_alias(b)) + .count() + } else { + 0 + }; + + let path_len = tree.path.len(); + Some(SimilarTree { + similarity, + tree, + path_len, + }) + } else { + None + } + }); + if use_tree.path.len() == 1 && merge_by == SharedPrefix::Crate { - if let Some(tree) = similar_trees.min_by_key(|tree| tree.path.len()) { - if tree.path.len() == 1 { + if let Some(tree) = similar_trees.min_by_key(|tree| tree.path_len) { + if tree.path_len == 1 { + return; + } + } + } else if merge_by == SharedPrefix::One { + if let Some(sim_tree) = similar_trees.max_by_key(|tree| tree.similarity) { + if sim_tree.similarity > 0 { + sim_tree.tree.merge(&use_tree, merge_by); return; } } - } else if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) { - if tree.path.len() > 1 { - tree.merge(&use_tree, merge_by); + } else if let Some(sim_tree) = similar_trees.max_by_key(|tree| tree.path_len) { + if sim_tree.path_len > 1 { + sim_tree.tree.merge(&use_tree, merge_by); return; } } @@ -880,6 +946,7 @@ impl Rewrite for UseTree { pub(crate) enum SharedPrefix { Crate, Module, + One, } #[cfg(test)] @@ -904,7 +971,7 @@ mod test { } fn eat(&mut self, c: char) { - assert!(self.input.next().unwrap() == c); + assert_eq!(self.input.next().unwrap(), c); } fn push_segment( @@ -1094,6 +1161,49 @@ mod test { ); } + #[test] + fn test_use_tree_merge_one() { + test_merge!(One, ["a", "b"], ["{a, b}"]); + + test_merge!(One, ["a::{aa, ab}", "b", "a"], ["{a::{self, aa, ab}, b}"]); + + test_merge!(One, ["a as x", "b as y"], ["{a as x, b as y}"]); + + test_merge!( + One, + ["a::{aa as xa, ab}", "b", "a"], + ["{a::{self, aa as xa, ab}, b}"] + ); + + test_merge!( + One, + ["a", "a::{aa, ab::{aba, abb}}"], + ["a::{self, aa, ab::{aba, abb}}"] + ); + + test_merge!(One, ["a", "b::{ba, *}"], ["{a, b::{ba, *}}"]); + + test_merge!(One, ["a", "b", "a::aa"], ["{a::{self, aa}, b}"]); + + test_merge!( + One, + ["a::aa::aaa", "a::ac::aca", "a::aa::*"], + ["a::{aa::{aaa, *}, ac::aca}"] + ); + + test_merge!( + One, + ["a", "b::{ba, bb}", "a::{aa::*, ab::aba}"], + ["{a::{self, aa::*, ab::aba}, b::{ba, bb}}"] + ); + + test_merge!( + One, + ["b", "a::ac::{aca, acb}", "a::{aa::*, ab}"], + ["{a::{aa::*, ab, ac::{aca, acb}}, b}"] + ); + } + #[test] fn test_flatten_use_trees() { assert_eq!( diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 14041539b9dfd..1cb1a2701c36b 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -174,14 +174,14 @@ pub(crate) struct FnSig<'a> { constness: ast::Const, defaultness: ast::Defaultness, unsafety: ast::Unsafe, - visibility: ast::Visibility, + visibility: &'a ast::Visibility, } impl<'a> FnSig<'a> { pub(crate) fn from_method_sig( method_sig: &'a ast::FnSig, generics: &'a ast::Generics, - visibility: ast::Visibility, + visibility: &'a ast::Visibility, ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, @@ -204,7 +204,7 @@ impl<'a> FnSig<'a> { match *fn_kind { visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt { visit::FnCtxt::Assoc(..) => { - let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis.clone()); + let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis); fn_sig.defaultness = defaultness; fn_sig } @@ -216,7 +216,7 @@ impl<'a> FnSig<'a> { is_async: Cow::Borrowed(&fn_sig.header.asyncness), defaultness, unsafety: fn_sig.header.unsafety, - visibility: vis.clone(), + visibility: vis, }, }, _ => unreachable!(), @@ -323,6 +323,7 @@ impl<'a> FmtVisitor<'a> { indent: Indent, ident: symbol::Ident, sig: &ast::FnSig, + vis: &ast::Visibility, generics: &ast::Generics, span: Span, ) -> Option { @@ -334,7 +335,7 @@ impl<'a> FmtVisitor<'a> { &context, indent, ident, - &FnSig::from_method_sig(sig, generics, DEFAULT_VISIBILITY), + &FnSig::from_method_sig(sig, generics, vis), span, FnBraceStyle::None, )?; @@ -1474,12 +1475,17 @@ fn format_tuple_struct( format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")"); } else { let shape = Shape::indented(offset, context.config).sub_width(1)?; + let lo = if let Some(generics) = struct_parts.generics { + generics.span.hi() + } else { + struct_parts.ident.span.hi() + }; result = overflow::rewrite_with_parens( context, &result, fields.iter(), shape, - span, + mk_sp(lo, span.hi()), context.config.fn_call_width(), None, )?; @@ -1503,7 +1509,7 @@ fn format_tuple_struct( Some(result) } -fn rewrite_type( +pub(crate) fn rewrite_type( context: &RewriteContext<'_>, indent: Indent, ident: symbol::Ident, @@ -1760,7 +1766,7 @@ impl<'a> StaticParts<'a> { }; StaticParts { prefix: "const", - vis: &DEFAULT_VISIBILITY, + vis: &ti.vis, ident: ti.ident, ty, mutability: ast::Mutability::Not, @@ -1847,29 +1853,6 @@ fn rewrite_static( Some(format!("{}{};", prefix, ty_str)) } } - -pub(crate) fn rewrite_type_alias( - ident: symbol::Ident, - ty_opt: Option<&ptr::P>, - generics: &ast::Generics, - generic_bounds_opt: Option<&ast::GenericBounds>, - context: &RewriteContext<'_>, - indent: Indent, - vis: &ast::Visibility, - span: Span, -) -> Option { - rewrite_type( - context, - indent, - ident, - vis, - generics, - generic_bounds_opt, - ty_opt, - span, - ) -} - struct OpaqueType<'a> { bounds: &'a ast::GenericBounds, } @@ -1883,32 +1866,7 @@ impl<'a> Rewrite for OpaqueType<'a> { } } -pub(crate) fn rewrite_opaque_impl_type( - context: &RewriteContext<'_>, - ident: symbol::Ident, - generics: &ast::Generics, - generic_bounds: &ast::GenericBounds, - indent: Indent, -) -> Option { - let ident_str = rewrite_ident(context, ident); - // 5 = "type " - let generics_shape = Shape::indented(indent, context.config).offset_left(5)?; - let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?; - let prefix = format!("type {} =", generics_str); - let rhs = OpaqueType { - bounds: generic_bounds, - }; - - rewrite_assign_rhs( - context, - &prefix, - &rhs, - Shape::indented(indent, context.config).sub_width(1)?, - ) - .map(|s| s + ";") -} - -pub(crate) fn rewrite_associated_impl_type( +pub(crate) fn rewrite_impl_type( ident: symbol::Ident, vis: &ast::Visibility, defaultness: ast::Defaultness, @@ -1918,7 +1876,25 @@ pub(crate) fn rewrite_associated_impl_type( indent: Indent, span: Span, ) -> Option { - let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis, span)?; + // Opaque type + let result = if let Some(rustc_ast::ast::Ty { + kind: ast::TyKind::ImplTrait(_, ref bounds), + .. + }) = ty_opt.map(|t| &**t) + { + rewrite_type( + context, + indent, + ident, + &DEFAULT_VISIBILITY, + generics, + None, + Some(&OpaqueType { bounds }), + span, + ) + } else { + rewrite_type(context, indent, ident, vis, generics, None, ty_opt, span) + }?; match defaultness { ast::Defaultness::Default(..) => Some(format!("default {}", result)), @@ -1995,14 +1971,17 @@ impl Rewrite for ast::Param { let param_attrs_result = self .attrs .rewrite(context, Shape::legacy(shape.width, shape.indent))?; - let (span, has_multiple_attr_lines) = if !self.attrs.is_empty() { + // N.B. Doc comments aren't typically valid syntax, but could appear + // in the presence of certain macros - https://github.com/rust-lang/rustfmt/issues/4936 + let (span, has_multiple_attr_lines, has_doc_comments) = if !self.attrs.is_empty() { let num_attrs = self.attrs.len(); ( mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()), param_attrs_result.contains('\n'), + self.attrs.iter().any(|a| a.is_doc_comment()), ) } else { - (mk_sp(self.span.lo(), self.span.lo()), false) + (mk_sp(self.span.lo(), self.span.lo()), false, false) }; if let Some(ref explicit_self) = self.to_self() { @@ -2015,15 +1994,16 @@ impl Rewrite for ast::Param { has_multiple_attr_lines, ) } else if is_named_param(self) { + let param_name = &self + .pat + .rewrite(context, Shape::legacy(shape.width, shape.indent))?; let mut result = combine_strs_with_missing_comments( context, ¶m_attrs_result, - &self - .pat - .rewrite(context, Shape::legacy(shape.width, shape.indent))?, + param_name, span, shape, - !has_multiple_attr_lines, + !has_multiple_attr_lines && !has_doc_comments, )?; if !is_empty_infer(&*self.ty, self.pat.span) { @@ -2034,10 +2014,30 @@ impl Rewrite for ast::Param { result.push_str(&after_comment); let overhead = last_line_width(&result); let max_width = shape.width.checked_sub(overhead)?; - let ty_str = self + if let Some(ty_str) = self .ty - .rewrite(context, Shape::legacy(max_width, shape.indent))?; - result.push_str(&ty_str); + .rewrite(context, Shape::legacy(max_width, shape.indent)) + { + result.push_str(&ty_str); + } else { + result = combine_strs_with_missing_comments( + context, + &(param_attrs_result + &shape.to_string_with_newline(context.config)), + param_name, + span, + shape, + !has_multiple_attr_lines, + )?; + result.push_str(&before_comment); + result.push_str(colon_spaces(context.config)); + result.push_str(&after_comment); + let overhead = last_line_width(&result); + let max_width = shape.width.checked_sub(overhead)?; + let ty_str = self + .ty + .rewrite(context, Shape::legacy(max_width, shape.indent))?; + result.push_str(&ty_str); + } } Some(result) @@ -3146,7 +3146,7 @@ impl Rewrite for ast::ForeignItem { context, shape.indent, self.ident, - &FnSig::from_method_sig(&fn_sig, generics, self.vis.clone()), + &FnSig::from_method_sig(&fn_sig, generics, &self.vis), span, FnBraceStyle::None, ) @@ -3170,14 +3170,14 @@ impl Rewrite for ast::ForeignItem { ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => { let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) = **ty_alias_kind; - rewrite_type_alias( - self.ident, - type_default.as_ref(), - generics, - Some(generic_bounds), + rewrite_type( &context, shape.indent, + self.ident, &self.vis, + generics, + Some(generic_bounds), + type_default.as_ref(), self.span, ) } diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs index 73e886c55637e..c04b478761693 100644 --- a/src/tools/rustfmt/src/lists.rs +++ b/src/tools/rustfmt/src/lists.rs @@ -367,9 +367,9 @@ where result.push_str(&comment); if !inner_item.is_empty() { - if tactic == DefinitiveListTactic::Vertical || tactic == DefinitiveListTactic::Mixed - { - // We cannot keep pre-comments on the same line if the comment if normalized. + use DefinitiveListTactic::*; + if matches!(tactic, Vertical | Mixed | SpecialMacro(_)) { + // We cannot keep pre-comments on the same line if the comment is normalized. let keep_comment = if formatting.config.normalize_comments() || item.pre_comment_style == ListItemCommentStyle::DifferentLine { @@ -389,7 +389,7 @@ where line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s)); } } else { - result.push(' '); + result.push(' ') } } item_max_width = None; diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs index 140ec226c02e5..5a6ed0ec06e55 100644 --- a/src/tools/rustfmt/src/matches.rs +++ b/src/tools/rustfmt/src/matches.rs @@ -409,6 +409,7 @@ fn rewrite_match_body( } result.push_str(&nested_indent_str); result.push_str(&body_str); + result.push_str(&comma); return Some(result); } diff --git a/src/tools/rustfmt/src/missed_spans.rs b/src/tools/rustfmt/src/missed_spans.rs index 263d840785a29..28edcb784b40e 100644 --- a/src/tools/rustfmt/src/missed_spans.rs +++ b/src/tools/rustfmt/src/missed_spans.rs @@ -51,6 +51,14 @@ impl<'a> FmtVisitor<'a> { } pub(crate) fn format_missing_with_indent(&mut self, end: BytePos) { + self.format_missing_indent(end, true) + } + + pub(crate) fn format_missing_no_indent(&mut self, end: BytePos) { + self.format_missing_indent(end, false) + } + + fn format_missing_indent(&mut self, end: BytePos, should_indent: bool) { let config = self.config; self.format_missing_inner(end, |this, last_snippet, snippet| { this.push_str(last_snippet.trim_end()); @@ -58,14 +66,10 @@ impl<'a> FmtVisitor<'a> { // No new lines in the snippet. this.push_str("\n"); } - let indent = this.block_indent.to_string(config); - this.push_str(&indent); - }) - } - - pub(crate) fn format_missing_no_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| { - this.push_str(last_snippet.trim_end()); + if should_indent { + let indent = this.block_indent.to_string(config); + this.push_str(&indent); + } }) } diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index e32213467a51f..ac24181c78052 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -77,6 +77,7 @@ pub(crate) enum OverflowableItem<'a> { FieldDef(&'a ast::FieldDef), TuplePatField(&'a TuplePatField<'a>), Ty(&'a ast::Ty), + Pat(&'a ast::Pat), } impl<'a> Rewrite for OverflowableItem<'a> { @@ -116,6 +117,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::FieldDef(sf) => f(*sf), OverflowableItem::TuplePatField(pat) => f(*pat), OverflowableItem::Ty(ty) => f(*ty), + OverflowableItem::Pat(pat) => f(*pat), } } @@ -232,7 +234,7 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types { } } -impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty); +impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty, Pat); impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); pub(crate) fn into_overflowable_list<'a, T>( diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 0501e76d27727..ba8d8024a9707 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -4,6 +4,7 @@ use rustc_span::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; use crate::config::lists::*; +use crate::config::Version; use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use crate::lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, @@ -226,12 +227,13 @@ impl Rewrite for Pat { PatKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) } - PatKind::TupleStruct(_, ref path, ref pat_vec) => { - let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; + PatKind::TupleStruct(ref q_self, ref path, ref pat_vec) => { + let path_str = + rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)?; rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape) } PatKind::Lit(ref expr) => expr.rewrite(context, shape), - PatKind::Slice(ref slice_pat) => { + PatKind::Slice(ref slice_pat) if context.config.version() == Version::One => { let rw: Vec = slice_pat .iter() .map(|p| { @@ -244,8 +246,17 @@ impl Rewrite for Pat { .collect(); Some(format!("[{}]", rw.join(", "))) } - PatKind::Struct(_, ref path, ref fields, ellipsis) => { - rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) + PatKind::Slice(ref slice_pat) => overflow::rewrite_with_square_brackets( + context, + "", + slice_pat.iter(), + shape, + self.span, + None, + None, + ), + PatKind::Struct(ref qself, ref path, ref fields, ellipsis) => { + rewrite_struct_pat(qself, path, fields, ellipsis, self.span, context, shape) } PatKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Pat) @@ -258,6 +269,7 @@ impl Rewrite for Pat { } fn rewrite_struct_pat( + qself: &Option, path: &ast::Path, fields: &[ast::PatField], ellipsis: bool, @@ -267,7 +279,7 @@ fn rewrite_struct_pat( ) -> Option { // 2 = ` {` let path_shape = shape.sub_width(2)?; - let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; + let path_str = rewrite_path(context, PathContext::Expr, qself.as_ref(), path, path_shape)?; if fields.is_empty() && !ellipsis { return Some(format!("{} {{}}", path_str)); diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs index ac65ff2c1086e..2c58350d4feb6 100644 --- a/src/tools/rustfmt/src/reorder.rs +++ b/src/tools/rustfmt/src/reorder.rs @@ -113,6 +113,7 @@ fn rewrite_reorderable_or_regroupable_items( merge_use_trees(normalized_items, SharedPrefix::Module) } ImportGranularity::Item => flatten_use_trees(normalized_items), + ImportGranularity::One => merge_use_trees(normalized_items, SharedPrefix::One), ImportGranularity::Preserve => normalized_items, }; diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 7e3786b7cd94c..8e6c75a3744ac 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -104,7 +104,7 @@ impl Spanned for ast::Arm { impl Spanned for ast::Param { fn span(&self) -> Span { if crate::items::is_named_param(self) { - mk_sp(self.pat.span.lo(), self.ty.span.hi()) + mk_sp(crate::items::span_lo_for_param(self), self.ty.span.hi()) } else { self.ty.span } diff --git a/src/tools/rustfmt/src/syntux/session.rs b/src/tools/rustfmt/src/syntux/session.rs index 2965b0928aada..946c076d9f2d1 100644 --- a/src/tools/rustfmt/src/syntux/session.rs +++ b/src/tools/rustfmt/src/syntux/session.rs @@ -175,6 +175,12 @@ impl ParseSess { self.parse_sess.source_map().span_to_filename(span).into() } + pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc { + self.parse_sess + .source_map() + .lookup_source_file(span.data().lo) + } + pub(crate) fn span_to_first_line_string(&self, span: Span) -> String { let file_lines = self.parse_sess.source_map().span_to_lines(span).ok(); diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs index cb52346a13a41..48d61289a9b8f 100644 --- a/src/tools/rustfmt/src/test/mod.rs +++ b/src/tools/rustfmt/src/test/mod.rs @@ -469,11 +469,6 @@ fn stdin_works_with_modified_lines() { #[test] fn stdin_disable_all_formatting_test() { init_log(); - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - // These tests require nightly. - _ => return, - } let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); let mut child = Command::new(rustfmt().to_str().unwrap()) .stdin(Stdio::piped()) @@ -694,7 +689,7 @@ fn read_significant_comments(file_name: &Path) -> HashMap { reader .lines() .map(|line| line.expect("failed getting line")) - .take_while(|line| line_regex.is_match(line)) + .filter(|line| line_regex.is_match(line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { ( diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 76bf58e875b1f..62c05ba078c56 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -169,31 +169,38 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::Const(const_) => const_.rewrite(context, shape), SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), - SegmentParam::Binding(assoc_ty_constraint) => { - let mut result = match assoc_ty_constraint.kind { - ast::AssocTyConstraintKind::Bound { .. } => { - format!("{}: ", rewrite_ident(context, assoc_ty_constraint.ident)) - } - ast::AssocTyConstraintKind::Equality { .. } => { - match context.config.type_punctuation_density() { - TypeDensity::Wide => { - format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident)) - } - TypeDensity::Compressed => { - format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident)) - } - } - } - }; + SegmentParam::Binding(atc) => atc.rewrite(context, shape), + } + } +} - let budget = shape.width.checked_sub(result.len())?; - let rewrite = assoc_ty_constraint - .kind - .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; - result.push_str(&rewrite); - Some(result) - } +impl Rewrite for ast::AssocTyConstraint { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + use ast::AssocTyConstraintKind::{Bound, Equality}; + + let mut result = String::with_capacity(128); + result.push_str(rewrite_ident(context, self.ident)); + + if let Some(ref gen_args) = self.gen_args { + let budget = shape.width.checked_sub(result.len())?; + let shape = Shape::legacy(budget, shape.indent + result.len()); + let gen_str = rewrite_generic_args(gen_args, context, shape, gen_args.span())?; + result.push_str(&gen_str); } + + let infix = match (&self.kind, context.config.type_punctuation_density()) { + (Bound { .. }, _) => ": ", + (Equality { .. }, TypeDensity::Wide) => " = ", + (Equality { .. }, TypeDensity::Compressed) => "=", + }; + result.push_str(infix); + + let budget = shape.width.checked_sub(result.len())?; + let shape = Shape::legacy(budget, shape.indent + result.len()); + let rewrite = self.kind.rewrite(context, shape)?; + result.push_str(&rewrite); + + Some(result) } } @@ -235,21 +242,9 @@ fn rewrite_segment( }; if let Some(ref args) = segment.args { + let generics_str = rewrite_generic_args(args, context, shape, mk_sp(*span_lo, span_hi))?; match **args { ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => { - let param_list = data - .args - .iter() - .map(|x| match x { - ast::AngleBracketedArg::Arg(generic_arg) => { - SegmentParam::from_generic_arg(generic_arg) - } - ast::AngleBracketedArg::Constraint(constraint) => { - SegmentParam::Binding(constraint) - } - }) - .collect::>(); - // 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 @@ -265,33 +260,14 @@ fn rewrite_segment( }; result.push_str(separator); - let generics_str = overflow::rewrite_with_angle_brackets( - context, - "", - param_list.iter(), - shape, - mk_sp(*span_lo, span_hi), - )?; - // Update position of last bracket. *span_lo = context .snippet_provider .span_after(mk_sp(*span_lo, span_hi), "<"); - - result.push_str(&generics_str) - } - ast::GenericArgs::Parenthesized(ref data) => { - result.push_str(&format_function_type( - data.inputs.iter().map(|x| &**x), - &data.output, - false, - data.span, - context, - shape, - )?); } _ => (), } + result.push_str(&generics_str) } Some(result) @@ -484,6 +460,41 @@ impl Rewrite for ast::GenericArg { } } +fn rewrite_generic_args( + gen_args: &ast::GenericArgs, + context: &RewriteContext<'_>, + shape: Shape, + span: Span, +) -> Option { + match gen_args { + ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => { + let args = data + .args + .iter() + .map(|x| match x { + ast::AngleBracketedArg::Arg(generic_arg) => { + SegmentParam::from_generic_arg(generic_arg) + } + ast::AngleBracketedArg::Constraint(constraint) => { + SegmentParam::Binding(constraint) + } + }) + .collect::>(); + + overflow::rewrite_with_angle_brackets(context, "", args.iter(), shape, span) + } + ast::GenericArgs::Parenthesized(ref data) => format_function_type( + data.inputs.iter().map(|x| &**x), + &data.output, + false, + data.span, + context, + shape, + ), + _ => Some("".to_owned()), + } +} + fn rewrite_bounded_lifetime( lt: &ast::Lifetime, bounds: &[ast::GenericBound], @@ -566,13 +577,23 @@ impl Rewrite for ast::GenericParam { if let ast::GenericParamKind::Const { ref ty, kw_span: _, - default: _, + default, } = &self.kind { result.push_str("const "); result.push_str(rewrite_ident(context, self.ident)); result.push_str(": "); result.push_str(&ty.rewrite(context, shape)?); + if let Some(default) = default { + let eq_str = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "=", + TypeDensity::Wide => " = ", + }; + result.push_str(eq_str); + let budget = shape.width.checked_sub(result.len())?; + let rewrite = default.rewrite(context, Shape::legacy(budget, shape.indent))?; + result.push_str(&rewrite); + } } else { result.push_str(rewrite_ident(context, self.ident)); } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 770693d165b7e..d854d90b40b6d 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use rustc_ast::{ast, token::DelimToken, visit, AstLike}; use rustc_data_structures::sync::Lrc; -use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; +use rustc_span::{symbol, BytePos, Pos, Span}; use crate::attr::*; use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; @@ -11,9 +11,9 @@ use crate::config::Version; use crate::config::{BraceStyle, Config}; use crate::coverage::transform_missing_snippet; use crate::items::{ - format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, - rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, + format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, + rewrite_impl_type, rewrite_opaque_type, rewrite_type, FnBraceStyle, FnSig, StaticParts, + StructParts, }; use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::modules::Module; @@ -568,6 +568,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { indent, item.ident, &fn_signature, + &item.vis, generics, item.span, ); @@ -579,14 +580,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { **alias_kind; match ty { Some(ty) => { - let rewrite = rewrite_type_alias( - item.ident, - Some(&*ty), - generics, - Some(generic_bounds), + let rewrite = rewrite_type( &self.get_context(), self.block_indent, + item.ident, &item.vis, + generics, + Some(generic_bounds), + Some(&*ty), item.span, ); self.push_rewrite(item.span, rewrite); @@ -641,14 +642,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind; if let Some(ref body) = block { let inner_attrs = inner_attributes(&ti.attrs); - let vis = ast::Visibility { - kind: ast::VisibilityKind::Inherited, - span: DUMMY_SP, - tokens: None, - }; let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); self.visit_fn( - visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), + visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &ti.vis, Some(body)), generics, &sig.decl, ti.span, @@ -658,21 +654,21 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { let indent = self.block_indent; let rewrite = - self.rewrite_required_fn(indent, ti.ident, sig, generics, ti.span); + self.rewrite_required_fn(indent, ti.ident, sig, &ti.vis, generics, ti.span); self.push_rewrite(ti.span, rewrite); } } ast::AssocItemKind::TyAlias(ref ty_alias_kind) => { let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) = **ty_alias_kind; - let rewrite = rewrite_type_alias( - ti.ident, - type_default.as_ref(), - generics, - Some(generic_bounds), + let rewrite = rewrite_type( &self.get_context(), self.block_indent, + ti.ident, &ti.vis, + generics, + Some(generic_bounds), + type_default.as_ref(), ti.span, ); self.push_rewrite(ti.span, rewrite); @@ -708,15 +704,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { let indent = self.block_indent; let rewrite = - self.rewrite_required_fn(indent, ii.ident, sig, generics, ii.span); + self.rewrite_required_fn(indent, ii.ident, sig, &ii.vis, generics, ii.span); self.push_rewrite(ii.span, rewrite); } } ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), ast::AssocItemKind::TyAlias(ref ty_alias_kind) => { let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind; - let rewrite_associated = || { - rewrite_associated_impl_type( + self.push_rewrite( + ii.span, + rewrite_impl_type( ii.ident, &ii.vis, defaultness, @@ -725,22 +722,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { &self.get_context(), self.block_indent, ii.span, - ) - }; - let rewrite = match ty { - None => rewrite_associated(), - Some(ty) => match ty.kind { - ast::TyKind::ImplTrait(_, ref bounds) => rewrite_opaque_impl_type( - &self.get_context(), - ii.ident, - generics, - bounds, - self.block_indent, - ), - _ => rewrite_associated(), - }, - }; - self.push_rewrite(ii.span, rewrite); + ), + ); } ast::AssocItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml new file mode 100644 index 0000000000000..315364a64573a --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cargo-fmt-test" +version = "0.1.0" +authors = ["calebcartwright"] +edition = "2018" + +[dependencies] +indexmap = "1.0.2" + +[workspace] +members = [ + "dependency-dir-name", +] \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml new file mode 100644 index 0000000000000..4493882bf40a2 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "dependency-crate-name" +version = "0.1.0" +authors = ["calebcartwright"] +edition = "2018" + +[dependencies] +subdep-crate-name = { path = "subdep-dir-name" } +indexmap = "1.0.2" +rusty-hook = "0.8.4" \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs new file mode 100644 index 0000000000000..e93b18d725b9d --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { +#[test] +fn it_works() { + assert_eq!(2 + 2, 4); +} +} diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml new file mode 100644 index 0000000000000..7dad09f4077b2 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "subdep-crate-name" +version = "0.1.0" +authors = ["calebcartwright"] +edition = "2018" + +[dependencies] diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs new file mode 100644 index 0000000000000..1c08c1c4fd386 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { +#[test] +fn sub_test_that_works() { + assert_eq!(3 + 3, 6); +} + } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs new file mode 100644 index 0000000000000..f5c339a8dd141 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs @@ -0,0 +1,3 @@ +fn main() { +println!("Hello, world!"); +} diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml new file mode 100644 index 0000000000000..eaf1d76f999d4 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "e" +version = "0.1.0" +edition = "2018" +[dependencies] +c = { path = "../ws/c" } + +[workspace] diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs new file mode 100644 index 0000000000000..1c26a3895f37e --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs @@ -0,0 +1 @@ +struct E{ } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml new file mode 100644 index 0000000000000..202739b613b8f --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "a", + "b" +] \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml new file mode 100644 index 0000000000000..712a113448fb1 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "a" +version = "0.1.0" +edition = "2018" +[dependencies] +d = { path = "./d" } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml new file mode 100644 index 0000000000000..fb0f06fe5fce1 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "d" +version = "0.1.0" +edition = "2018" +[dependencies] +e = { path = "../../../e" } +f = { path = "f" } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml new file mode 100644 index 0000000000000..5c4fa5617886f --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "f" +version = "0.1.0" +edition = "2018" diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs new file mode 100644 index 0000000000000..c655c4d5e1a82 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs @@ -0,0 +1 @@ +struct F{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs new file mode 100644 index 0000000000000..04e6e4cb94022 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs @@ -0,0 +1 @@ +struct D{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs new file mode 100644 index 0000000000000..04e6e4cb94022 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs @@ -0,0 +1 @@ +struct D{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml new file mode 100644 index 0000000000000..47a24ff4f2753 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "b" +version = "0.1.0" +edition = "2018" +[dependencies] +c = { path = "../c" } diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs new file mode 100644 index 0000000000000..4833bbc69b48e --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs @@ -0,0 +1 @@ +struct B{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml new file mode 100644 index 0000000000000..49fa6c395eb6c --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "c" +version = "0.1.0" +edition = "2018" diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs new file mode 100644 index 0000000000000..1245ac91d60a4 --- /dev/null +++ b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs @@ -0,0 +1 @@ +struct C{ } \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs b/src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs new file mode 100644 index 0000000000000..3804bf3215b19 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs @@ -0,0 +1,14 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ^ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ & abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ << abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/comp.rs b/src/tools/rustfmt/tests/source/binop-separator-back/comp.rs new file mode 100644 index 0000000000000..50a27127445df --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/comp.rs @@ -0,0 +1,23 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ < abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <= abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ > abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >= abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ == abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/logic.rs b/src/tools/rustfmt/tests/source/binop-separator-back/logic.rs new file mode 100644 index 0000000000000..8c297e5a67507 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/logic.rs @@ -0,0 +1,7 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ && abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ || abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ { + // + } +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/math.rs b/src/tools/rustfmt/tests/source/binop-separator-back/math.rs new file mode 100644 index 0000000000000..3af4aad16051e --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/math.rs @@ -0,0 +1,7 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs b/src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs new file mode 100644 index 0000000000000..a8c3b5cdd9b16 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs @@ -0,0 +1,9 @@ +// rustfmt-binop_separator: Back + +fn main() { + match val { + ThisIsA::ReallyLongPatternNameToHelpOverflowTheNextValueOntoTheNextLine | ThisIsA::SecondValueSeparatedByAPipe | ThisIsA::ThirdValueSeparatedByAPipe => { + // + } + } +} diff --git a/src/tools/rustfmt/tests/source/binop-separator-back/range.rs b/src/tools/rustfmt/tests/source/binop-separator-back/range.rs new file mode 100644 index 0000000000000..bdd3de9922b09 --- /dev/null +++ b/src/tools/rustfmt/tests/source/binop-separator-back/range.rs @@ -0,0 +1,7 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs new file mode 100644 index 0000000000000..dec1e00d117b4 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs @@ -0,0 +1,8 @@ +// @generated +// rustfmt-format_generated_files: false + +fn main() +{ + println!("hello, world") + ; +} diff --git a/src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs new file mode 100644 index 0000000000000..a25ddc25a6a44 --- /dev/null +++ b/src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs @@ -0,0 +1,8 @@ +// @generated +// rustfmt-format_generated_files: true + +fn main() +{ + println!("hello, world") + ; +} diff --git a/src/tools/rustfmt/tests/source/hex_literal_lower.rs b/src/tools/rustfmt/tests/source/hex_literal_lower.rs new file mode 100644 index 0000000000000..ce307b3aa521e --- /dev/null +++ b/src/tools/rustfmt/tests/source/hex_literal_lower.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Lower +fn main() { + let h1 = 0xCAFE_5EA7; + let h2 = 0xCAFE_F00Du32; +} diff --git a/src/tools/rustfmt/tests/source/hex_literal_upper.rs b/src/tools/rustfmt/tests/source/hex_literal_upper.rs new file mode 100644 index 0000000000000..b1092ad71ba13 --- /dev/null +++ b/src/tools/rustfmt/tests/source/hex_literal_upper.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Upper +fn main() { + let h1 = 0xCaFE_5ea7; + let h2 = 0xCAFE_F00Du32; +} diff --git a/src/tools/rustfmt/tests/source/impls.rs b/src/tools/rustfmt/tests/source/impls.rs index fb8701989fa19..dcd1f0cd5b09d 100644 --- a/src/tools/rustfmt/tests/source/impls.rs +++ b/src/tools/rustfmt/tests/source/impls.rs @@ -13,6 +13,14 @@ pub impl Foo for Bar { // Comment 3 } +#[inherent] +impl Visible for Bar { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} + pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { fn foo() { "hi" } } diff --git a/src/tools/rustfmt/tests/source/imports_granularity_one.rs b/src/tools/rustfmt/tests/source/imports_granularity_one.rs new file mode 100644 index 0000000000000..c21707df39545 --- /dev/null +++ b/src/tools/rustfmt/tests/source/imports_granularity_one.rs @@ -0,0 +1,60 @@ +// rustfmt-imports_granularity: One + +use b; +use a::ac::{aca, acb}; +use a::{aa::*, ab}; + +use a as x; +use b::ba; +use a::{aa, ab}; + +use a::aa::aaa; +use a::ab::aba as x; +use a::aa::*; + +use a::aa; +use a::ad::ada; +#[cfg(test)] +use a::{ab, ac::aca}; +use b; +#[cfg(test)] +use b::{ + ba, bb, + bc::bca::{bcaa, bcab}, +}; + +pub use a::aa; +pub use a::ae; +use a::{ab, ac, ad}; +use b::ba; +pub use b::{bb, bc::bca}; + +use a::aa::aaa; +use a::ac::{aca, acb}; +use a::{aa::*, ab}; +use b::{ + ba, + bb::{self, bba}, +}; + +use crate::a; +use crate::b::ba; +use c::ca; + +use super::a; +use c::ca; +use super::b::ba; + +use crate::a; +use super::b; +use c::{self, ca}; + +use a::{ + // some comment + aa::{aaa, aab}, + ab, + // another comment + ac::aca, +}; +use b as x; +use a::ad::ada; diff --git a/src/tools/rustfmt/tests/source/issue-3158.rs b/src/tools/rustfmt/tests/source/issue-3158.rs new file mode 100644 index 0000000000000..315073db6af5a --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-3158.rs @@ -0,0 +1,74 @@ +// rustfmt-format_code_in_doc_comments: true + +/// Should format +/// ```rust +/// assert!( false ); +/// ``` +/// +/// Should format +/// ```rust,should_panic +/// assert!( false ); +/// ``` +/// +/// Should format +/// ```rust,should_panic,edition2018 +/// assert!( false ); +/// ``` +/// +/// Should format +/// ```rust , should_panic , edition2018 +/// assert!( false ); +/// ``` +/// +/// Should not format +/// ```ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (not all are rust) +/// ```rust,ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```compile_fail +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```rust,compile_fail +/// assert!( false ); +/// ``` +/// +/// Various unspecified ones that should format +/// ``` +/// assert!( false ); +/// ``` +/// +/// ```, +/// assert!( false ); +/// ``` +/// +/// ```,,,,, +/// assert!( false ); +/// ``` +/// +/// ```,,, rust ,, +/// assert!( false ); +/// ``` +/// +/// Should not format +/// ```,,, rust , ignore, +/// assert!( false ); +/// ``` +/// +/// Few empty ones +/// ``` +/// ``` +/// +/// ```rust +/// ``` +/// +/// ```ignore +/// ``` +fn foo() {} diff --git a/src/tools/rustfmt/tests/source/issue-4530.rs b/src/tools/rustfmt/tests/source/issue-4530.rs new file mode 100644 index 0000000000000..9d2882abb3c1c --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4530.rs @@ -0,0 +1,4 @@ +// rustfmt-version: Two +fn main() { + let [aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccccc, ddddddddddddddddddddddddd] = panic!(); +} diff --git a/src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs new file mode 100644 index 0000000000000..89af5d1239dd0 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs @@ -0,0 +1,4 @@ +info!(//debug + "{}: sending function_code={:04x} data={:04x} crc=0x{:04X} data={:02X?}", + self.name, function_code, data, crc, output_cmd +); diff --git a/src/tools/rustfmt/tests/source/issue-4816/lib.rs b/src/tools/rustfmt/tests/source/issue-4816/lib.rs new file mode 100644 index 0000000000000..43d540c4a5d72 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4816/lib.rs @@ -0,0 +1,10 @@ +#![feature(const_generics_defaults)] +struct Foo; +struct Bar; +struct Lots; +struct NamesRHard; +struct FooBar< + const LessThan100ButClose: usize = {1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1} +>; +struct FooBarrrrrrrr; diff --git a/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs new file mode 100644 index 0000000000000..e55e41bd1a58a --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs @@ -0,0 +1,35 @@ + +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { a: 1_000, b: 1_000, .. } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs new file mode 100644 index 0000000000000..516699fa2b8bc --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs @@ -0,0 +1,43 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs new file mode 100644 index 0000000000000..38fd6f02cf069 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs @@ -0,0 +1,44 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs b/src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs new file mode 100644 index 0000000000000..336378537df38 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs @@ -0,0 +1,35 @@ +// rustfmt-struct_field_align_threshold: 30 +// rustfmt-enum_discrim_align_threshold: 30 +// rustfmt-imports_layout: HorizontalVertical + +#[derive(Default)] +struct InnerStructA { bbbbbbbbb: i32, cccccccc: i32 } + +enum SomeEnumNamedD { + E(InnerStructA), + F { + ggggggggggggggggggggggggg: bool, + h: bool, + } +} + +impl SomeEnumNamedD { + fn f_variant() -> Self { + Self::F { ggggggggggggggggggggggggg: true, h: true } + } +} + +fn main() { + let kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = SomeEnumNamedD::f_variant(); + let something_we_care_about = matches!( + kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk, + SomeEnumNamedD::F { + ggggggggggggggggggggggggg: true, + .. + } + ); + + if something_we_care_about { + println!("Yup it happened"); + } +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs new file mode 100644 index 0000000000000..2c3045dea489e --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs @@ -0,0 +1,10 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { a: i32, b: i32 } + +fn test(x: X) { + let y = matches!(x, X { + a: 1, + .. + }); +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs b/src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs new file mode 100644 index 0000000000000..b8a37f0714ee6 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs @@ -0,0 +1,21 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let y = matches!(x, X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, + .. + }); +} diff --git a/src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs b/src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs new file mode 100644 index 0000000000000..4adfd3b306296 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs @@ -0,0 +1,21 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let y = matches!(x, X { + a: 1_000, b: 1_000, c: 1_000, d: 1_000, e: 1_000, f: 1_000, g: 1_000, h: 1_000, i: 1_000, j: 1_000, .. + }); +} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs new file mode 100644 index 0000000000000..677f873771691 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs @@ -0,0 +1,2 @@ +#[derive(/*Debug, */Clone)] +struct Foo; diff --git a/src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs b/src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs new file mode 100644 index 0000000000000..73921dd173547 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs @@ -0,0 +1,20 @@ +#[derive( +/* ---------- Some really important comment that just had to go inside the derive --------- */ +Debug, Clone, Eq, PartialEq, +)] +struct Foo { + a: i32, + b: T, +} + +#[derive( +/* + Some really important comment that just had to go inside the derive. + Also had to be put over multiple lines +*/ +Debug, Clone, Eq, PartialEq, +)] +struct Bar { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs b/src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs new file mode 100644 index 0000000000000..eb474a723d016 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs @@ -0,0 +1,8 @@ +#[derive( +/* ---------- Some really important comment that just had to go inside the derive --------- */ +Debug, Clone,/* Another comment */Eq, PartialEq, +)] +struct Foo { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/source/issue-5011.rs b/src/tools/rustfmt/tests/source/issue-5011.rs new file mode 100644 index 0000000000000..b48292164e43a --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-5011.rs @@ -0,0 +1,12 @@ +pub(crate) struct ASlash( + // hello + i32 +); + +pub(crate) struct AStar( + /* hello */ + i32 +); + +pub(crate) struct BStar(/* hello */ i32); + diff --git a/src/tools/rustfmt/tests/source/issue_4032.rs b/src/tools/rustfmt/tests/source/issue_4032.rs new file mode 100644 index 0000000000000..11ded074c3455 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4032.rs @@ -0,0 +1,4 @@ +fn a1(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8) {} +fn b1(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8) {} +fn a2(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8) {} +fn b2(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8) {} diff --git a/src/tools/rustfmt/tests/source/issue_4257.rs b/src/tools/rustfmt/tests/source/issue_4257.rs new file mode 100644 index 0000000000000..2b887fadb621c --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4257.rs @@ -0,0 +1,13 @@ +#![feature(generic_associated_types)] +#![allow(incomplete_features)] + +trait Trait { + type Type<'a> where T: 'a; + fn foo(x: &T) -> Self::Type<'_>; +} +impl Trait for () { + type Type<'a> where T: 'a = &'a T; + fn foo(x: &T) -> Self::Type<'_> { + x + } +} diff --git a/src/tools/rustfmt/tests/source/issue_4322.rs b/src/tools/rustfmt/tests/source/issue_4322.rs new file mode 100644 index 0000000000000..b28cc7cdd12fe --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4322.rs @@ -0,0 +1,3 @@ +trait Bar { + type X<'a> where Self: 'a; +} diff --git a/src/tools/rustfmt/tests/source/issue_4579.rs b/src/tools/rustfmt/tests/source/issue_4579.rs new file mode 100644 index 0000000000000..73f345233ba77 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4579.rs @@ -0,0 +1,15 @@ +// rustfmt-hard_tabs: true + +#[macro_export] +macro_rules! main { + () => { + #[spirv(fragment)] + pub fn main_fs( + mut out_color: ::spirv_std::storage_class::Output, + #[spirv(descriptor_set = 1)]iChannelResolution: ::spirv_std::storage_class::UniformConstant< + [::spirv_std::glam::Vec3A; 4], + >, + ) { + } + }; +} diff --git a/src/tools/rustfmt/tests/source/issue_4911.rs b/src/tools/rustfmt/tests/source/issue_4911.rs new file mode 100644 index 0000000000000..21ef6c6c491ac --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4911.rs @@ -0,0 +1,6 @@ +#![feature(generic_associated_types)] +#![feature(min_type_alias_impl_trait)] + +impl SomeTrait for SomeType { + type SomeGAT<'a> where Self: 'a = impl SomeOtherTrait; +} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/issue_4943.rs b/src/tools/rustfmt/tests/source/issue_4943.rs new file mode 100644 index 0000000000000..0793b7b4fe1cc --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4943.rs @@ -0,0 +1,9 @@ +#![feature(generic_associated_types)] + +impl SomeStruct { + fn process(v: T) -> ::R + where Self: GAT = T> + { + SomeStruct::do_something(v) + } +} diff --git a/src/tools/rustfmt/tests/source/issue_4954.rs b/src/tools/rustfmt/tests/source/issue_4954.rs new file mode 100644 index 0000000000000..8011c601b654f --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4954.rs @@ -0,0 +1,5 @@ +trait Foo { + type Arg<'a>; +} + +struct Bar(T) where for<'a> T: Foo = ()>; diff --git a/src/tools/rustfmt/tests/source/issue_4963.rs b/src/tools/rustfmt/tests/source/issue_4963.rs new file mode 100644 index 0000000000000..32e1f6cd41bf6 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue_4963.rs @@ -0,0 +1,5 @@ +mod test { + extern "C" {fn test();} +} + +extern "C" {fn test();} \ No newline at end of file diff --git a/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs b/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs index e9daac13bf96f..baa05b79c1617 100644 --- a/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs +++ b/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs @@ -8,6 +8,14 @@ fn foo() { "line1"; "line2" } + ThisIsA::Guard if true => { + "line1"; + "line2" + } + ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine) if true => { + "line1"; + "line2" + } b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), } diff --git a/src/tools/rustfmt/tests/source/trait.rs b/src/tools/rustfmt/tests/source/trait.rs index 80ee0188a6baa..b6db9e1590d41 100644 --- a/src/tools/rustfmt/tests/source/trait.rs +++ b/src/tools/rustfmt/tests/source/trait.rs @@ -174,3 +174,10 @@ Send + DDDDDDDD + DDDDDDDDD + EEEEEEE; + +trait Visible { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs b/src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs new file mode 100644 index 0000000000000..ce32c05ef703f --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs @@ -0,0 +1,18 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ^ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ & + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ | + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ << + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >> + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/comp.rs b/src/tools/rustfmt/tests/target/binop-separator-back/comp.rs new file mode 100644 index 0000000000000..efd837bcfe389 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/comp.rs @@ -0,0 +1,33 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ < + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ <= + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ > + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ >= + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } + + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ == + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/logic.rs b/src/tools/rustfmt/tests/target/binop-separator-back/logic.rs new file mode 100644 index 0000000000000..5f69fd5f55e4a --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/logic.rs @@ -0,0 +1,10 @@ +// rustfmt-binop_separator: Back + +fn main() { + if abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ && + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ || + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + { + // + } +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/math.rs b/src/tools/rustfmt/tests/target/binop-separator-back/math.rs new file mode 100644 index 0000000000000..7a3f27e733b2c --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/math.rs @@ -0,0 +1,23 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ - + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ * + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ / + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs b/src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs new file mode 100644 index 0000000000000..2e59713526a02 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs @@ -0,0 +1,11 @@ +// rustfmt-binop_separator: Back + +fn main() { + match val { + ThisIsA::ReallyLongPatternNameToHelpOverflowTheNextValueOntoTheNextLine | + ThisIsA::SecondValueSeparatedByAPipe | + ThisIsA::ThirdValueSeparatedByAPipe => { + // + } + } +} diff --git a/src/tools/rustfmt/tests/target/binop-separator-back/range.rs b/src/tools/rustfmt/tests/target/binop-separator-back/range.rs new file mode 100644 index 0000000000000..19e5a81cd9cd1 --- /dev/null +++ b/src/tools/rustfmt/tests/target/binop-separator-back/range.rs @@ -0,0 +1,9 @@ +// rustfmt-binop_separator: Back + +fn main() { + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.. + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; + + let value = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..= + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ; +} diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs new file mode 100644 index 0000000000000..dec1e00d117b4 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs @@ -0,0 +1,8 @@ +// @generated +// rustfmt-format_generated_files: false + +fn main() +{ + println!("hello, world") + ; +} diff --git a/src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs new file mode 100644 index 0000000000000..5fea7e8b34139 --- /dev/null +++ b/src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs @@ -0,0 +1,6 @@ +// @generated +// rustfmt-format_generated_files: true + +fn main() { + println!("hello, world"); +} diff --git a/src/tools/rustfmt/tests/target/hex_literal_lower.rs b/src/tools/rustfmt/tests/target/hex_literal_lower.rs new file mode 100644 index 0000000000000..5c27fded16743 --- /dev/null +++ b/src/tools/rustfmt/tests/target/hex_literal_lower.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Lower +fn main() { + let h1 = 0xcafe_5ea7; + let h2 = 0xcafe_f00du32; +} diff --git a/src/tools/rustfmt/tests/target/hex_literal_preserve.rs b/src/tools/rustfmt/tests/target/hex_literal_preserve.rs new file mode 100644 index 0000000000000..e8774d0bb24eb --- /dev/null +++ b/src/tools/rustfmt/tests/target/hex_literal_preserve.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Preserve +fn main() { + let h1 = 0xcAfE_5Ea7; + let h2 = 0xCaFe_F00du32; +} diff --git a/src/tools/rustfmt/tests/target/hex_literal_upper.rs b/src/tools/rustfmt/tests/target/hex_literal_upper.rs new file mode 100644 index 0000000000000..48bb93d2c1c08 --- /dev/null +++ b/src/tools/rustfmt/tests/target/hex_literal_upper.rs @@ -0,0 +1,5 @@ +// rustfmt-hex_literal_case: Upper +fn main() { + let h1 = 0xCAFE_5EA7; + let h2 = 0xCAFE_F00Du32; +} diff --git a/src/tools/rustfmt/tests/target/impls.rs b/src/tools/rustfmt/tests/target/impls.rs index bf63f924a33b0..99e02990e4177 100644 --- a/src/tools/rustfmt/tests/target/impls.rs +++ b/src/tools/rustfmt/tests/target/impls.rs @@ -21,6 +21,14 @@ pub impl Foo for Bar { // Comment 3 } +#[inherent] +impl Visible for Bar { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} + pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z>, diff --git a/src/tools/rustfmt/tests/target/imports_granularity_one.rs b/src/tools/rustfmt/tests/target/imports_granularity_one.rs new file mode 100644 index 0000000000000..78ec5e7325c50 --- /dev/null +++ b/src/tools/rustfmt/tests/target/imports_granularity_one.rs @@ -0,0 +1,79 @@ +// rustfmt-imports_granularity: One + +use { + a::{ + aa::*, + ab, + ac::{aca, acb}, + }, + b, +}; + +use { + a::{self as x, aa, ab}, + b::ba, +}; + +use a::{ + aa::{aaa, *}, + ab::aba as x, +}; + +#[cfg(test)] +use a::{ab, ac::aca}; +#[cfg(test)] +use b::{ + ba, bb, + bc::bca::{bcaa, bcab}, +}; +use { + a::{aa, ad::ada}, + b, +}; + +pub use { + a::{aa, ae}, + b::{bb, bc::bca}, +}; +use { + a::{ab, ac, ad}, + b::ba, +}; + +use { + a::{ + aa::{aaa, *}, + ab, + ac::{aca, acb}, + }, + b::{ + ba, + bb::{self, bba}, + }, +}; + +use { + crate::{a, b::ba}, + c::ca, +}; + +use { + super::{a, b::ba}, + c::ca, +}; + +use { + super::b, + crate::a, + c::{self, ca}, +}; + +use { + a::{ + aa::{aaa, aab}, + ab, + ac::aca, + ad::ada, + }, + b as x, +}; diff --git a/src/tools/rustfmt/tests/target/issue-3158.rs b/src/tools/rustfmt/tests/target/issue-3158.rs new file mode 100644 index 0000000000000..4bbbdc1d03922 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-3158.rs @@ -0,0 +1,74 @@ +// rustfmt-format_code_in_doc_comments: true + +/// Should format +/// ```rust +/// assert!(false); +/// ``` +/// +/// Should format +/// ```rust,should_panic +/// assert!(false); +/// ``` +/// +/// Should format +/// ```rust,should_panic,edition2018 +/// assert!(false); +/// ``` +/// +/// Should format +/// ```rust , should_panic , edition2018 +/// assert!(false); +/// ``` +/// +/// Should not format +/// ```ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (not all are rust) +/// ```rust,ignore +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```compile_fail +/// assert!( false ); +/// ``` +/// +/// Should not format (rust compile_fail) +/// ```rust,compile_fail +/// assert!( false ); +/// ``` +/// +/// Various unspecified ones that should format +/// ``` +/// assert!(false); +/// ``` +/// +/// ```, +/// assert!(false); +/// ``` +/// +/// ```,,,,, +/// assert!(false); +/// ``` +/// +/// ```,,, rust ,, +/// assert!(false); +/// ``` +/// +/// Should not format +/// ```,,, rust , ignore, +/// assert!( false ); +/// ``` +/// +/// Few empty ones +/// ``` +/// ``` +/// +/// ```rust +/// ``` +/// +/// ```ignore +/// ``` +fn foo() {} diff --git a/src/tools/rustfmt/tests/target/issue-4530.rs b/src/tools/rustfmt/tests/target/issue-4530.rs new file mode 100644 index 0000000000000..296dc559a9343 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4530.rs @@ -0,0 +1,9 @@ +// rustfmt-version: Two +fn main() { + let [ + aaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + cccccccccccccccccccccccccc, + ddddddddddddddddddddddddd, + ] = panic!(); +} diff --git a/src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs new file mode 100644 index 0000000000000..223b89b812d3d --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs @@ -0,0 +1,5 @@ +info!( + //debug + "{}: sending function_code={:04x} data={:04x} crc=0x{:04X} data={:02X?}", + self.name, function_code, data, crc, output_cmd +); diff --git a/src/tools/rustfmt/tests/target/issue-4816/lib.rs b/src/tools/rustfmt/tests/target/issue-4816/lib.rs new file mode 100644 index 0000000000000..246e775e1febc --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4816/lib.rs @@ -0,0 +1,35 @@ +#![feature(const_generics_defaults)] +struct Foo; +struct Bar; +struct Lots< + const N1BlahFooUwU: usize = { 10 + 28 + 1872 / 10 * 3 }, + const N2SecondParamOhmyyy: usize = { N1BlahFooUwU / 2 + 10 * 2 }, +>; +struct NamesRHard; +struct FooBar< + const LessThan100ButClose: usize = { + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + }, +>; +struct FooBarrrrrrrr< + const N: usize = { + 13478234326456456444323871 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + }, +>; diff --git a/src/tools/rustfmt/tests/target/issue-4908-2.rs b/src/tools/rustfmt/tests/target/issue-4908-2.rs new file mode 100644 index 0000000000000..023b323cb2796 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4908-2.rs @@ -0,0 +1,20 @@ +#![feature(more_qualified_paths)] + +fn main() { + // destructure through a qualified path + let ::Assoc { br } = StructStruct { br: 2 }; +} + +struct StructStruct { + br: i8, +} + +struct Foo; + +trait A { + type Assoc; +} + +impl A for Foo { + type Assoc = StructStruct; +} diff --git a/src/tools/rustfmt/tests/target/issue-4908.rs b/src/tools/rustfmt/tests/target/issue-4908.rs new file mode 100644 index 0000000000000..ac5357abe2a18 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4908.rs @@ -0,0 +1,34 @@ +#![feature(more_qualified_paths)] + +mod foo_bar { + pub enum Example { + Example1 {}, + Example2 {}, + } +} + +fn main() { + foo!(crate::foo_bar::Example, Example1); + + let i1 = foo_bar::Example::Example1 {}; + + assert_eq!(i1.foo_example(), 1); + + let i2 = foo_bar::Example::Example2 {}; + + assert_eq!(i2.foo_example(), 2); +} + +#[macro_export] +macro_rules! foo { + ($struct:path, $variant:ident) => { + impl $struct { + pub fn foo_example(&self) -> i32 { + match self { + <$struct>::$variant { .. } => 1, + _ => 2, + } + } + } + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs new file mode 100644 index 0000000000000..072cf2f6674a1 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs @@ -0,0 +1,38 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + a: 1_000, + b: 1_000, + .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs new file mode 100644 index 0000000000000..c7bc7f7296d6b --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs @@ -0,0 +1,44 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, + .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs new file mode 100644 index 0000000000000..69793162519a7 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs @@ -0,0 +1,54 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let d = { + let e = { + let f = { + let g = { + let h = { + let i = { + let j = { + matches!( + x, + X { + a: 1_000, + b: 1_000, + c: 1_000, + d: 1_000, + e: 1_000, + f: 1_000, + g: 1_000, + h: 1_000, + i: 1_000, + j: 1_000, + .. + } + ) + }; + j + }; + i + }; + h + }; + g + }; + f + }; + e + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs b/src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs new file mode 100644 index 0000000000000..2471df84653c9 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs @@ -0,0 +1,41 @@ +// rustfmt-struct_field_align_threshold: 30 +// rustfmt-enum_discrim_align_threshold: 30 +// rustfmt-imports_layout: HorizontalVertical + +#[derive(Default)] +struct InnerStructA { + bbbbbbbbb: i32, + cccccccc: i32, +} + +enum SomeEnumNamedD { + E(InnerStructA), + F { + ggggggggggggggggggggggggg: bool, + h: bool, + }, +} + +impl SomeEnumNamedD { + fn f_variant() -> Self { + Self::F { + ggggggggggggggggggggggggg: true, + h: true, + } + } +} + +fn main() { + let kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = SomeEnumNamedD::f_variant(); + let something_we_care_about = matches!( + kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk, + SomeEnumNamedD::F { + ggggggggggggggggggggggggg: true, + .. + } + ); + + if something_we_care_about { + println!("Yup it happened"); + } +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs new file mode 100644 index 0000000000000..06e18427465c9 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs @@ -0,0 +1,10 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, +} + +fn test(x: X) { + let y = matches!(x, X { a: 1, .. }); +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs b/src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs new file mode 100644 index 0000000000000..ac4674ab5d520 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs @@ -0,0 +1,24 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + really_really_long_field_a: i32, + really_really_really_long_field_b: i32, + really_really_really_really_long_field_c: i32, + really_really_really_really_really_long_field_d: i32, + really_really_really_really_really_really_long_field_e: i32, + f: i32, +} + +fn test(x: X) { + let y = matches!( + x, + X { + really_really_long_field_a: 10, + really_really_really_long_field_b: 10, + really_really_really_really_long_field_c: 10, + really_really_really_really_really_long_field_d: 10, + really_really_really_really_really_really_long_field_e: 10, + .. + } + ); +} diff --git a/src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs b/src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs new file mode 100644 index 0000000000000..96dfe14bf7dd1 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs @@ -0,0 +1,34 @@ +// rustfmt-struct_field_align_threshold: 30 + +struct X { + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, +} + +fn test(x: X) { + let y = matches!( + x, + X { + a: 1_000, + b: 1_000, + c: 1_000, + d: 1_000, + e: 1_000, + f: 1_000, + g: 1_000, + h: 1_000, + i: 1_000, + j: 1_000, + .. + } + ); +} diff --git a/src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs new file mode 100644 index 0000000000000..f0599c5d694b2 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs @@ -0,0 +1,2 @@ +#[derive(/*Debug, */ Clone)] +struct Foo; diff --git a/src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs b/src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs new file mode 100644 index 0000000000000..5fbd9784adc97 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs @@ -0,0 +1,26 @@ +#[derive( + /* ---------- Some really important comment that just had to go inside the derive --------- */ + Debug, + Clone, + Eq, + PartialEq, +)] +struct Foo { + a: i32, + b: T, +} + +#[derive( + /* + Some really important comment that just had to go inside the derive. + Also had to be put over multiple lines + */ + Debug, + Clone, + Eq, + PartialEq, +)] +struct Bar { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs b/src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs new file mode 100644 index 0000000000000..d2924f0d0f2e2 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs @@ -0,0 +1,11 @@ +#[derive( + /* ---------- Some really important comment that just had to go inside the derive --------- */ + Debug, + Clone, + /* Another comment */ Eq, + PartialEq, +)] +struct Foo { + a: i32, + b: T, +} diff --git a/src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs b/src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs new file mode 100644 index 0000000000000..e46ee511084fe --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs @@ -0,0 +1,5 @@ +#[derive(Clone, Debug, Eq, PartialEq)] +struct Foo; + +#[derive(Clone)] +struct Bar; diff --git a/src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs new file mode 100644 index 0000000000000..11cc645fa5356 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs @@ -0,0 +1,9 @@ +#![feature(more_qualified_paths)] +macro_rules! show { + ($ty:ty, $ex:expr) => { + match $ex { + <$ty>::A(_val) => println!("got a"), // formatting should not remove <$ty>:: + <$ty>::B => println!("got b"), + } + }; +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs new file mode 100644 index 0000000000000..55836f4bf52c7 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs @@ -0,0 +1,4 @@ +fn main() { + // the "in" inside the pattern produced invalid syntax + for variable_in_here /* ... */ in 0..1 {} +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs new file mode 100644 index 0000000000000..d83590c6852fb --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs @@ -0,0 +1,3 @@ +fn main() { + for in_in_in_in_in_in_in_in /* ... */ in 0..1 {} +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs new file mode 100644 index 0000000000000..9c800723939bd --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs @@ -0,0 +1,5 @@ +fn main() { + for variable_in_x /* ... */ in 0..1 { + for variable_in_y /* ... */ in 0..1 {} + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs b/src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs new file mode 100644 index 0000000000000..a716d0d3082a5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs @@ -0,0 +1,13 @@ +fn main() { + for variable_in_x /* ... */ in 0..1 { + for variable_in_y /* ... */ in 0..1 { + if false { + + } else if false { + + } else { + + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs b/src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs new file mode 100644 index 0000000000000..41ea46d4cb9b8 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs @@ -0,0 +1,15 @@ +fn main() { + let in_ = false; + + for variable_in_x /* ... */ in 0..1 { + for variable_in_y /* ... */ in 0..1 { + if in_ { + + } else if in_ { + + } else { + + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs new file mode 100644 index 0000000000000..789e54f7e5fb5 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs @@ -0,0 +1,32 @@ +fn main() { + for variable_in_a /* ... */ in 0..1 { + for variable_in_b /* ... */ in 0..1 { + for variable_in_c /* ... */ in 0..1 { + for variable_in_d /* ... */ in 0..1 { + for variable_in_e /* ... */ in 0..1 { + for variable_in_f /* ... */ in 0..1 { + for variable_in_g /* ... */ in 0..1 { + for variable_in_h /* ... */ in 0..1 { + for variable_in_i /* ... */ in 0..1 { + for variable_in_j /* ... */ in 0..1 { + for variable_in_k /* ... */ in 0..1 { + for variable_in_l /* ... */ in 0..1 { + for variable_in_m /* ... */ in 0..1 { + for variable_in_n /* ... */ in 0..1 { + for variable_in_o /* ... */ in 0..1 { + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/src/tools/rustfmt/tests/target/issue-5011.rs b/src/tools/rustfmt/tests/target/issue-5011.rs new file mode 100644 index 0000000000000..9ad4a1929bdbf --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-5011.rs @@ -0,0 +1,8 @@ +pub(crate) struct ASlash( + // hello + i32, +); + +pub(crate) struct AStar(/* hello */ i32); + +pub(crate) struct BStar(/* hello */ i32); diff --git a/src/tools/rustfmt/tests/target/issue_4031.rs b/src/tools/rustfmt/tests/target/issue_4031.rs new file mode 100644 index 0000000000000..065d5395c7e73 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4031.rs @@ -0,0 +1,21 @@ +fn foo() { + with_woff2_glyf_table("tests/fonts/woff2/SFNT-TTF-Composite.woff2", |glyf| { + let actual = glyf + .records + .iter() + .map(|glyph| match glyph { + GlyfRecord::Parsed( + found @ Glyph { + data: GlyphData::Composite { .. }, + .. + }, + ) => Some(found), + _ => None, + }) + .find(|candidate| candidate.is_some()) + .unwrap() + .unwrap(); + + assert_eq!(*actual, expected) + }); +} diff --git a/src/tools/rustfmt/tests/target/issue_4032.rs b/src/tools/rustfmt/tests/target/issue_4032.rs new file mode 100644 index 0000000000000..2e7e624ca6e6d --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4032.rs @@ -0,0 +1,18 @@ +fn a1( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + a: u8, +) { +} +fn b1( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + bb: u8, +) { +} +fn a2( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8, +) { +} +fn b2( + #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] bb: u8, +) { +} diff --git a/src/tools/rustfmt/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs new file mode 100644 index 0000000000000..4a58c3946e12d --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4110.rs @@ -0,0 +1,55 @@ +fn bindings() { + let err = match (place_desc, explanation) { + ( + Some(ref name), + BorrowExplanation::MustBeValidFor { + category: + category @ (ConstraintCategory::Return + | ConstraintCategory::CallArgument + | ConstraintCategory::OpaqueType), + from_closure: false, + ref region_name, + span, + .. + }, + ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self + .report_escaping_closure_capture( + borrow_spans, + borrow_span, + region_name, + category, + span, + &format!("`{}`", name), + ), + ( + ref name, + BorrowExplanation::MustBeValidFor { + category: ConstraintCategory::Assignment, + from_closure: false, + region_name: + RegionName { + source: RegionNameSource::AnonRegionFromUpvar(upvar_span, ref upvar_name), + .. + }, + span, + .. + }, + ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span), + (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( + location, + &name, + &borrow, + drop_span, + borrow_spans, + explanation, + ), + (None, explanation) => self.report_temporary_value_does_not_live_long_enough( + location, + &borrow, + drop_span, + borrow_spans, + proper_span, + explanation, + ), + }; +} diff --git a/src/tools/rustfmt/tests/target/issue_4257.rs b/src/tools/rustfmt/tests/target/issue_4257.rs new file mode 100644 index 0000000000000..1ebaaf2b60018 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4257.rs @@ -0,0 +1,18 @@ +#![feature(generic_associated_types)] +#![allow(incomplete_features)] + +trait Trait { + type Type<'a> + where + T: 'a; + fn foo(x: &T) -> Self::Type<'_>; +} +impl Trait for () { + type Type<'a> + where + T: 'a, + = &'a T; + fn foo(x: &T) -> Self::Type<'_> { + x + } +} diff --git a/src/tools/rustfmt/tests/target/issue_4322.rs b/src/tools/rustfmt/tests/target/issue_4322.rs new file mode 100644 index 0000000000000..0ec0547119f47 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4322.rs @@ -0,0 +1,5 @@ +trait Bar { + type X<'a> + where + Self: 'a; +} diff --git a/src/tools/rustfmt/tests/target/issue_4579.rs b/src/tools/rustfmt/tests/target/issue_4579.rs new file mode 100644 index 0000000000000..7b0a5f3a62e49 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4579.rs @@ -0,0 +1,16 @@ +// rustfmt-hard_tabs: true + +#[macro_export] +macro_rules! main { + () => { + #[spirv(fragment)] + pub fn main_fs( + mut out_color: ::spirv_std::storage_class::Output, + #[spirv(descriptor_set = 1)] + iChannelResolution: ::spirv_std::storage_class::UniformConstant< + [::spirv_std::glam::Vec3A; 4], + >, + ) { + } + }; +} diff --git a/src/tools/rustfmt/tests/target/issue_4911.rs b/src/tools/rustfmt/tests/target/issue_4911.rs new file mode 100644 index 0000000000000..890a62267ce64 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4911.rs @@ -0,0 +1,9 @@ +#![feature(generic_associated_types)] +#![feature(min_type_alias_impl_trait)] + +impl SomeTrait for SomeType { + type SomeGAT<'a> + where + Self: 'a, + = impl SomeOtherTrait; +} diff --git a/src/tools/rustfmt/tests/target/issue_4936.rs b/src/tools/rustfmt/tests/target/issue_4936.rs new file mode 100644 index 0000000000000..c19e505fd03ad --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4936.rs @@ -0,0 +1,10 @@ +#[discard_params_doc] +trait Trait { + fn foo( + &self, + /// some docs + bar: String, + /// another docs + baz: i32, + ); +} diff --git a/src/tools/rustfmt/tests/target/issue_4943.rs b/src/tools/rustfmt/tests/target/issue_4943.rs new file mode 100644 index 0000000000000..318f7ebed6e06 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4943.rs @@ -0,0 +1,10 @@ +#![feature(generic_associated_types)] + +impl SomeStruct { + fn process(v: T) -> ::R + where + Self: GAT = T>, + { + SomeStruct::do_something(v) + } +} diff --git a/src/tools/rustfmt/tests/target/issue_4954.rs b/src/tools/rustfmt/tests/target/issue_4954.rs new file mode 100644 index 0000000000000..aa5e79befe9c8 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4954.rs @@ -0,0 +1,7 @@ +trait Foo { + type Arg<'a>; +} + +struct Bar(T) +where + for<'a> T: Foo = ()>; diff --git a/src/tools/rustfmt/tests/target/issue_4963.rs b/src/tools/rustfmt/tests/target/issue_4963.rs new file mode 100644 index 0000000000000..0c3c13579c13b --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_4963.rs @@ -0,0 +1,9 @@ +mod test { + extern "C" { + fn test(); + } +} + +extern "C" { + fn test(); +} diff --git a/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs b/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs index 44d1f289f8e0f..5ab433a2e6cf6 100644 --- a/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs +++ b/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs @@ -8,6 +8,16 @@ fn foo() { "line1"; "line2" }, + ThisIsA::Guard if true => { + "line1"; + "line2" + }, + ThisIsA::ReallyLongPattern(ThatWillForce::TheGuard, ToWrapOnto::TheFollowingLine) + if true => + { + "line1"; + "line2" + }, b => ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, diff --git a/src/tools/rustfmt/tests/target/trait.rs b/src/tools/rustfmt/tests/target/trait.rs index 620046a71b29b..7f067991b267b 100644 --- a/src/tools/rustfmt/tests/target/trait.rs +++ b/src/tools/rustfmt/tests/target/trait.rs @@ -211,3 +211,10 @@ where + DDDDDDDD + DDDDDDDDD + EEEEEEE; + +trait Visible { + pub const C: i32; + pub type T; + pub fn f(); + pub fn g() {} +} diff --git a/src/tools/rustfmt/triagebot.toml b/src/tools/rustfmt/triagebot.toml new file mode 100644 index 0000000000000..fa0824ac53c0a --- /dev/null +++ b/src/tools/rustfmt/triagebot.toml @@ -0,0 +1 @@ +[assign]