Skip to content

Commit

Permalink
Merge commit '93f0a9a91f58c9b2153868f458402155fb6265bb' into clippy-s…
Browse files Browse the repository at this point in the history
…ubtree-update
  • Loading branch information
flip1995 committed Mar 7, 2024
2 parents 52f8aec + 93f0a9a commit 73f7e79
Show file tree
Hide file tree
Showing 155 changed files with 4,143 additions and 2,430 deletions.
4 changes: 2 additions & 2 deletions src/tools/clippy/.github/driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ diff -u normalized.stderr tests/ui/double_neg.stderr

# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
SYSROOT=$(rustc --print sysroot)
diff -u <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
diff -u <(./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)

echo "fn main() {}" >target/driver_test.rs
# we can't run 2 rustcs on the same file at the same time
CLIPPY=$(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc)
CLIPPY=$(./target/debug/clippy-driver ./target/driver_test.rs --rustc)
RUSTC=$(rustc ./target/driver_test.rs)
diff -u <($CLIPPY) <($RUSTC)

Expand Down
11 changes: 3 additions & 8 deletions src/tools/clippy/.github/workflows/clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ jobs:
run: rustup show active-toolchain

# Run
- name: Set LD_LIBRARY_PATH (Linux)
run: |
SYSROOT=$(rustc --print sysroot)
echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
- name: Build
run: cargo build --tests --features deny-warnings,internal

Expand All @@ -72,6 +67,6 @@ jobs:
working-directory: clippy_dev

- name: Test clippy-driver
run: bash .github/driver.sh
env:
OS: ${{ runner.os }}
run: |
TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
rustup run $TOOLCHAIN bash .github/driver.sh
32 changes: 6 additions & 26 deletions src/tools/clippy/.github/workflows/clippy_bors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
host: i686-unknown-linux-gnu
- os: windows-latest
host: x86_64-pc-windows-msvc
- os: macos-latest
- os: macos-13
host: x86_64-apple-darwin

runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -87,23 +87,6 @@ jobs:
rustup show active-toolchain
# Run
- name: Set LD_LIBRARY_PATH (Linux)
if: runner.os == 'Linux'
run: |
SYSROOT=$(rustc --print sysroot)
echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
- name: Link rustc dylib (MacOS)
if: runner.os == 'macOS'
run: |
SYSROOT=$(rustc --print sysroot)
sudo mkdir -p /usr/local/lib
sudo find "${SYSROOT}/lib" -maxdepth 1 -name '*dylib' -exec ln -s {} /usr/local/lib \;
- name: Set PATH (Windows)
if: runner.os == 'Windows'
run: |
SYSROOT=$(rustc --print sysroot)
echo "$SYSROOT/bin" >> $GITHUB_PATH
- name: Build
run: cargo build --tests --features deny-warnings,internal

Expand Down Expand Up @@ -136,7 +119,9 @@ jobs:
working-directory: clippy_dev

- name: Test clippy-driver
run: bash .github/driver.sh
run: |
TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
rustup run $TOOLCHAIN bash .github/driver.sh
env:
OS: ${{ runner.os }}

Expand Down Expand Up @@ -236,11 +221,6 @@ jobs:
- name: Install toolchain
run: rustup show active-toolchain

- name: Set LD_LIBRARY_PATH
run: |
SYSROOT=$(rustc --print sysroot)
echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
# Download
- name: Download target dir
uses: actions/download-artifact@v3
Expand All @@ -254,8 +234,8 @@ jobs:
# Run
- name: Test ${{ matrix.integration }}
run: |
RUSTUP_TOOLCHAIN="$(rustup show active-toolchain | grep -o -E "nightly-[0-9]{4}-[0-9]{2}-[0-9]{2}")" \
$CARGO_TARGET_DIR/debug/integration --show-output
TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
rustup run $TOOLCHAIN $CARGO_TARGET_DIR/debug/integration --show-output
env:
INTEGRATION: ${{ matrix.integration }}

Expand Down
112 changes: 57 additions & 55 deletions src/tools/clippy/CHANGELOG.md

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions src/tools/clippy/book/src/development/trait_checking.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,53 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
}
```

## Creating Types Programmatically

Traits are often generic over a type parameter, e.g. `Borrow<T>` is generic
over `T`. Rust allows us to implement a trait for a specific type. For example,
we can implement `Borrow<[u8]>` for a hypothetical type `Foo`. Let's suppose
that we would like to find whether our type actually implements `Borrow<[u8]>`.

To do so, we can use the same `implements_trait` function as above, and supply
a type parameter that represents `[u8]`. Since `[u8]` is a specialization of
`[T]`, we can use the [`Ty::new_slice`][new_slice] method to create a type
that represents `[T]` and supply `u8` as a type parameter.
To create a `ty::Ty` programmatically, we rely on `Ty::new_*` methods. These
methods create a `TyKind` and then wrap it in a `Ty` struct. This means we
have access to all the primitive types, such as `Ty::new_char`,
`Ty::new_bool`, `Ty::new_int`, etc. We can also create more complex types,
such as slices, tuples, and references out of these basic building blocks.

For trait checking, it is not enough to create the types, we need to convert
them into [GenericArg]. In rustc, a generic is an entity that the compiler
understands and has three kinds, type, const and lifetime. By calling
`.into()` on a constructed [Ty], we wrap the type into a generic which can
then be used by the query system to decide whether the specialized trait
is implemented.

The following code demonstrates how to do this:

```rust

use rustc_middle::ty::Ty;
use clippy_utils::ty::implements_trait;
use rustc_span::symbol::sym;

let ty = todo!("Get the `Foo` type to check for a trait implementation");
let borrow_id = cx.tcx.get_diagnostic_item(sym::Borrow).unwrap(); // avoid unwrap in real code
let slice_of_bytes_t = Ty::new_slice(cx.tcx, cx.tcx.types.u8);
let generic_param = slice_of_bytes_t.into();
if implements_trait(cx, ty, borrow_id, &[generic_param]) {
todo!("Rest of lint implementation")
}
```

In essence, the [Ty] struct allows us to create types programmatically in a
representation that can be used by the compiler and the query engine. We then
use the `rustc_middle::Ty` of the type we are interested in, and query the
compiler to see if it indeed implements the trait we are interested in.


[DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
[diagnostic_items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
[lang_items]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/struct.LanguageItems.html
Expand All @@ -102,4 +149,7 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
[symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html
[symbol_index]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html
[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
[rust]: https://github.com/rust-lang/rust
[new_slice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.new_slice
[GenericArg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html
16 changes: 16 additions & 0 deletions src/tools/clippy/book/src/development/type_checking.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@ the [`TypeckResults::node_type()`][node_type] method inside of bodies.

> **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs.
## Creating Types programmatically

A common usecase for creating types programmatically is when we want to check if a type implements a trait (see
[Trait Checking](trait_checking.md)).

Here's an example of how to create a `Ty` for a slice of `u8`, i.e. `[u8]`

```rust
use rustc_middle::ty::Ty;
// assume we have access to a LateContext
let ty = Ty::new_slice(cx.tcx, Ty::new_u8());
```

In general, we rely on `Ty::new_*` methods. These methods define the basic building-blocks that the
type-system and trait-system use to define and understand the written code.

## Useful Links

Below are some useful links to further explore the concepts covered
Expand Down
Loading

0 comments on commit 73f7e79

Please sign in to comment.