Update cargo
10 commits in bc89bffa5987d4af8f71011c7557119b39e44a65..4ed7bee47f7dd4416b36fada1909e9a62c546246
2024-06-22 00:36:36 +0000 to 2024-06-25 16:28:22 +0000
- test: omit target-dir name (rust-lang/cargo#14142)
- test: migrate offline, open_namespaces and owner to snapbox (rust-lang/cargo#14138)
- docs: remove stray comment (rust-lang/cargo#14133)
- Change tests to support `rustc` wording changes (rust-lang/cargo#14135)
- deps: dont use tracing-attributes for workspace, use for cargo only (rust-lang/cargo#14122)
- Include vcs_info even if workspace is dirty (rust-lang/cargo#13960)
- test: migrate profile* to snapbox (rust-lang/cargo#14128)
- test: migrate path and paths to snapbox (rust-lang/cargo#14109)
- test: migrate rustflags, rustup and script to snapbox (rust-lang/cargo#14126)
- test: migrate rename_deps, replace, required_features and run to snapbox (rust-lang/cargo#14127)
Rollup of 7 pull requests
Successful merges:
- #126618 (Mark assoc tys live only if the corresponding trait is live)
- #126746 (Deny `use<>` for RPITITs)
- #126868 (not use offset when there is not ends with brace)
- #126884 (Do not ICE when suggesting dereferencing closure arg)
- #126893 (Eliminate the distinction between PREC_POSTFIX and PREC_PAREN precedence level)
- #126915 (Don't suggest awaiting in closure patterns)
- #126943 (De-duplicate all consecutive native libs regardless of their options)
r? `@ghost`
`@rustbot` modify labels: rollup
Tweak `FlatPat::new` to avoid a temporarily-invalid state
It was somewhat confusing that the old constructor would create a `FlatPat` in a (possibly) non-simplified state, and then simplify its contents in-place.
So instead we now create its fields as local variables, perform simplification, and then create the struct afterwards.
This doesn't affect correctness, but is less confusing.
---
I've also included some semi-related comments that I made while trying to navigate this code.
core: VaArgSafe is an unsafe trait
`T: VaArgSafe` is relied on for soundness. Safe impls promise nothing. Therefore this must be an unsafe trait. Slightly pedantic, as only core can impl this, but we *could* choose to unseal the trait. That would allow soundly (but unsafely) implementing this for e.g. a `#[repr(C)] struct` that should be passable by varargs.
Relates to https://github.com/rust-lang/rust/issues/44930
Tweak a confusing comment in `create_match_candidates`
This comment was accurate at the time it was written, but various later changes reshuffled things in ways that caused the existing comment to become confusing.
I've therefore tried to clarify that *these* candidates are 1:1 with match arms, while also warning that that isn't the case in general.
Specify target specific linker for `riscv64gc-gnu` job
In https://github.com/rust-lang/rust/pull/125669 I updated the `riscv64gc-gnu` job to be more in line with other jobs, like the `armhf-gnu` one.
I missed something important, though! Since the `riscv64gc-unknown-linux-gnu` builds go through a cross compiler, invoking `cc` is not correct! That would invoke the `x86_64-unknown-linux-gnu` linker, instead of the `riscv64gc-unknown-linux-gnu` linker.
While developing #125669 I assumed this line would have been sufficient, however it was not:
553a69030e/src/ci/docker/host-x86_64/disabled/riscv64gc-gnu/Dockerfile (L27-L28)
Unfortunately, without the linker set, `cc` is invoked, and the following linker error occurs:
<details>
<summary>Long output</summary>
```
2024-06-21T14:37:54.4786899Z === HAYSTACK ===
2024-06-21T14:37:54.4787240Z error: linking with `cc` failed: exit status: 1
2024-06-21T14:37:54.4787589Z |
2024-06-21T14:37:54.4806781Z = note: LC_ALL="C" PATH="/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/bin:/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/bin:/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" VSLANG="1033" "cc" "/tmp/rustc7Ju6va/symbols.o" "inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o" "inaccessible/tmp/program.dv9uftjrq86w5xa7l2eo7g9l7.rcgu.o" "-Wl,--as-needed" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-make/inaccessible-temp-dir/inaccessible-temp-dir/rmake_out" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libstd-bb9ed017b7d70437.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libpanic_unwind-5b34ef68c22a7b9b.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libobject-4b9224407e296f51.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libmemchr-1eaaa8d74bbe0b36.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libaddr2line-b34292f7086867e9.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libgimli-1927540c5dff6690.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/librustc_demangle-ab493befe3742702.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libstd_detect-41195694489636c4.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libhashbrown-6905da49c8a1542a.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/librustc_std_workspace_alloc-bbc6290f03f92349.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libminiz_oxide-7a4683d4a82cf47c.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libadler-071583516cdbce90.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libunwind-d84b176d2f4c1334.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libcfg_if-92b7de0160f87442.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/liblibc-cff1533ea7c26263.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/liballoc-49e374c13f9e6132.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/librustc_std_workspace_core-9389dcc15b2f7f7b.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libcore-46f0fa14905fdc5c.rlib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib/libcompiler_builtins-20e1af401f90cd1c.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/riscv64gc-unknown-linux-gnu/lib" "-o" "program" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs"
2024-06-21T14:37:54.4823900Z = note: /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4825032Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4826130Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4827200Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4828279Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4829365Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4830474Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4831554Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4833002Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4834116Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: Relocations in generic ELF (EM: 243)
2024-06-21T14:37:54.4835237Z /usr/bin/ld: inaccessible/tmp/program.program.45572bc5f2b14090-cgu.0.rcgu.o: error adding symbols: file in wrong format
2024-06-21T14:37:54.4835971Z collect2: error: ld returned 1 exit status
2024-06-21T14:37:54.4836449Z
2024-06-21T14:37:54.4836584Z
2024-06-21T14:37:54.4836744Z error: aborting due to 1 previous error
2024-06-21T14:37:54.4836983Z
2024-06-21T14:37:54.4836990Z
2024-06-21T14:37:54.4837083Z === NEEDLE ===
2024-06-21T14:37:54.4837518Z failed to find or create the directory specified by `--temps-dir`
2024-06-21T14:37:54.4838250Z thread 'main' panicked at /checkout/tests/run-make/inaccessible-temp-dir/rmake.rs:35:14:
2024-06-21T14:37:54.4838801Z needle was not found in haystack
2024-06-21T14:37:54.4839270Z note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2024-06-21T14:37:54.4840125Z thread 'main' panicked at /checkout/tests/run-make/inaccessible-temp-dir/rmake.rs:27:5:
2024-06-21T14:37:54.4840759Z called `Result::unwrap()` on an `Err` value: Any { .. }
2024-06-21T14:37:54.4841194Z ------------------------------------------
```
</details>
By setting `--set target.riscv64gc-unknown-linux-gnu.linker=riscv64-linux-gnu-gcc` the correct linker is invoked.
## Testing
> [!NOTE]
> `riscv64gc-unknown-linux-gnu` is a [**Tier 2 with Host Tools** platform](https://doc.rust-lang.org/beta/rustc/platform-support.html), all tests may not necessarily pass! This change should only make fix existing broken tests (like `inaccessible-temp-dir`) while introducing no new breakage.
You can test out the job locally:
```sh
mv src/ci/docker/host-x86_64/disabled/riscv64gc-gnu src/ci/docker/host-x86_64/riscv64gc-gnu
DEPLOY=1 ./src/ci/docker/run.sh riscv64gc-gnu
```
Detect unused structs which derived Default
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.
This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using
r? <reviewer name>
-->
Fixes#98871
De-duplicate all consecutive native libs regardless of their options
Address https://github.com/rust-lang/rust/pull/126913#issuecomment-2188184011 by no longer de-duplicating based on the "options" but by only looking at the generated link args, as to avoid consecutive libs that originated from different native-lib with different options (like `raw-dylib` on Windows) but isn't relevant for `--print=native-static-libs`.
r? ``@petrochenkov``
Don't suggest awaiting in closure patterns
Fixes#126903.
For
```rust
async fn do_async() {}
fn main() {
Some(do_async()).map(|()| {});
}
```
the error is now
```rust
error[E0308]: mismatched types
--> src/main.rs:4:27
|
4 | Some(do_async()).map(|()| {});
| ^^
| |
| expected future, found `()`
| expected due to this
|
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
```
Ideally, if `main` were to be `async`, it should be
```rs
error[E0308]: mismatched types
--> src/main.rs:4:27
|
4 | Some(do_async()).map(|()| {});
| ^^
| |
| expected future, found `()`
| expected due to this
|
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
help: consider `await`ing on the `Future`
|
4 | Some(do_async().await).map(|()| {});
| ++++++
```
However, this would mean `FnCtx::check_pat_top` would have to be called with an `origin_expr` in `rustc_hir_typeck::check::check_fn`, and that expr would have to be somehow plumbed through `FnCtxt::check_expr_closure` and closure signature deduction. I'm willing to work on the plumbing but unsure how to start.
Eliminate the distinction between PREC_POSTFIX and PREC_PAREN precedence level
I have been tangling with precedence as part of porting some pretty-printer improvements from syn back to rustc (related to parenthesization of closures, returns, and breaks by the AST pretty-printer).
As far as I have been able to tell, there is no difference between the 2 different precedence levels that rustc identifies as `PREC_POSTFIX` (field access, square bracket index, question mark, method call) and `PREC_PAREN` (loops, if, paths, literals).
There are a bunch of places that look at either `prec < PREC_POSTFIX` or `prec >= PREC_POSTFIX`. But there is nothing that needs to distinguish PREC_POSTFIX and PREC_PAREN from one another.
d49994b060/compiler/rustc_ast/src/util/parser.rs (L236-L237)d49994b060/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs (L2829)d49994b060/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs (L1290)
In the interest of eliminating a distinction without a difference, this PR collapses these 2 levels down to 1.
There is exactly 1 case where an expression with PREC_POSTFIX precedence needs to be parenthesized in a location that an expression with PREC_PAREN would not, and that's when the receiver of ExprKind::MethodCall is ExprKind::Field. `x.f()` means a different thing than `(x.f)()`. But this does not justify having separate precedence levels because this special case in the grammar is not governed by precedence. Field access does not have "lower precedence than" method call syntax — you can tell because if it did, then `x.f[0].f()` wouldn't be able to have its unparenthesized field access in the receiver of a method call. Because this Field/MethodCall special case is not governed by precedence, it already requires special handling and is not affected by eliminating the PREC_POSTFIX precedence level.
d49994b060/compiler/rustc_ast_pretty/src/pprust/state/expr.rs (L217-L221)
Do not ICE when suggesting dereferencing closure arg
Account for `for` lifetimes when constructing closure to see if dereferencing the return value would be valid.
Fix#125634, fix#124563.
Deny `use<>` for RPITITs
Precise capturing `use<>` syntax is currently a no-op on RPITITs, since GATs have no variance, so all captured lifetimes are captured invariantly.
We don't currently *need* to support `use<>` on RPITITs, since `use<>` is initially intended for migrating RPIT *overcaptures* from edition 2021->2024, but since RPITITs currently capture all in-scope lifetimes, we'll never need to write `use<>` on an RPITIT.
Eventually, though, it would be desirable to support precise capturing on RPITITs, since RPITITs overcapturing by default can be annoying to some folks. But let's separate that (which will likely require some delicate types team work for adding variances to GATs and adjusting the refinement rules) from the stabilization of the feature for edition 2024.
r? oli-obk cc ``@traviscross``
Tracking:
- https://github.com/rust-lang/rust/issues/123432
ast: Standardize visiting order for attributes and node IDs
This should only affect `macro_rules` scopes and order of diagnostics.
Also add a deprecation lint for `macro_rules` called outside of their scope, like in https://github.com/rust-lang/rust/issues/124535.
Various refactorings to rustc_interface
This should make it easier to move the driver interface away from queries in the future. Many custom drivers call queries like `queries.global_ctxt()` before they are supposed to be called, breaking some things like certain `--print` and `-Zunpretty` options, `-Zparse-only` and emitting the dep info at the wrong point in time. They are also not actually necessary at all. Passing around the query output manually would avoid recomputation too and would be just as easy. Removing driver queries would also reduce the amount of global mutable state of the compiler. I'm not removing driver queries in this PR to avoid breaking the aforementioned custom drivers.
It was somewhat confusing that the old constructor would create a `FlatPat` in
a (possibly) non-simplified state, and then simplify its contents in-place.
So instead we now create its fields as local variables, perform simplification,
and then create the struct afterwards.
This doesn't affect correctness, but is less confusing.
transmute size check: properly account for alignment
Fixes another place where ZST alignment was ignored when checking whether something is a newtype. I wonder how many more of these there are...
Fixes https://github.com/rust-lang/rust/issues/101084
Allow constraining opaque types during various unsizing casts
allows unsizing of tuples, arrays and Adts to constraint opaque types in their generic parameters to concrete types on either side of the unsizing cast.
Also allows constraining opaque types during trait object casts that only differ in auto traits or lifetimes.
cc #116652
`T: VaArgSafe` is relied on for soundness. Safe impls promise nothing.
Therefore this must be an unsafe trait. Slightly pedantic, as
only core can impl this, but we could choose to unseal the trait.
That would allow soundly (but unsafely) implementing this for e.g.
a `#[repr(C)] struct` that should be passable by varargs.
Add `SliceLike` to `rustc_type_ir`, use it in the generic solver code (+ some other changes)
First, we split out `TraitRef::new_from_args` which takes *just* `ty::GenericArgsRef` from `TraitRef::new` which takes `impl IntoIterator<Item: Into<GenericArg>>`. I will explain in a minute why.
Second, we introduce `SliceLike`, which allows us to be generic over `List<T>` and `[T]`. This trait has an `as_slice()` and `into_iter()` method, and some other convenience functions. However, importantly, since types like `I::GenericArgs` now implement `SliceLike` rather than `IntoIter<Item = I::GenericArg>`, we can't use `TraitRef::new` on this directly. That's where `new_from_args` comes in.
Finally, we adjust all the code to use these slice operators. Some things get simpler, some things get a bit more annoying since we need to use `as_slice()` in a few places. 🤷
r? lcnr
Rollup of 11 pull requests
Successful merges:
- #124460 (Show notice about "never used" of Debug for enum)
- #124712 (Deprecate no-op codegen option `-Cinline-threshold=...`)
- #125082 (Remove `MaybeUninit::uninit_array()` and replace it with inline const blocks.)
- #125575 (SmartPointer derive-macro)
- #126413 (compiletest: make the crash test error message abit more informative)
- #126673 (Ensure we don't accidentally succeed when we want to report an error)
- #126682 (coverage: Overhaul validation of the `#[coverage(..)]` attribute)
- #126899 (Suggest inline const blocks for array initialization)
- #126904 (Small fixme in core now that NonZero is generic)
- #126909 (add `@kobzol` to bootstrap team for triagebot)
- #126911 (Split the lifetimes of `MirBorrowckCtxt`)
r? `@ghost`
`@rustbot` modify labels: rollup
Split the lifetimes of `MirBorrowckCtxt`
These lifetimes are sometimes too general and will link things together that are independent. These are a blocker for actually finishing tracking more state (e.g. error tainting) in the diagnostic context handle, and I'd rather land it in its own PR instead of together with functional changes.
Also changes a bunch of named lifetimes to `'_` where they were irrelevant
follow-up to https://github.com/rust-lang/rust/pull/126623
coverage: Overhaul validation of the `#[coverage(..)]` attribute
This PR makes sweeping changes to how the (currently-unstable) coverage attribute is validated:
- Multiple coverage attributes on the same item/expression are now treated as an error.
- The attribute must always be `#[coverage(off)]` or `#[coverage(on)]`, and the error messages for this are more consistent.
- A trailing comma is still allowed after off/on, since that's part of the normal attribute syntax.
- Some places that silently ignored a coverage attribute now produce an error instead.
- These cases were all clearly bugs.
- Some places that ignored a coverage attribute (with a warning) now produce an error instead.
- These were originally added as lints, but I don't think it makes much sense to knowingly allow new attributes to be used in meaningless places.
- Some of these errors might soon disappear, if it's easy to extend recursive coverage attributes to things like modules and impl blocks.
---
One of the goals of this PR is to lay a more solid foundation for making the coverage attribute recursive, so that it applies to all nested functions/closures instead of just the one it is directly attached to.
Fixes#126658.
This PR incorporates #126659, which adds more tests for validation of the coverage attribute.
`@rustbot` label +A-code-coverage
Ensure we don't accidentally succeed when we want to report an error
This also changes the `DefiningOpaqueTypes::No` to `Yes` without adding tests, as it is solely run on the error path to improve diagnostics. I was unable to provide a test that changes diagnostics, as all the tests I came up with ended up successfully constraining the opaque type and thus succeeding the coercion.
r? ```@compiler-errors```
cc https://github.com/rust-lang/rust/issues/116652
SmartPointer derive-macro
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.
This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using
r? <reviewer name>
-->
Possibly replacing #123472 for continued upkeep of the proposal rust-lang/rfcs#3621 and implementation of the tracking issue #123430.
cc `@Darksonn` `@wedsonaf`
Remove `MaybeUninit::uninit_array()` and replace it with inline const blocks.
\[This PR originally contained the changes in #125995 too. See edit history for the original PR description.]
The documentation of `MaybeUninit::uninit_array()` says:
> Note: in a future Rust version this method may become unnecessary when Rust allows [inline const expressions](https://github.com/rust-lang/rust/issues/76001). The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`.
The PR adding it also said: <https://github.com/rust-lang/rust/pull/65580#issuecomment-544200681>
> if it’s stabilized soon enough maybe it’s not worth having a standard library method that will be replaceable with `let buffer = [MaybeUninit::<T>::uninit(); $N];`
That time has come to pass — inline const expressions are stable — so `MaybeUninit::uninit_array()` is now unnecessary. The only remaining question is whether it is an important enough *convenience* to keep it around.
I believe it is net good to remove this function, on the principle that it is better to compose two orthogonal features (`MaybeUninit` and array construction) than to have a specific function for the specific combination, now that that is possible.