Skip to content

Rollup of 15 pull requests #90118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 133 commits into from
Closed
Changes from all commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
734bfde
Disallow octal zeros in IPv4 addresses
syvb Jul 8, 2021
69de693
Clarify docs on what IPv4 octal addresses are
syvb Jul 9, 2021
b9b97bb
Reject too-long IPs quicker
syvb Jul 9, 2021
a331e5f
Simplify leading zero checks
syvb Jul 11, 2021
ace518d
Add example with a bunch of leading zeos
syvb Jul 11, 2021
d65ab29
Remove unnecessary condition in Barrier::wait()
twetzel59 Jul 24, 2021
e4b8714
Merge commit '4236289b75ee55c78538c749512cdbeea5e1c332' into update-r…
calebcartwright Jul 26, 2021
778f035
ci: remove unnecessary cargo-make install on windows jobs
calebcartwright Jul 27, 2021
e7fa070
fix: make --edition 2021 visible in --help
outloudvi Jul 22, 2021
0b21ea2
Unyeet const param defaults
BoxyUwU Apr 28, 2021
8c52aae
Bump deps
klensy Jun 3, 2021
e9038b8
rfc3052: Remove authors field from Cargo manifests
lf- Jul 27, 2021
8cbee56
ci: functionally delete appveyor
calebcartwright Jul 30, 2021
2323cbc
Auto merge of #87535 - lf-:authors, r=Mark-Simulacrum
bors Aug 2, 2021
fefb542
fix: handle GAT types in impls with self bounds
calebcartwright Aug 7, 2021
5d8eb8d
fix: don't drop drop generic args on assoc ty constraints
calebcartwright Aug 8, 2021
1d6002a
Enable triagebot assignment in rustfmt
nipunn1313 Aug 8, 2021
403d269
Specify maximum IP address length
syvb Aug 10, 2021
64bf8df
Introduce hir::ExprKind::Let - Take 2
c410-f3r Aug 8, 2021
7769ed0
Document private items for rustfmt
jyn514 Jul 14, 2021
e1dac88
Auto merge of #87119 - jyn514:rustfmt-doc-private, r=Mark-Simulacrum
bors Aug 17, 2021
667a2da
Fix stable toggle on gh pages configuration site
ayazhafiz May 31, 2020
6959d03
Show configs from different versions on github pages
ayazhafiz Jun 1, 2020
916c238
fixup! Show configs from different versions on github pages
ayazhafiz Jun 1, 2020
1045c62
Add github-style highlighting for code blocks (#4224)
ayazhafiz Jun 1, 2020
c5f1d96
Adds direct linking using header ids (#4272)
aszenz Jun 23, 2020
31c97ce
Adds query param for version no (#4270)
aszenz Jun 23, 2020
3195d6c
docs: Preserve updated query param content and add config option links
ayazhafiz Jul 3, 2020
bf47fc1
Ensure that doc url hash IDs are scrolled to on page load
ayazhafiz Jul 16, 2020
f5c782f
fixup! Ensure that doc url hash IDs are scrolled to on page load
ayazhafiz Jul 16, 2020
5c7ac69
Warn when rate limit is on docs page
ayazhafiz Jul 16, 2020
3c36a0c
Exluding v0.8.1 and v0.7 from the config dropdown
jdollar Oct 3, 2020
042c2ec
Added Updated default version to Rustfmt docs config
gunadhya Jan 15, 2021
ec86cfd
Fix redirect issue
gunadhya Jan 21, 2021
f787288
Fix for version config option anchor
davidBar-On Mar 3, 2021
25ebc35
Fix more “a”/“an” typos
steffahn Aug 22, 2021
9bc0dbe
Fix typos “an”→“a” and a few different ones that appeared in the same…
steffahn Aug 22, 2021
c8bd550
Add test for visibility on a trait item (currently wrong)
dtolnay Aug 20, 2021
fd6b025
Preserve visibility on trait items inside trait and impl
dtolnay Aug 20, 2021
e81c393
fix: remove wrong reformatting of qualified paths in struct patterns
ashvin021 Aug 25, 2021
076916f
Introduce `~const`
fee1-dead Aug 25, 2021
20ddab3
Fix rustfmt test
fee1-dead Aug 27, 2021
a603756
Temporary fix rustfmt for let-else
camsteffen Jul 25, 2021
ca9b050
Implement `One` option for imports_granularity (#4669)
magurotuna Jan 30, 2021
c71c68c
Add <title> to docs
akiomik Sep 1, 2021
d19f69c
test: add missing source for #4943
cowboy-bebug Aug 30, 2021
33d1368
test: add test for #4257
cowboy-bebug Aug 30, 2021
bfc6046
test: add test for #4954
cowboy-bebug Aug 30, 2021
ae5696a
test: add test for #4322
cowboy-bebug Aug 30, 2021
48b8e45
Detect bare blocks with type ascription that were meant to be a `stru…
estebank Sep 2, 2021
1674eea
Fix #88256, remove duplicated diagnostic
chenyukang Sep 4, 2021
85d6029
`AbstractConst::root`: Always run `subst` when `Node` is `Leaf`
eopb Sep 4, 2021
22c2738
Minor cleanup: make imports more consistent
eopb Sep 4, 2021
6e40618
Remove left over comment
eopb Sep 4, 2021
fc5633f
Make fields on `AbstractConst` private
eopb Sep 4, 2021
b7d9998
Add line that was unintentionally removed
eopb Sep 4, 2021
6271ded
Auto merge of #88493 - chenyukang:fix-duplicated-diagnostic, r=estebank
bors Sep 6, 2021
59063e8
fix: newline width calc in combine w/ comments (#4123)
calebcartwright Apr 16, 2020
a59cac2
fix: use correct spans for params with attrs
calebcartwright Sep 6, 2021
c2f0e99
try to write the parameter on a new line in case the attribute/parame…
scampi Oct 6, 2020
3d8cd57
tests: add files for issue 4579
calebcartwright Sep 6, 2021
57548aa
fix: resolve idempotency issue in extern body elements
calebcartwright Sep 8, 2021
a806883
fix: handle param doc comments for macro scenarios
calebcartwright Sep 8, 2021
b10ab51
rustfmt doc code blocks with multiple comma-separated attributes
nipunn1313 Aug 8, 2021
d647ebf
Revert "Allow formatting `Anonymous{Struct, Union}` declarations"
pnkfelix Sep 8, 2021
e014277
Ignore automatically derived impls of `Clone` and `Debug` in dead cod…
FabianWolff May 21, 2021
127ec9a
Keep a parent LocalDefId in SpanData.
cjgillot Apr 18, 2021
8743472
Auto merge of #84373 - cjgillot:resolve-span, r=michaelwoerister,petr…
bors Sep 11, 2021
67a59f6
opts: rephrase wording for --all and -p
lnicola Nov 8, 2019
d4ffd1e
Support @generated marker to skip code formatting
topecongiro Jul 10, 2020
9d65b7d
feat: upper- or lowercase hexadecimal literals
ArjenL Jul 15, 2021
52e1a52
Rollup merge of #88775 - pnkfelix:revert-anon-union-parsing, r=davidtwco
Manishearth Sep 15, 2021
17cb2b1
feat: add --check flag to cargo fmt (#3890)
calebcartwright Oct 27, 2019
7aa69e5
refactor: use iter workaround for contains() gap
calebcartwright Sep 17, 2021
dd445ab
Trailing comma on match block goes missing when guard is on its own line
ulyssa Sep 15, 2021
9060bc5
Migrate to 2021
Mark-Simulacrum Sep 19, 2021
74df7b3
deps: update cargo_metadata to include 'path'
calebcartwright Sep 20, 2021
7f6229b
tests: restructure and extend cargo-fmt tests
calebcartwright Sep 20, 2021
4b9d637
refactor: simplify local dep lookups
calebcartwright Sep 21, 2021
cb144c3
In Configurations.md demonstrate both cases for noop selections
rukai Sep 10, 2021
a5138b3
Prevent removal of qualified path for tuple struct inside macro
ytmimi Sep 27, 2021
e3203ef
Add tests for binop_separator = Back
ulyssa Sep 20, 2021
f0f449d
Wrap long array and slice patterns.
pcwalton Sep 18, 2021
40f4993
Update derive attibute span to start after opening '('
ytmimi Sep 24, 2021
365a2f8
Add additional test cases for issue 4984
ytmimi Sep 29, 2021
8b58cce
Stabilize match_block_trailing_comma. (#4145)
emilio May 16, 2020
d418057
Prevent structs with ".." from being rewritten with alignment
ytmimi Oct 11, 2021
f7c4a44
Adjust non-empty tuple struct span to start before fields
ytmimi Oct 5, 2021
f2fb3c9
Update connector search in ControlFlow::rewrite_pat_expr for for loops
ytmimi Oct 6, 2021
c9c1932
feat: stabilize disable_all_formatting
calebcartwright Oct 14, 2021
0cff306
ci: fix release asset upload job
calebcartwright Oct 14, 2021
5f4811e
Handle DefinitiveListTactic::SpecialMacro when writing pre-comments
ytmimi Oct 14, 2021
4a37b9c
Avoid overflow in `VecDeque::with_capacity_in()`.
hkratz Oct 18, 2021
93f80bf
Remove comment saying that we don't build debug rustc in CI, since we do
tgnottingham Oct 18, 2021
aefbd40
Add test for debug logging during incremental compilation
tgnottingham Oct 18, 2021
f2a234e
config: add the option to enable LLVM tests
durin42 Oct 18, 2021
1ae5c35
Replace match expression with match! macro
ytmimi Oct 19, 2021
e8b5af1
Upgrade browser-ui-test version to 0.4.5 (it allows to have multi-lin…
GuillaumeGomez Oct 19, 2021
05eb6f3
Cleanup dead code in hir::map::blocks.
cjgillot Oct 19, 2021
99b8c01
Address lcnr review
eopb Oct 19, 2021
6e98688
Replace FnLikeNode by FnKind.
cjgillot Oct 19, 2021
aad48f7
replace format!("") with String::new()
klensy Oct 9, 2021
f3fb821
use array explicitly instead of vec for const content (even if optimi…
klensy Oct 9, 2021
2fc7806
Make `From` impls of NonZero integer const.
lilasta Oct 20, 2021
9231263
Merge branch 'master' into 1.4.38-subtree
calebcartwright Oct 20, 2021
5f79583
chore: bump toolchain, fix conflict
calebcartwright Oct 20, 2021
b9178dc
Merge pull request #5036 from calebcartwright/1.4.38-subtree
calebcartwright Oct 20, 2021
efa8f55
chore: bump version and changelog
calebcartwright Oct 20, 2021
714e904
Merge commit 'efa8f5521d3813cc897ba29ea0ef98c7aef66bb6' into rustfmt-…
calebcartwright Oct 20, 2021
0697f56
update rustfmt
calebcartwright Oct 20, 2021
be30e60
remove duplicate subst
eopb Oct 20, 2021
457f578
Add test for line-number setting
GuillaumeGomez Oct 19, 2021
0aa68a8
Prevent invalid values from existing in Vec::swap_remove
SkiFire13 Oct 20, 2021
50dc319
Add test for duplicated sidebar entries for reexported macro
GuillaumeGomez Oct 20, 2021
69ca324
Add test to ensure that the missing_doc_code_examples is not triggere…
GuillaumeGomez Oct 20, 2021
d3ecb02
ensure cargo-fmt tests are excluded from root workspace
calebcartwright Oct 20, 2021
86b3dd9
stabilize CString::from_vec_with_nul[_unchecked]
CleanCut Sep 26, 2021
39af41e
fix 'since' version number
CleanCut Oct 20, 2021
d03a803
Rollup merge of #86984 - Smittyvb:ipv4-octal-zero, r=m-ou-se
JohnTitor Oct 21, 2021
a2eb20f
Rollup merge of #87440 - twetzel59:fix-barrier-no-op, r=yaahc
JohnTitor Oct 21, 2021
65c70d1
Rollup merge of #88644 - eopb:abstractconst_leaf_subst, r=lcnr
JohnTitor Oct 21, 2021
504d16a
Rollup merge of #89292 - CleanCut:stabilize-cstring_from_vec_with_nul…
JohnTitor Oct 21, 2021
9b5f471
Rollup merge of #90010 - rusticstuff:vecdeque_with_capacity_in_overfl…
JohnTitor Oct 21, 2021
ad8df27
Rollup merge of #90029 - tgnottingham:incr-debug-logging-test, r=Mark…
JohnTitor Oct 21, 2021
6a30dd3
Rollup merge of #90031 - durin42:allow-llvm-tests, r=Mark-Simulacrum
JohnTitor Oct 21, 2021
aadd5d2
Rollup merge of #90048 - GuillaumeGomez:line-number-setting, r=jsha
JohnTitor Oct 21, 2021
2e9d967
Rollup merge of #90071 - cjgillot:no-blocks, r=oli-obk
JohnTitor Oct 21, 2021
558dace
Rollup merge of #90074 - klensy:upvar-all, r=wesleywiser
JohnTitor Oct 21, 2021
3b51106
Rollup merge of #90077 - woppopo:const_nonzero_from, r=oli-obk
JohnTitor Oct 21, 2021
e0963fe
Rollup merge of #90087 - calebcartwright:rustfmt-subtree, r=calebcart…
JohnTitor Oct 21, 2021
248d914
Rollup merge of #90097 - GuillaumeGomez:duplicated-sidebar-entry-reex…
JohnTitor Oct 21, 2021
5300f62
Rollup merge of #90098 - GuillaumeGomez:add-test-foreign-impl-missing…
JohnTitor Oct 21, 2021
0cb360d
Rollup merge of #90099 - SkiFire13:fix-vec-swap-remove, r=dtolnay
JohnTitor Oct 21, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 37 additions & 43 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -265,14 +265,23 @@ 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"
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"
5 changes: 2 additions & 3 deletions compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
@@ -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;
}

27 changes: 27 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -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<FnKind<'hir>> {
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.
8 changes: 8 additions & 0 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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
239 changes: 0 additions & 239 deletions compiler/rustc_middle/src/hir/map/blocks.rs

This file was deleted.

2 changes: 0 additions & 2 deletions compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
@@ -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, _, _), .. })
5 changes: 2 additions & 3 deletions compiler/rustc_mir_build/src/lints.rs
Original file line number Diff line number Diff line change
@@ -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;
}
3 changes: 1 addition & 2 deletions compiler/rustc_mir_transform/src/const_prop.rs
Original file line number Diff line number Diff line change
@@ -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
5 changes: 2 additions & 3 deletions compiler/rustc_mir_transform/src/coverage/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
}

3 changes: 1 addition & 2 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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);
9 changes: 3 additions & 6 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<V::BreakTy> {
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
30 changes: 15 additions & 15 deletions compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
Original file line number Diff line number Diff line change
@@ -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<R>,
) -> ControlFlow<R> {
f(ct)?;
let root = ct.root();
let root = ct.root(tcx);
match root {
Node::Leaf(_) => ControlFlow::CONTINUE,
Node::Binop(_, l, r) => {
@@ -570,27 +574,23 @@ 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,
Err(_) => return true,
}
}

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;
}
15 changes: 7 additions & 8 deletions compiler/rustc_trait_selection/src/traits/object_safety.rs
Original file line number Diff line number Diff line change
@@ -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 {
5 changes: 2 additions & 3 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -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.
8 changes: 4 additions & 4 deletions compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
@@ -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<MigrationDiagnosticInfo>, 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();
6 changes: 6 additions & 0 deletions config.toml.example
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
@@ -543,9 +543,9 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn with_capacity_in(capacity: usize, alloc: A) -> VecDeque<T, A> {
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) }
}
7 changes: 4 additions & 3 deletions library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
@@ -1305,10 +1305,11 @@ impl<T, A: Allocator> Vec<T, A> {
// 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
}
}

5 changes: 3 additions & 2 deletions library/core/src/convert/num.rs
Original file line number Diff line number Diff line change
@@ -390,15 +390,16 @@ 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]
#[inline]
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()))
}
}
}
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
2 changes: 1 addition & 1 deletion library/core/src/num/nonzero.rs
Original file line number Diff line number Diff line change
@@ -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]
2 changes: 1 addition & 1 deletion library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
@@ -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]
11 changes: 7 additions & 4 deletions library/core/tests/nonzero.rs
Original file line number Diff line number Diff line change
@@ -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> = NonZeroU8::new(0);
@@ -215,8 +215,11 @@ fn nonzero_const() {
const ONE: Option<NonZeroU8> = 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]
20 changes: 8 additions & 12 deletions library/std/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
@@ -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<u8>,
@@ -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<u8> {
self.bytes
}
@@ -704,15 +703,14 @@ 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()) },
/// unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
/// );
/// ```
#[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<u8>) -> 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<u8>) -> Result<Self, FromVecWithNulError> {
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 {
2 changes: 1 addition & 1 deletion library/std/src/ffi/mod.rs
Original file line number Diff line number Diff line change
@@ -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};
6 changes: 5 additions & 1 deletion library/std/src/net/ip.rs
Original file line number Diff line number Diff line change
@@ -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::<Ipv4Addr>().is_err()); // all octets are in octal
/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
/// ```
#[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
8 changes: 8 additions & 0 deletions library/std/src/net/ip/tests.rs
Original file line number Diff line number Diff line change
@@ -20,6 +20,14 @@ fn test_from_str_ipv4() {
// no number between dots
let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
assert_eq!(None, none);
// octal
let none: Option<Ipv4Addr> = "255.0.0.01".parse().ok();
assert_eq!(None, none);
// octal zero
let none: Option<Ipv4Addr> = "255.0.0.00".parse().ok();
assert_eq!(None, none);
let none: Option<Ipv4Addr> = "255.0.00.0".parse().ok();
assert_eq!(None, none);
}

#[test]
28 changes: 19 additions & 9 deletions library/std/src/net/parser.rs
Original file line number Diff line number Diff line change
@@ -111,10 +111,12 @@ impl<'a> Parser<'a> {
&mut self,
radix: u32,
max_digits: Option<usize>,
allow_zero_prefix: bool,
) -> Option<T> {
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,15 +232,15 @@ impl<'a> Parser<'a> {
fn read_port(&mut self) -> Option<u16> {
self.read_atomically(|p| {
p.read_given_char(':')?;
p.read_number(10, None)
p.read_number(10, None, true)
})
}

/// Read a `%` followed by a scope ID in base 10.
fn read_scope_id(&mut self) -> Option<u32> {
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<Ipv4Addr, AddrParseError> {
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())
}
}
}

2 changes: 1 addition & 1 deletion library/std/src/sync/barrier.rs
Original file line number Diff line number Diff line change
@@ -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)
5 changes: 5 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
@@ -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<bool>,
release_debuginfo: Option<bool>,
assertions: Option<bool>,
tests: Option<bool>,
plugins: Option<bool>,
ccache: Option<StringOrBool>,
version_check: Option<bool>,
@@ -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);

3 changes: 2 additions & 1 deletion src/bootstrap/native.rs
Original file line number Diff line number Diff line change
@@ -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")
2 changes: 1 addition & 1 deletion src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 \
8 changes: 8 additions & 0 deletions src/test/incremental/auxiliary/rustc-rust-log-aux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// rustc-env:RUSTC_LOG=debug
#[cfg(rpass1)]
pub fn foo() {}

#[cfg(rpass2)]
pub fn foo() {
println!();
}
16 changes: 16 additions & 0 deletions src/test/incremental/rustc-rust-log.rs
Original file line number Diff line number Diff line change
@@ -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!();
}
22 changes: 22 additions & 0 deletions src/test/rustdoc-gui/docblock-code-block-line-number.goml
Original file line number Diff line number Diff line change
@@ -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 `<pre>` elements lists both of them.
assert-text: ("pre.line-number", "1\n2")
5 changes: 5 additions & 0 deletions src/test/rustdoc-gui/sidebar-macro-reexport.goml
Original file line number Diff line number Diff line change
@@ -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)
13 changes: 7 additions & 6 deletions src/test/rustdoc-gui/sidebar.goml
Original file line number Diff line number Diff line change
@@ -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"

8 changes: 8 additions & 0 deletions src/test/rustdoc-gui/src/test_docs/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
9 changes: 9 additions & 0 deletions src/test/rustdoc-ui/doc-without-codeblock.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
2 changes: 1 addition & 1 deletion src/test/rustdoc-ui/doc-without-codeblock.stderr
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ LL | |
LL | | /// Some docs.
LL | |
... |
LL | | pub fn bar() {}
LL | | }
LL | | }
| |_^
|
5 changes: 1 addition & 4 deletions src/test/ui/rustc-rust-log.rs
Original file line number Diff line number Diff line change
@@ -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
29 changes: 15 additions & 14 deletions src/tools/rustfmt/.github/workflows/upload-assets.yml
Original file line number Diff line number Diff line change
@@ -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 }}
3 changes: 0 additions & 3 deletions src/tools/rustfmt/.github/workflows/windows.yml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions src/tools/rustfmt/.gitignore
Original file line number Diff line number Diff line change
@@ -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
67 changes: 67 additions & 0 deletions src/tools/rustfmt/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
372 changes: 93 additions & 279 deletions src/tools/rustfmt/Cargo.lock

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/tools/rustfmt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
70 changes: 65 additions & 5 deletions src/tools/rustfmt/Configurations.md
Original file line number Diff line number Diff line change
@@ -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<Self::Item> {
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.
```

49 changes: 1 addition & 48 deletions src/tools/rustfmt/appveyor.yml
Original file line number Diff line number Diff line change
@@ -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?
210 changes: 165 additions & 45 deletions src/tools/rustfmt/docs/index.html
Original file line number Diff line number Diff line change
@@ -2,9 +2,13 @@
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>Rustfmt</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css">
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue-async-computed@3.8.1"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<style>
@media (max-width: 767px) {
@@ -38,6 +42,15 @@
.searchCondition > div {
margin-right: 30px;
}
.header-link {
position: relative;
}
.header-link:hover::before {
position: absolute;
left: -2em;
padding-right: 0.5em;
content: '\2002\00a7\2002';
}
</style>
</head>
<body>
@@ -59,70 +72,170 @@
<label for="stable">stable: </label>
<input type="checkbox" id="stable" v-model="shouldStable">
</div>
<div>
<label for="viewVersion">version: </label>
<select name="viewVersion" id="viewVersion" v-model="viewVersion">
<option v-for="option in versionOptions" v-bind:value="option">
{{ option }}
</option>
</select>
</div>
</div>
<div v-html="aboutHtml"></div>
<div v-html="configurationAboutHtml"></div>
<div v-html="outputHtml"></div>
</article>
</div>
<script>
const ConfigurationMdUrl = 'https://raw.githubusercontent.com/rust-lang/rustfmt/master/Configurations.md';
const RusfmtTagsUrl = 'https://api.github.com/repos/rust-lang/rustfmt/tags';
const RustfmtLatestUrl = 'https://api.github.com/repos/rust-lang/rustfmt/releases/latest';
const UrlHash = window.location.hash.replace(/^#/, '');
const queryParams = new URLSearchParams(window.location.search);
const searchParam = queryParams.get('search');
const searchTerm = null !== searchParam ? searchParam : '';
const versionParam = queryParams.get('version');
const parseVersionParam = (version) => {
if (version === 'master') return 'master';
if (version.startsWith('v')) return version;
return `v${version}`;
};
const versionNumber = null !== versionParam ? parseVersionParam(versionParam) : 'master';
new Vue({
el: '#app',
data() {
const configurationDescriptions = [];
configurationDescriptions.links = {};
return {
aboutHtml: '',
configurationAboutHtml: '',
searchCondition: UrlHash,
configurationDescriptions,
shouldStable: false
}
data: {
aboutHtml: '',
configurationAboutHtml: '',
configurationDescriptions: [],
searchCondition: searchTerm,
shouldStable: false,
viewVersion: versionNumber,
oldViewVersion: undefined,
versionOptions: ['master'],
scrolledOnce: false,
},
computed: {
outputHtml() {
const ast = this.configurationDescriptions
.filter(({ head, text, stable }) => {
asyncComputed: {
async updateVersion() {
let latest;
try {
latest = (await axios.get(RustfmtLatestUrl)).data;
} catch(err) {
console.log(err);
return;
}
if (versionParam == null) {
this.viewVersion = latest.name;
}
},
async outputHtml() {
if (this.viewVersion !== this.oldViewVersion) {
const ConfigurationMdUrl =
`https://raw.githubusercontent.com/rust-lang/rustfmt/${this.viewVersion}/Configurations.md`;
let res;
try {
res = await axios.get(ConfigurationMdUrl).catch(e => { throw e });
} catch(e) {
this.handleReqFailure(e);
return;
}
const {
about,
configurationAbout,
configurationDescriptions
} = parseMarkdownAst(res.data);
this.aboutHtml = marked.parser(about);
this.configurationAboutHtml = marked.parser(configurationAbout);
this.configurationDescriptions = configurationDescriptions;
this.oldViewVersion = this.viewVersion;
}

if (
text.includes(this.searchCondition) === false &&
head.includes(this.searchCondition) === false
) {
return false;
}
return (this.shouldStable)
? stable === true
: true;
})
.reduce((stack, { value }) => {
return stack.concat(value);
}, []);
const ast = this.configurationDescriptions
.filter(({ head, text, stable }) => {
if (text.includes(this.searchCondition) === false &&
head.includes(this.searchCondition) === false) {
return false;
}
return (this.shouldStable)
? stable === true
: true;
})
.reduce((stack, { value }) => {
return stack.concat(value);
}, []);
ast.links = {};
return marked.parser(ast);

queryParams.set('version', this.viewVersion);
queryParams.set('search', this.searchCondition);
const curUrl = window.location.pathname +
'?' + queryParams.toString() + window.location.hash;
history.pushState(null, '', curUrl);

const renderer = new marked.Renderer();
renderer.heading = function(text, level) {
const id = htmlToId(text);
return `<h${level}>
<a id="${id}" href="#${id}" name="${id}" class="header-link">${text}</a>
</h${level}>`;
};

return marked.parser(ast, {
highlight(code, lang) {
return hljs.highlight(lang ? lang : 'rust', code).value;
},
headerIds: true,
headerPrefix: '',
renderer,
});
}
},
created: async function() {
const res = await axios.get(ConfigurationMdUrl);
const {
about,
configurationAbout,
configurationDescriptions
} = parseMarkdownAst(res.data);
this.aboutHtml = marked.parser(about);
this.configurationAboutHtml = marked.parser(configurationAbout);
this.configurationDescriptions = configurationDescriptions;
let tags;
try {
tags = (await axios.get(RusfmtTagsUrl)).data;
} catch(e) {
this.handleReqFailure(e);
return;
}

const excludedTagVersions = new Set(['v0.7', 'v0.8.1']);

const tagOptions = tags
.map(tag => tag.name)
.filter(tag => tag.startsWith('v') && !excludedTagVersions.has(tag));
this.versionOptions = this.versionOptions.concat(tagOptions);
},
mounted() {
updated() {
if (UrlHash === '') return;
const interval = setInterval(() => {
this.$nextTick(() => {
const target = document.querySelector(`#${UrlHash}`);
if (target != null) {
if (target != null && !this.scrolledOnce) {
target.scrollIntoView(true);
clearInterval(interval);
this.scrolledOnce = true;
}
}, 100);
});
},
methods: {
handleReqFailure(e) {
if (e.response.status === 404) {
this.aboutHtml =
"<p>Failed to get configuration options for this version, please select the version from the dropdown above.</p>";
} else if (
e.response.status === 403 &&
e.response.headers["X-RateLimit-Remaining"] === 0
) {
const resetDate = new Date(
e.response.headers['X-RateLimit-Reset'] * 1000
).toLocaleString();
this.aboutHtml =
`<p>You have hit the GitHub API rate limit; documentation cannot be updated.` +
`<p>The rate limit will be reset at ${resetDate}.</p>`;
} else {
this.aboutHtml =
`<p>Ecountered an error when fetching documentation data:</p>` +
`<pre><code>${e.response.data}</code></pre>` +
`<p>We would appreciate <a href="https://github.com/rust-lang/rustfmt/issues/new?template=bug_report.md">a bug report</a>.` +
`<p>Try refreshing the page.</p>`;
}
}
}
});
const extractDepthOnes = (ast) => {
@@ -155,7 +268,9 @@
head: val[0].text,
value: val,
stable: val.some((elem) => {
return !!elem.text && elem.text.includes("**Stable**: Yes")
return elem.type === "list" &&
!!elem.raw &&
elem.raw.includes("**Stable**: Yes");
}),
text: val.reduce((result, next) => {
return next.text != null
@@ -186,6 +301,11 @@
configurationDescriptions
};
}
function htmlToId(text) {
const tmpl = document.createElement('template');
tmpl.innerHTML = text.trim();
return encodeURIComponent(CSS.escape(tmpl.content.textContent));
}
</script>
</body>
</html>
</html>
2 changes: 1 addition & 1 deletion src/tools/rustfmt/rust-toolchain
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2021-07-23"
channel = "nightly-2021-10-20"
components = ["rustc-dev"]
5 changes: 4 additions & 1 deletion src/tools/rustfmt/src/attr.rs
Original file line number Diff line number Diff line change
@@ -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,
);
2 changes: 1 addition & 1 deletion src/tools/rustfmt/src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -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",
293 changes: 39 additions & 254 deletions src/tools/rustfmt/src/cargo-fmt/main.rs
Original file line number Diff line number Diff line change
@@ -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<String>,

@@ -53,9 +57,13 @@ pub struct Opts {
#[structopt(name = "rustfmt_options", raw(true))]
rustfmt_options: Vec<String>,

/// 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<Target>,
) -> 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<Target>,
visited: &mut BTreeSet<String>,
) -> 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<Target>,
) -> 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<cargo_metadata::Metadata, io::Error> {
fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
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<String> = 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")]
);
}
}
}
80 changes: 80 additions & 0 deletions src/tools/rustfmt/src/cargo-fmt/test/message_format.rs
Original file line number Diff line number Diff line change
@@ -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")]
);
}
137 changes: 137 additions & 0 deletions src/tools/rustfmt/src/cargo-fmt/test/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use super::*;

mod message_format;
mod targets;

#[test]
fn default_options() {
let empty: Vec<String> = 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()
);
}
134 changes: 134 additions & 0 deletions src/tools/rustfmt/src/cargo-fmt/test/targets.rs
Original file line number Diff line number Diff line change
@@ -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");
}
}
}
68 changes: 32 additions & 36 deletions src/tools/rustfmt/src/comment.rs
Original file line number Diff line number Diff line change
@@ -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 <https://doc.rust-lang.org/rustdoc/print.html#attributes>.
/// 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);
9 changes: 7 additions & 2 deletions src/tools/rustfmt/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions src/tools/rustfmt/src/config/options.rs
Original file line number Diff line number Diff line change
@@ -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]
Loading