-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Description
I work on the s2n-quic project. We have Client and Server builders that allow applications to configure the behavior of the library through several "providers":
Server::builder()
.with_connection_id(MyConnectionId)?
.with_limits(MyLimits)?
.with_tls(MyTls)?
.with_io(MyIo)?
.build()?;We noticed that as the number of configured providers increased, the time that rustc spends type checking exponentially increases. I've created a standalone example of this behavior in a gist. Note that it doesn't even need to call different providers; the example calls with_a over and over again with the same type.
The issue seems to be with the use of impl T in each of the with_* functions:
pub fn with_a<T, U>(self, value: T) -> Builder<impl Providers>
where
T: a::Provider,
U: Providers,
Self: a::With<T, Output = U>,If the return type is changed to Builder<U>, the compile time is unchanged in relation to the number of calls.
| impl T | U | |
|---|---|---|
| depth 1 | 0.12s | 0.12s |
| depth 2 | 0.12s | 0.12s |
| depth 3 | 0.13s | 0.12s |
| depth 4 | 0.15s | 0.12s |
| depth 5 | 0.44s | 0.12s |
| depth 6 | 5.45s | 0.12s |
| depth 7 | 1m10s | 0.12s |
Here's a summary from the self-profile:
| Item | Self time | % of total time | Time | Item count |
|---|---|---|---|---|
| evaluate_obligation | 17.58s | 31.904 | 17.58s | 340 |
| check_mod_privacy | 13.71s | 24.876 | 13.71s | 2 |
| typeck | 10.95s | 19.881 | 19.21s | 10 |
| type_op_prove_predicate | 7.05s | 12.803 | 16.38s | 121 |
| mir_borrowck | 4.43s | 8.035 | 22.13s | 10 |
| normalize_projection_ty | 1.32s | 2.387 | 1.32s | 131 |
| self_profile_alloc_query_strings | 14.69ms | 0.027 | 26.63ms | 1 |
My expectation is that impl T would be equivalent to U in the amount of type checking needed. My preference would be to use impl T, as it keeps the display size of the type in the UI minimal.
Let me know if you need any additional details 😃.
Meta
rustc --version --verbose:
rustc 1.63.0 (4b91a6ea7 2022-08-08)
binary: rustc
commit-hash: 4b91a6ea7258a947e59c6522cd5898e7c0a6a88f
commit-date: 2022-08-08
host: x86_64-apple-darwin
release: 1.63.0
LLVM version: 14.0.5
nightly (for the self-profile):
rustc 1.65.0-nightly (0b79f758c 2022-08-18)
binary: rustc
commit-hash: 0b79f758c9aa6646606662a6d623a0752286cd17
commit-date: 2022-08-18
host: x86_64-apple-darwin
release: 1.65.0-nightly
LLVM version: 15.0.0
I also tested this behavior on an old version of rustc (1.35) and compile times were actually worse so there has been some improvement since then.
rustc 1.35.0 (3c235d560 2019-05-20)
binary: rustc
commit-hash: 3c235d5600393dfe6c36eeed34042efad8d4f26e
commit-date: 2019-05-20
host: x86_64-apple-darwin
release: 1.35.0
LLVM version: 8.0