Skip to content

Commit aeba3c6

Browse files
committed
Auto merge of #136209 - flip1995:clippy-subtree-update, r=Manishearth
Clippy subtree update r? `@Manishearth` Quite a bit late, as I was on vacation and then we had an issue in MacOS CI after the sync.
2 parents bf1b174 + 4288227 commit aeba3c6

File tree

273 files changed

+5679
-795
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

273 files changed

+5679
-795
lines changed

src/tools/clippy/.github/deploy.sh

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ if [[ -n $TAG_NAME ]]; then
4545
git add "$TAG_NAME"
4646
# Update the symlink
4747
git add stable
48+
# Update the index.html file
49+
git add index.html
4850
git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}"
4951
elif [[ $BETA = "true" ]]; then
5052
if git diff --exit-code --quiet -- beta/; then

src/tools/clippy/.github/driver.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ unset CARGO_MANIFEST_DIR
4747

4848
# Run a lint and make sure it produces the expected output. It's also expected to exit with code 1
4949
# FIXME: How to match the clippy invocation in compile-test.rs?
50-
./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/box_default.rs 2>box_default.stderr && exit 1
51-
sed -e "/= help: for/d" box_default.stderr > normalized.stderr
52-
diff -u normalized.stderr tests/ui/box_default.stderr
50+
./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/string_to_string.rs 2>string_to_string.stderr && exit 1
51+
sed -e "/= help: for/d" string_to_string.stderr > normalized.stderr
52+
diff -u normalized.stderr tests/ui/string_to_string.stderr
5353

5454
# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
5555
SYSROOT=$(rustc --print sysroot)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Clippy changelog check
2+
3+
on:
4+
merge_group:
5+
pull_request:
6+
types: [opened, reopened, synchronize, edited]
7+
8+
concurrency:
9+
# For a given workflow, if we push to the same PR, cancel all previous builds on that PR.
10+
# If the push is not attached to a PR, we will cancel all builds on the same branch.
11+
group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}"
12+
cancel-in-progress: true
13+
14+
jobs:
15+
changelog:
16+
runs-on: ubuntu-latest
17+
18+
defaults:
19+
run:
20+
shell: bash
21+
22+
steps:
23+
# Run
24+
- name: Check Changelog
25+
if: ${{ github.event_name == 'pull_request' }}
26+
run: |
27+
body=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR_NUMBER" | \
28+
python -c "import sys, json; print(json.load(sys.stdin)['body'])")
29+
output=$(awk '/^changelog:\s*\S/ && !/changelog: \[.*\]: your change/' <<< "$body" | sed "s/changelog:\s*//g")
30+
if [ -z "$output" ]; then
31+
echo "ERROR: pull request message must contain 'changelog: ...' with your changelog. Please add it."
32+
exit 1
33+
else
34+
echo "changelog: $output"
35+
fi
36+
env:
37+
PYTHONIOENCODING: 'utf-8'
38+
PR_NUMBER: '${{ github.event.number }}'
39+
40+
# We need to have the "conclusion" job also on PR CI, to make it possible
41+
# to add PRs to a merge queue.
42+
conclusion_changelog:
43+
needs: [ changelog ]
44+
# We need to ensure this job does *not* get skipped if its dependencies fail,
45+
# because a skipped job is considered a success by GitHub. So we have to
46+
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
47+
# when the workflow is canceled manually.
48+
#
49+
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
50+
if: ${{ !cancelled() }}
51+
runs-on: ubuntu-latest
52+
steps:
53+
# Manually check the status of all dependencies. `if: failure()` does not work.
54+
- name: Conclusion
55+
run: |
56+
# Print the dependent jobs to see them in the CI log
57+
jq -C <<< '${{ toJson(needs) }}'
58+
# Check if all jobs that we depend on (in the needs array) were successful.
59+
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

src/tools/clippy/.github/workflows/clippy_mq.yml

+1-33
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,7 @@ defaults:
1515
shell: bash
1616

1717
jobs:
18-
changelog:
19-
runs-on: ubuntu-latest
20-
21-
steps:
22-
- name: Checkout
23-
uses: actions/checkout@v4
24-
with:
25-
ref: ${{ github.ref }}
26-
# Unsetting this would make so that any malicious package could get our Github Token
27-
persist-credentials: false
28-
29-
# Run
30-
- name: Check Changelog
31-
run: |
32-
MESSAGE=$(git log --format=%B -n 1)
33-
PR=$(echo "$MESSAGE" | grep -o "#[0-9]*" | head -1 | sed -e 's/^#//')
34-
body=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$PR" | \
35-
python -c "import sys, json; print(json.load(sys.stdin)['body'])")
36-
output=$(grep "^changelog:\s*\S" <<< "$body" | sed "s/changelog:\s*//g") || {
37-
echo "ERROR: PR body must contain 'changelog: ...'"
38-
exit 1
39-
}
40-
if [[ "$output" = "none" ]]; then
41-
echo "WARNING: changelog is 'none'"
42-
else
43-
echo "changelog: $output"
44-
fi
45-
env:
46-
PYTHONIOENCODING: 'utf-8'
4718
base:
48-
needs: changelog
4919
strategy:
5020
matrix:
5121
include:
@@ -119,7 +89,6 @@ jobs:
11989
OS: ${{ runner.os }}
12090

12191
metadata_collection:
122-
needs: changelog
12392
runs-on: ubuntu-latest
12493

12594
steps:
@@ -138,7 +107,6 @@ jobs:
138107
run: cargo collect-metadata
139108

140109
integration_build:
141-
needs: changelog
142110
runs-on: ubuntu-latest
143111

144112
steps:
@@ -228,7 +196,7 @@ jobs:
228196
INTEGRATION: ${{ matrix.integration }}
229197

230198
conclusion:
231-
needs: [ changelog, base, metadata_collection, integration_build, integration ]
199+
needs: [ base, metadata_collection, integration_build, integration ]
232200
# We need to ensure this job does *not* get skipped if its dependencies fail,
233201
# because a skipped job is considered a success by GitHub. So we have to
234202
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run

src/tools/clippy/.github/workflows/lintcheck.yml

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
name: Lintcheck
22

3-
on: pull_request
3+
on:
4+
pull_request:
5+
paths-ignore:
6+
- 'book/**'
7+
- 'util/**'
8+
- 'tests/**'
9+
- '*.md'
410

511
env:
612
RUST_BACKTRACE: 1

src/tools/clippy/.github/workflows/remark.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- name: Install mdbook
2828
run: |
2929
mkdir mdbook
30-
curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.34/mdbook-v0.4.34-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
30+
curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.43/mdbook-v0.4.43-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
3131
echo `pwd`/mdbook >> $GITHUB_PATH
3232
3333
# Run

src/tools/clippy/CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -5533,6 +5533,7 @@ Released 2018-09-13
55335533
[`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
55345534
[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
55355535
[`doc_nested_refdefs`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_nested_refdefs
5536+
[`doc_overindented_list_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_overindented_list_items
55365537
[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
55375538
[`double_ended_iterator_last`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_ended_iterator_last
55385539
[`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use
@@ -5762,11 +5763,13 @@ Released 2018-09-13
57625763
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
57635764
[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back
57645765
[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
5766+
[`manual_ok_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_err
57655767
[`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
57665768
[`manual_pattern_char_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison
57675769
[`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
57685770
[`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns
57695771
[`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid
5772+
[`manual_repeat_n`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_repeat_n
57705773
[`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain
57715774
[`manual_rotate`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rotate
57725775
[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
@@ -5904,6 +5907,7 @@ Released 2018-09-13
59045907
[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
59055908
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
59065909
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
5910+
[`non_std_lazy_statics`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_std_lazy_statics
59075911
[`non_zero_suggestions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_zero_suggestions
59085912
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
59095913
[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
@@ -6063,6 +6067,7 @@ Released 2018-09-13
60636067
[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
60646068
[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref
60656069
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
6070+
[`sliced_string_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#sliced_string_as_bytes
60666071
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
60676072
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
60686073
[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc
@@ -6172,12 +6177,14 @@ Released 2018-09-13
61726177
[`unnecessary_safety_comment`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_comment
61736178
[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc
61746179
[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports
6180+
[`unnecessary_semicolon`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_semicolon
61756181
[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
61766182
[`unnecessary_struct_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_struct_initialization
61776183
[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
61786184
[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
61796185
[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps
61806186
[`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern
6187+
[`unneeded_struct_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_struct_pattern
61816188
[`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern
61826189
[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns
61836190
[`unreachable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreachable
@@ -6216,6 +6223,7 @@ Released 2018-09-13
62166223
[`useless_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
62176224
[`useless_format`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_format
62186225
[`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq
6226+
[`useless_nonzero_new_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_nonzero_new_unchecked
62196227
[`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute
62206228
[`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec
62216229
[`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box

src/tools/clippy/CONTRIBUTING.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ currently. Between writing new lints, fixing issues, reviewing pull requests and
199199
responding to issues there may not always be enough time to stay on top of it
200200
all.
201201

202-
Our highest priority is fixing [crashes][l-crash] and [bugs][l-bug], for example
202+
Our highest priority is fixing [ICEs][I-ICE] and [bugs][C-bug], for example
203203
an ICE in a popular crate that many other crates depend on. We don't
204204
want Clippy to crash on your code and we want it to be as reliable as the
205205
suggestions from Rust compiler errors.
@@ -213,8 +213,8 @@ Or rather: before the sync this should be addressed,
213213
e.g. by removing a lint again, so it doesn't hit beta/stable.
214214

215215
[triage]: https://forge.rust-lang.org/release/triage-procedure.html
216-
[l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash
217-
[l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug
216+
[I-ICE]: https://github.com/rust-lang/rust-clippy/labels/I-ICE
217+
[C-bug]: https://github.com/rust-lang/rust-clippy/labels/C-bug
218218
[p-low]: https://github.com/rust-lang/rust-clippy/labels/P-low
219219
[p-medium]: https://github.com/rust-lang/rust-clippy/labels/P-medium
220220
[p-high]: https://github.com/rust-lang/rust-clippy/labels/P-high

src/tools/clippy/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ license = "MIT OR Apache-2.0"
1010
keywords = ["clippy", "lint", "plugin"]
1111
categories = ["development-tools", "development-tools::cargo-plugins"]
1212
build = "build.rs"
13-
edition = "2021"
13+
edition = "2024"
1414
publish = false
1515

1616
[[bin]]

src/tools/clippy/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ line. (You can swap `clippy::all` with the specific lint category you are target
159159
You can add options to your code to `allow`/`warn`/`deny` Clippy lints:
160160

161161
* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`).
162-
Note that `rustc` has additional [lint groups](https://doc.rust-lang.org/rustc/lints/groups.html).
162+
Note that `rustc` has additional [lint groups](https://doc.rust-lang.org/rustc/lints/groups.html).
163163

164164
* all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![deny(clippy::all)]`,
165-
`#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive
166-
lints prone to false positives.
165+
`#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive
166+
lints prone to false positives.
167167

168168
* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.)
169169

src/tools/clippy/book/book.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ src = "src"
66
title = "Clippy Documentation"
77

88
[rust]
9-
edition = "2018"
9+
edition = "2024"
1010

1111
[output.html]
1212
edit-url-template = "https://github.com/rust-lang/rust-clippy/edit/master/book/{path}"

src/tools/clippy/book/src/development/adding_lints.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,11 @@ This is good, because it makes writing this particular lint less complicated.
299299
We have to make this decision with every new Clippy lint. It boils down to using
300300
either [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass].
301301

302-
In short, the `EarlyLintPass` runs before type checking and
303-
[HIR](https://rustc-dev-guide.rust-lang.org/hir.html) lowering and the `LateLintPass`
304-
has access to type information. Consider using the `LateLintPass` unless you need
305-
something specific from the `EarlyLintPass`.
302+
`EarlyLintPass` runs before type checking and
303+
[HIR](https://rustc-dev-guide.rust-lang.org/hir.html) lowering, while `LateLintPass`
304+
runs after these stages, providing access to type information. The `cargo dev new_lint` command
305+
defaults to the recommended `LateLintPass`, but you can specify `--pass=early` if your lint
306+
only needs AST level analysis.
306307

307308
Since we don't need type information for checking the function name, we used
308309
`--pass=early` when running the new lint automation and all the imports were
@@ -537,7 +538,7 @@ via `Tools -> Clippy` and you should see the generated code in the output below.
537538
If the command was executed successfully, you can copy the code over to where
538539
you are implementing your lint.
539540

540-
[author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55
541+
[author_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=9a12cb60e5c6ad4e3003ac6d5e63cf55
541542

542543
## Print HIR lint
543544

@@ -552,7 +553,7 @@ attribute to expressions you often need to enable
552553
_Clippy_.
553554

554555
[_High-Level Intermediate Representation (HIR)_]: https://rustc-dev-guide.rust-lang.org/hir.html
555-
[print_hir_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf14db3a7f39ca467cd1b86c34b9afb
556+
[print_hir_example]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=daf14db3a7f39ca467cd1b86c34b9afb
556557

557558
## Documentation
558559

src/tools/clippy/book/src/development/common_tools_writing_lints.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,10 @@ functions to deal with macros:
265265
```
266266

267267
[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
268-
[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
268+
[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html
269269
[TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html
270270
[expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty
271271
[LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
272272
[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
273-
[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
273+
[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.pat_ty
274274
[paths]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/paths/index.html

src/tools/clippy/book/src/development/defining_lints.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,10 @@ Untracked files:
139139
```
140140

141141

142-
## The `define_clippy_lints` macro
142+
## The `declare_clippy_lint` macro
143143

144144
After `cargo dev new_lint`, you should see a macro with the name
145-
`define_clippy_lints`. It will be in the same file if you defined a standalone
145+
`declare_clippy_lint`. It will be in the same file if you defined a standalone
146146
lint, and it will be in `mod.rs` if you defined a type-specific lint.
147147

148148
The macro looks something like this:

src/tools/clippy/book/src/development/infrastructure/release.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ git tag rust-1.XX.0 # XX should be exchanged with the correspondin
9696
git push upstream rust-1.XX.0 # `upstream` is the `rust-lang/rust-clippy` remote
9797
```
9898

99-
After this, the release should be available on the Clippy [release page].
99+
After this, the release should be available on the Clippy [tags page].
100100

101-
[release page]: https://github.com/rust-lang/rust-clippy/releases
101+
[tags page]: https://github.com/rust-lang/rust-clippy/tags
102102

103103
## Publish `clippy_utils`
104104

0 commit comments

Comments
 (0)