| author | bors <bors@rust-lang.org> 2026-01-27 06:37:15 UTC |
| committer | bors <bors@rust-lang.org> 2026-01-27 06:37:15 UTC |
| log | 78df2f92de1da3601d967dc8beb9f9cea267e45f |
| tree | f968b6ab4870faf534b672347078b7722a3733cf |
| parent | ebf13cca58b551b83133d4895e123f7d1e795111 |
| parent | 6ec16a409905d07f773575c9ec7dad6d776e4e33 |
Rollup of 5 pull requests
Successful merges:
- rust-lang/rust#151692 (Try to reduce rustdoc GUI tests flakyness)
- rust-lang/rust#147436 (slice/ascii: Optimize `eq_ignore_ascii_case` with auto-vectorization)
- rust-lang/rust#151390 (Reintroduce `QueryStackFrame` split.)
- rust-lang/rust#151097 (Use an associated type default for `Key::Cache`.)
- rust-lang/rust#151702 (Omit standard copyright notice)29 files changed, 489 insertions(+), 443 deletions(-)
REUSE.toml+1-1| ... | ... | @@ -53,7 +53,7 @@ path = [ |
| 53 | 53 | ] |
| 54 | 54 | precedence = "override" |
| 55 | 55 | SPDX-FileCopyrightText = "The Rust Project Developers (see https://thanks.rust-lang.org)" |
| 56 | SPDX-License-Identifier = "MIT or Apache-2.0" | |
| 56 | SPDX-License-Identifier = "MIT OR Apache-2.0" | |
| 57 | 57 | |
| 58 | 58 | [[annotations]] |
| 59 | 59 | path = "compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp" |
compiler/rustc_codegen_gcc/example/alloc_system.rs-3| ... | ... | @@ -1,6 +1,3 @@ |
| 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 | |
| 2 | // SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org) | |
| 3 | ||
| 4 | 1 | #![no_std] |
| 5 | 2 | #![feature(allocator_api, rustc_private)] |
| 6 | 3 |
compiler/rustc_middle/src/query/keys.rs+4-278| ... | ... | @@ -3,8 +3,8 @@ |
| 3 | 3 | use std::ffi::OsStr; |
| 4 | 4 | |
| 5 | 5 | use rustc_ast::tokenstream::TokenStream; |
| 6 | use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; | |
| 7 | use rustc_hir::hir_id::{HirId, OwnerId}; | |
| 6 | use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId}; | |
| 7 | use rustc_hir::hir_id::OwnerId; | |
| 8 | 8 | use rustc_query_system::dep_graph::DepNodeIndex; |
| 9 | 9 | use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; |
| 10 | 10 | use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol}; |
| ... | ... | @@ -12,7 +12,7 @@ use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol}; |
| 12 | 12 | use crate::infer::canonical::CanonicalQueryInput; |
| 13 | 13 | use crate::mir::mono::CollectionMode; |
| 14 | 14 | use crate::ty::fast_reject::SimplifiedType; |
| 15 | use crate::ty::layout::{TyAndLayout, ValidityRequirement}; | |
| 15 | use crate::ty::layout::ValidityRequirement; | |
| 16 | 16 | use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt}; |
| 17 | 17 | use crate::{mir, traits}; |
| 18 | 18 | |
| ... | ... | @@ -29,15 +29,7 @@ pub trait Key: Sized { |
| 29 | 29 | /// constraint is not enforced here. |
| 30 | 30 | /// |
| 31 | 31 | /// [`QueryCache`]: rustc_query_system::query::QueryCache |
| 32 | // N.B. Most of the keys down below have `type Cache<V> = DefaultCache<Self, V>;`, | |
| 33 | // it would be reasonable to use associated type defaults, to remove the duplication... | |
| 34 | // | |
| 35 | // ...But r-a doesn't support them yet and using a default here causes r-a to not infer | |
| 36 | // return types of queries which is very annoying. Thus, until r-a support associated | |
| 37 | // type defaults, please restrain from using them here <3 | |
| 38 | // | |
| 39 | // r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693> | |
| 40 | type Cache<V>; | |
| 32 | type Cache<V> = DefaultCache<Self, V>; | |
| 41 | 33 | |
| 42 | 34 | /// In the event that a cycle occurs, if no explicit span has been |
| 43 | 35 | /// given for a query with key `self`, what span should we use? |
| ... | ... | @@ -72,49 +64,30 @@ impl Key for () { |
| 72 | 64 | } |
| 73 | 65 | |
| 74 | 66 | impl<'tcx> Key for ty::InstanceKind<'tcx> { |
| 75 | type Cache<V> = DefaultCache<Self, V>; | |
| 76 | ||
| 77 | 67 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 78 | 68 | tcx.def_span(self.def_id()) |
| 79 | 69 | } |
| 80 | 70 | } |
| 81 | 71 | |
| 82 | impl<'tcx> AsLocalKey for ty::InstanceKind<'tcx> { | |
| 83 | type LocalKey = Self; | |
| 84 | ||
| 85 | #[inline(always)] | |
| 86 | fn as_local_key(&self) -> Option<Self::LocalKey> { | |
| 87 | self.def_id().is_local().then(|| *self) | |
| 88 | } | |
| 89 | } | |
| 90 | ||
| 91 | 72 | impl<'tcx> Key for ty::Instance<'tcx> { |
| 92 | type Cache<V> = DefaultCache<Self, V>; | |
| 93 | ||
| 94 | 73 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 95 | 74 | tcx.def_span(self.def_id()) |
| 96 | 75 | } |
| 97 | 76 | } |
| 98 | 77 | |
| 99 | 78 | impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { |
| 100 | type Cache<V> = DefaultCache<Self, V>; | |
| 101 | ||
| 102 | 79 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 103 | 80 | self.instance.default_span(tcx) |
| 104 | 81 | } |
| 105 | 82 | } |
| 106 | 83 | |
| 107 | 84 | impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) { |
| 108 | type Cache<V> = DefaultCache<Self, V>; | |
| 109 | ||
| 110 | 85 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 111 | 86 | DUMMY_SP |
| 112 | 87 | } |
| 113 | 88 | } |
| 114 | 89 | |
| 115 | 90 | impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { |
| 116 | type Cache<V> = DefaultCache<Self, V>; | |
| 117 | ||
| 118 | 91 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 119 | 92 | DUMMY_SP |
| 120 | 93 | } |
| ... | ... | @@ -184,8 +157,6 @@ impl AsLocalKey for DefId { |
| 184 | 157 | } |
| 185 | 158 | |
| 186 | 159 | impl Key for LocalModDefId { |
| 187 | type Cache<V> = DefaultCache<Self, V>; | |
| 188 | ||
| 189 | 160 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 190 | 161 | tcx.def_span(*self) |
| 191 | 162 | } |
| ... | ... | @@ -196,79 +167,19 @@ impl Key for LocalModDefId { |
| 196 | 167 | } |
| 197 | 168 | } |
| 198 | 169 | |
| 199 | impl Key for ModDefId { | |
| 200 | type Cache<V> = DefaultCache<Self, V>; | |
| 201 | ||
| 202 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 203 | tcx.def_span(*self) | |
| 204 | } | |
| 205 | ||
| 206 | #[inline(always)] | |
| 207 | fn key_as_def_id(&self) -> Option<DefId> { | |
| 208 | Some(self.to_def_id()) | |
| 209 | } | |
| 210 | } | |
| 211 | ||
| 212 | impl AsLocalKey for ModDefId { | |
| 213 | type LocalKey = LocalModDefId; | |
| 214 | ||
| 215 | #[inline(always)] | |
| 216 | fn as_local_key(&self) -> Option<Self::LocalKey> { | |
| 217 | self.as_local() | |
| 218 | } | |
| 219 | } | |
| 220 | ||
| 221 | 170 | impl Key for SimplifiedType { |
| 222 | type Cache<V> = DefaultCache<Self, V>; | |
| 223 | ||
| 224 | 171 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 225 | 172 | DUMMY_SP |
| 226 | 173 | } |
| 227 | 174 | } |
| 228 | 175 | |
| 229 | 176 | impl Key for (DefId, DefId) { |
| 230 | type Cache<V> = DefaultCache<Self, V>; | |
| 231 | ||
| 232 | 177 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 233 | 178 | self.1.default_span(tcx) |
| 234 | 179 | } |
| 235 | 180 | } |
| 236 | 181 | |
| 237 | impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) { | |
| 238 | type Cache<V> = DefaultCache<Self, V>; | |
| 239 | ||
| 240 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 241 | self.0.default_span(tcx) | |
| 242 | } | |
| 243 | } | |
| 244 | ||
| 245 | impl Key for (DefId, LocalDefId) { | |
| 246 | type Cache<V> = DefaultCache<Self, V>; | |
| 247 | ||
| 248 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 249 | self.1.default_span(tcx) | |
| 250 | } | |
| 251 | } | |
| 252 | ||
| 253 | impl Key for (LocalDefId, DefId) { | |
| 254 | type Cache<V> = DefaultCache<Self, V>; | |
| 255 | ||
| 256 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 257 | self.0.default_span(tcx) | |
| 258 | } | |
| 259 | } | |
| 260 | ||
| 261 | impl Key for (LocalDefId, LocalDefId) { | |
| 262 | type Cache<V> = DefaultCache<Self, V>; | |
| 263 | ||
| 264 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 265 | self.0.default_span(tcx) | |
| 266 | } | |
| 267 | } | |
| 268 | ||
| 269 | 182 | impl Key for (DefId, Ident) { |
| 270 | type Cache<V> = DefaultCache<Self, V>; | |
| 271 | ||
| 272 | 183 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 273 | 184 | tcx.def_span(self.0) |
| 274 | 185 | } |
| ... | ... | @@ -280,16 +191,12 @@ impl Key for (DefId, Ident) { |
| 280 | 191 | } |
| 281 | 192 | |
| 282 | 193 | impl Key for (LocalDefId, LocalDefId, Ident) { |
| 283 | type Cache<V> = DefaultCache<Self, V>; | |
| 284 | ||
| 285 | 194 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 286 | 195 | self.1.default_span(tcx) |
| 287 | 196 | } |
| 288 | 197 | } |
| 289 | 198 | |
| 290 | 199 | impl Key for (CrateNum, DefId) { |
| 291 | type Cache<V> = DefaultCache<Self, V>; | |
| 292 | ||
| 293 | 200 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 294 | 201 | self.1.default_span(tcx) |
| 295 | 202 | } |
| ... | ... | @@ -305,8 +212,6 @@ impl AsLocalKey for (CrateNum, DefId) { |
| 305 | 212 | } |
| 306 | 213 | |
| 307 | 214 | impl Key for (CrateNum, SimplifiedType) { |
| 308 | type Cache<V> = DefaultCache<Self, V>; | |
| 309 | ||
| 310 | 215 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 311 | 216 | DUMMY_SP |
| 312 | 217 | } |
| ... | ... | @@ -321,121 +226,37 @@ impl AsLocalKey for (CrateNum, SimplifiedType) { |
| 321 | 226 | } |
| 322 | 227 | } |
| 323 | 228 | |
| 324 | impl Key for (DefId, SimplifiedType) { | |
| 325 | type Cache<V> = DefaultCache<Self, V>; | |
| 326 | ||
| 327 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 328 | self.0.default_span(tcx) | |
| 329 | } | |
| 330 | } | |
| 331 | ||
| 332 | 229 | impl Key for (DefId, ty::SizedTraitKind) { |
| 333 | type Cache<V> = DefaultCache<Self, V>; | |
| 334 | ||
| 335 | 230 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 336 | 231 | self.0.default_span(tcx) |
| 337 | 232 | } |
| 338 | 233 | } |
| 339 | 234 | |
| 340 | 235 | impl<'tcx> Key for GenericArgsRef<'tcx> { |
| 341 | type Cache<V> = DefaultCache<Self, V>; | |
| 342 | ||
| 343 | 236 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 344 | 237 | DUMMY_SP |
| 345 | 238 | } |
| 346 | 239 | } |
| 347 | 240 | |
| 348 | 241 | impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) { |
| 349 | type Cache<V> = DefaultCache<Self, V>; | |
| 350 | ||
| 351 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 352 | self.0.default_span(tcx) | |
| 353 | } | |
| 354 | } | |
| 355 | ||
| 356 | impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) { | |
| 357 | type Cache<V> = DefaultCache<Self, V>; | |
| 358 | ||
| 359 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 360 | (self.0).def.default_span(tcx) | |
| 361 | } | |
| 362 | } | |
| 363 | ||
| 364 | impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) { | |
| 365 | type Cache<V> = DefaultCache<Self, V>; | |
| 366 | ||
| 367 | 242 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 368 | 243 | self.0.default_span(tcx) |
| 369 | 244 | } |
| 370 | 245 | } |
| 371 | 246 | |
| 372 | impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) { | |
| 373 | type Cache<V> = DefaultCache<Self, V>; | |
| 374 | ||
| 375 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 376 | tcx.def_span(self.1.def_id) | |
| 377 | } | |
| 378 | } | |
| 379 | ||
| 380 | impl<'tcx> Key for ty::ParamEnvAnd<'tcx, Ty<'tcx>> { | |
| 381 | type Cache<V> = DefaultCache<Self, V>; | |
| 382 | ||
| 383 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { | |
| 384 | DUMMY_SP | |
| 385 | } | |
| 386 | } | |
| 387 | ||
| 388 | 247 | impl<'tcx> Key for ty::TraitRef<'tcx> { |
| 389 | type Cache<V> = DefaultCache<Self, V>; | |
| 390 | ||
| 391 | 248 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 392 | 249 | tcx.def_span(self.def_id) |
| 393 | 250 | } |
| 394 | 251 | } |
| 395 | 252 | |
| 396 | impl<'tcx> Key for ty::PolyTraitRef<'tcx> { | |
| 397 | type Cache<V> = DefaultCache<Self, V>; | |
| 398 | ||
| 399 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 400 | tcx.def_span(self.def_id()) | |
| 401 | } | |
| 402 | } | |
| 403 | ||
| 404 | impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> { | |
| 405 | type Cache<V> = DefaultCache<Self, V>; | |
| 406 | ||
| 407 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 408 | tcx.def_span(self.def_id()) | |
| 409 | } | |
| 410 | } | |
| 411 | ||
| 412 | impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) { | |
| 413 | type Cache<V> = DefaultCache<Self, V>; | |
| 414 | ||
| 415 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 416 | tcx.def_span(self.0.def_id()) | |
| 417 | } | |
| 418 | } | |
| 419 | ||
| 420 | 253 | impl<'tcx> Key for GenericArg<'tcx> { |
| 421 | type Cache<V> = DefaultCache<Self, V>; | |
| 422 | ||
| 423 | fn default_span(&self, _: TyCtxt<'_>) -> Span { | |
| 424 | DUMMY_SP | |
| 425 | } | |
| 426 | } | |
| 427 | ||
| 428 | impl<'tcx> Key for ty::Const<'tcx> { | |
| 429 | type Cache<V> = DefaultCache<Self, V>; | |
| 430 | ||
| 431 | 254 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 432 | 255 | DUMMY_SP |
| 433 | 256 | } |
| 434 | 257 | } |
| 435 | 258 | |
| 436 | 259 | impl<'tcx> Key for Ty<'tcx> { |
| 437 | type Cache<V> = DefaultCache<Self, V>; | |
| 438 | ||
| 439 | 260 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 440 | 261 | DUMMY_SP |
| 441 | 262 | } |
| ... | ... | @@ -449,41 +270,19 @@ impl<'tcx> Key for Ty<'tcx> { |
| 449 | 270 | } |
| 450 | 271 | } |
| 451 | 272 | |
| 452 | impl<'tcx> Key for TyAndLayout<'tcx> { | |
| 453 | type Cache<V> = DefaultCache<Self, V>; | |
| 454 | ||
| 455 | fn default_span(&self, _: TyCtxt<'_>) -> Span { | |
| 456 | DUMMY_SP | |
| 457 | } | |
| 458 | } | |
| 459 | ||
| 460 | 273 | impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) { |
| 461 | type Cache<V> = DefaultCache<Self, V>; | |
| 462 | ||
| 463 | 274 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 464 | 275 | DUMMY_SP |
| 465 | 276 | } |
| 466 | 277 | } |
| 467 | 278 | |
| 468 | 279 | impl<'tcx> Key for ty::Clauses<'tcx> { |
| 469 | type Cache<V> = DefaultCache<Self, V>; | |
| 470 | ||
| 471 | fn default_span(&self, _: TyCtxt<'_>) -> Span { | |
| 472 | DUMMY_SP | |
| 473 | } | |
| 474 | } | |
| 475 | ||
| 476 | impl<'tcx> Key for ty::ParamEnv<'tcx> { | |
| 477 | type Cache<V> = DefaultCache<Self, V>; | |
| 478 | ||
| 479 | 280 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 480 | 281 | DUMMY_SP |
| 481 | 282 | } |
| 482 | 283 | } |
| 483 | 284 | |
| 484 | 285 | impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { |
| 485 | type Cache<V> = DefaultCache<Self, V>; | |
| 486 | ||
| 487 | 286 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 488 | 287 | self.value.default_span(tcx) |
| 489 | 288 | } |
| ... | ... | @@ -494,24 +293,18 @@ impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { |
| 494 | 293 | } |
| 495 | 294 | |
| 496 | 295 | impl Key for Symbol { |
| 497 | type Cache<V> = DefaultCache<Self, V>; | |
| 498 | ||
| 499 | 296 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 500 | 297 | DUMMY_SP |
| 501 | 298 | } |
| 502 | 299 | } |
| 503 | 300 | |
| 504 | 301 | impl Key for Option<Symbol> { |
| 505 | type Cache<V> = DefaultCache<Self, V>; | |
| 506 | ||
| 507 | 302 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 508 | 303 | DUMMY_SP |
| 509 | 304 | } |
| 510 | 305 | } |
| 511 | 306 | |
| 512 | 307 | impl<'tcx> Key for &'tcx OsStr { |
| 513 | type Cache<V> = DefaultCache<Self, V>; | |
| 514 | ||
| 515 | 308 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 516 | 309 | DUMMY_SP |
| 517 | 310 | } |
| ... | ... | @@ -520,119 +313,54 @@ impl<'tcx> Key for &'tcx OsStr { |
| 520 | 313 | /// Canonical query goals correspond to abstract trait operations that |
| 521 | 314 | /// are not tied to any crate in particular. |
| 522 | 315 | impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> { |
| 523 | type Cache<V> = DefaultCache<Self, V>; | |
| 524 | ||
| 525 | 316 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 526 | 317 | DUMMY_SP |
| 527 | 318 | } |
| 528 | 319 | } |
| 529 | 320 | |
| 530 | 321 | impl<'tcx, T: Clone> Key for (CanonicalQueryInput<'tcx, T>, bool) { |
| 531 | type Cache<V> = DefaultCache<Self, V>; | |
| 532 | ||
| 533 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { | |
| 534 | DUMMY_SP | |
| 535 | } | |
| 536 | } | |
| 537 | ||
| 538 | impl Key for (Symbol, u32, u32) { | |
| 539 | type Cache<V> = DefaultCache<Self, V>; | |
| 540 | ||
| 541 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { | |
| 542 | DUMMY_SP | |
| 543 | } | |
| 544 | } | |
| 545 | ||
| 546 | impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) { | |
| 547 | type Cache<V> = DefaultCache<Self, V>; | |
| 548 | ||
| 549 | 322 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 550 | 323 | DUMMY_SP |
| 551 | 324 | } |
| 552 | 325 | } |
| 553 | 326 | |
| 554 | 327 | impl<'tcx> Key for (Ty<'tcx>, rustc_abi::VariantIdx) { |
| 555 | type Cache<V> = DefaultCache<Self, V>; | |
| 556 | ||
| 557 | 328 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 558 | 329 | DUMMY_SP |
| 559 | 330 | } |
| 560 | 331 | } |
| 561 | 332 | |
| 562 | 333 | impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { |
| 563 | type Cache<V> = DefaultCache<Self, V>; | |
| 564 | ||
| 565 | 334 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 566 | 335 | DUMMY_SP |
| 567 | 336 | } |
| 568 | 337 | } |
| 569 | 338 | |
| 570 | 339 | impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) { |
| 571 | type Cache<V> = DefaultCache<Self, V>; | |
| 572 | ||
| 573 | 340 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 574 | 341 | DUMMY_SP |
| 575 | 342 | } |
| 576 | 343 | } |
| 577 | 344 | |
| 578 | 345 | impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) { |
| 579 | type Cache<V> = DefaultCache<Self, V>; | |
| 580 | ||
| 581 | 346 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 582 | 347 | self.0.default_span(tcx) |
| 583 | 348 | } |
| 584 | 349 | } |
| 585 | 350 | |
| 586 | 351 | impl<'tcx> Key for ty::Value<'tcx> { |
| 587 | type Cache<V> = DefaultCache<Self, V>; | |
| 588 | ||
| 589 | 352 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| 590 | 353 | DUMMY_SP |
| 591 | 354 | } |
| 592 | 355 | } |
| 593 | 356 | |
| 594 | impl Key for HirId { | |
| 595 | type Cache<V> = DefaultCache<Self, V>; | |
| 596 | ||
| 597 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 598 | tcx.hir_span(*self) | |
| 599 | } | |
| 600 | ||
| 601 | #[inline(always)] | |
| 602 | fn key_as_def_id(&self) -> Option<DefId> { | |
| 603 | None | |
| 604 | } | |
| 605 | } | |
| 606 | ||
| 607 | impl Key for (LocalDefId, HirId) { | |
| 608 | type Cache<V> = DefaultCache<Self, V>; | |
| 609 | ||
| 610 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { | |
| 611 | tcx.hir_span(self.1) | |
| 612 | } | |
| 613 | ||
| 614 | #[inline(always)] | |
| 615 | fn key_as_def_id(&self) -> Option<DefId> { | |
| 616 | Some(self.0.into()) | |
| 617 | } | |
| 618 | } | |
| 619 | ||
| 620 | 357 | impl<'tcx> Key for (LocalExpnId, &'tcx TokenStream) { |
| 621 | type Cache<V> = DefaultCache<Self, V>; | |
| 622 | ||
| 623 | 358 | fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| 624 | 359 | self.0.expn_data().call_site |
| 625 | 360 | } |
| 626 | ||
| 627 | #[inline(always)] | |
| 628 | fn key_as_def_id(&self) -> Option<DefId> { | |
| 629 | None | |
| 630 | } | |
| 631 | 361 | } |
| 632 | 362 | |
| 633 | 363 | impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) { |
| 634 | type Cache<V> = DefaultCache<Self, V>; | |
| 635 | ||
| 636 | 364 | // Just forward to `Ty<'tcx>` |
| 637 | 365 | |
| 638 | 366 | fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| ... | ... | @@ -648,8 +376,6 @@ impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx> |
| 648 | 376 | } |
| 649 | 377 | |
| 650 | 378 | impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) { |
| 651 | type Cache<V> = DefaultCache<Self, V>; | |
| 652 | ||
| 653 | 379 | fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| 654 | 380 | self.0.default_span(tcx) |
| 655 | 381 | } |
compiler/rustc_middle/src/query/mod.rs+1-1| ... | ... | @@ -88,7 +88,7 @@ use rustc_index::IndexVec; |
| 88 | 88 | use rustc_lint_defs::LintId; |
| 89 | 89 | use rustc_macros::rustc_queries; |
| 90 | 90 | use rustc_query_system::ich::StableHashingContext; |
| 91 | use rustc_query_system::query::{QueryMode, QueryState}; | |
| 91 | use rustc_query_system::query::{QueryMode, QueryStackDeferred, QueryState}; | |
| 92 | 92 | use rustc_session::Limits; |
| 93 | 93 | use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; |
| 94 | 94 | use rustc_session::cstore::{ |
compiler/rustc_middle/src/query/plumbing.rs+1-1| ... | ... | @@ -427,7 +427,7 @@ macro_rules! define_callbacks { |
| 427 | 427 | #[derive(Default)] |
| 428 | 428 | pub struct QueryStates<'tcx> { |
| 429 | 429 | $( |
| 430 | pub $name: QueryState<$($K)*>, | |
| 430 | pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>, | |
| 431 | 431 | )* |
| 432 | 432 | } |
| 433 | 433 |
compiler/rustc_middle/src/ty/print/pretty.rs+1-3| ... | ... | @@ -159,9 +159,7 @@ pub macro with_types_for_signature($e:expr) {{ |
| 159 | 159 | /// Avoids running any queries during prints. |
| 160 | 160 | pub macro with_no_queries($e:expr) {{ |
| 161 | 161 | $crate::ty::print::with_reduced_queries!($crate::ty::print::with_forced_impl_filename_line!( |
| 162 | $crate::ty::print::with_no_trimmed_paths!($crate::ty::print::with_no_visible_paths!( | |
| 163 | $crate::ty::print::with_forced_impl_filename_line!($e) | |
| 164 | )) | |
| 162 | $crate::ty::print::with_no_trimmed_paths!($crate::ty::print::with_no_visible_paths!($e)) | |
| 165 | 163 | )) |
| 166 | 164 | }} |
| 167 | 165 |
compiler/rustc_middle/src/values.rs+2-2| ... | ... | @@ -88,7 +88,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability { |
| 88 | 88 | if info.query.dep_kind == dep_kinds::representability |
| 89 | 89 | && let Some(field_id) = info.query.def_id |
| 90 | 90 | && let Some(field_id) = field_id.as_local() |
| 91 | && let Some(DefKind::Field) = info.query.def_kind | |
| 91 | && let Some(DefKind::Field) = info.query.info.def_kind | |
| 92 | 92 | { |
| 93 | 93 | let parent_id = tcx.parent(field_id.to_def_id()); |
| 94 | 94 | let item_id = match tcx.def_kind(parent_id) { |
| ... | ... | @@ -224,7 +224,7 @@ impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>> |
| 224 | 224 | continue; |
| 225 | 225 | }; |
| 226 | 226 | let frame_span = |
| 227 | frame.query.default_span(cycle[(i + 1) % cycle.len()].span); | |
| 227 | frame.query.info.default_span(cycle[(i + 1) % cycle.len()].span); | |
| 228 | 228 | if frame_span.is_dummy() { |
| 229 | 229 | continue; |
| 230 | 230 | } |
compiler/rustc_query_impl/src/lib.rs+6-3| ... | ... | @@ -23,7 +23,7 @@ use rustc_query_system::dep_graph::SerializedDepNodeIndex; |
| 23 | 23 | use rustc_query_system::ich::StableHashingContext; |
| 24 | 24 | use rustc_query_system::query::{ |
| 25 | 25 | CycleError, CycleErrorHandling, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, |
| 26 | QueryState, get_query_incr, get_query_non_incr, | |
| 26 | QueryStackDeferred, QueryState, get_query_incr, get_query_non_incr, | |
| 27 | 27 | }; |
| 28 | 28 | use rustc_span::{ErrorGuaranteed, Span}; |
| 29 | 29 | |
| ... | ... | @@ -79,7 +79,10 @@ where |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | #[inline(always)] |
| 82 | fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key> | |
| 82 | fn query_state<'a>( | |
| 83 | self, | |
| 84 | qcx: QueryCtxt<'tcx>, | |
| 85 | ) -> &'a QueryState<Self::Key, QueryStackDeferred<'tcx>> | |
| 83 | 86 | where |
| 84 | 87 | QueryCtxt<'tcx>: 'a, |
| 85 | 88 | { |
| ... | ... | @@ -88,7 +91,7 @@ where |
| 88 | 91 | unsafe { |
| 89 | 92 | &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>) |
| 90 | 93 | .byte_add(self.dynamic.query_state) |
| 91 | .cast::<QueryState<Self::Key>>() | |
| 94 | .cast::<QueryState<Self::Key, QueryStackDeferred<'tcx>>>() | |
| 92 | 95 | } |
| 93 | 96 | } |
| 94 | 97 |
compiler/rustc_query_impl/src/plumbing.rs+63-33| ... | ... | @@ -6,6 +6,7 @@ use std::num::NonZero; |
| 6 | 6 | |
| 7 | 7 | use rustc_data_structures::jobserver::Proxy; |
| 8 | 8 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
| 9 | use rustc_data_structures::sync::{DynSend, DynSync}; | |
| 9 | 10 | use rustc_data_structures::unord::UnordMap; |
| 10 | 11 | use rustc_hashes::Hash64; |
| 11 | 12 | use rustc_hir::limit::Limit; |
| ... | ... | @@ -26,8 +27,8 @@ use rustc_middle::ty::{self, TyCtxt}; |
| 26 | 27 | use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; |
| 27 | 28 | use rustc_query_system::ich::StableHashingContext; |
| 28 | 29 | use rustc_query_system::query::{ |
| 29 | QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame, | |
| 30 | force_query, | |
| 30 | QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, | |
| 31 | QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query, | |
| 31 | 32 | }; |
| 32 | 33 | use rustc_query_system::{QueryOverflow, QueryOverflowNote}; |
| 33 | 34 | use rustc_serialize::{Decodable, Encodable}; |
| ... | ... | @@ -59,7 +60,9 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> { |
| 59 | 60 | } |
| 60 | 61 | } |
| 61 | 62 | |
| 62 | impl QueryContext for QueryCtxt<'_> { | |
| 63 | impl<'tcx> QueryContext for QueryCtxt<'tcx> { | |
| 64 | type QueryInfo = QueryStackDeferred<'tcx>; | |
| 65 | ||
| 63 | 66 | #[inline] |
| 64 | 67 | fn jobserver_proxy(&self) -> &Proxy { |
| 65 | 68 | &self.tcx.jobserver_proxy |
| ... | ... | @@ -90,7 +93,10 @@ impl QueryContext for QueryCtxt<'_> { |
| 90 | 93 | /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, |
| 91 | 94 | /// especially when called from within a deadlock handler, unless a |
| 92 | 95 | /// complete map is needed and no deadlock is possible at this call site. |
| 93 | fn collect_active_jobs(self, require_complete: bool) -> Result<QueryMap, QueryMap> { | |
| 96 | fn collect_active_jobs( | |
| 97 | self, | |
| 98 | require_complete: bool, | |
| 99 | ) -> Result<QueryMap<QueryStackDeferred<'tcx>>, QueryMap<QueryStackDeferred<'tcx>>> { | |
| 94 | 100 | let mut jobs = QueryMap::default(); |
| 95 | 101 | let mut complete = true; |
| 96 | 102 | |
| ... | ... | @@ -103,6 +109,13 @@ impl QueryContext for QueryCtxt<'_> { |
| 103 | 109 | if complete { Ok(jobs) } else { Err(jobs) } |
| 104 | 110 | } |
| 105 | 111 | |
| 112 | fn lift_query_info( | |
| 113 | self, | |
| 114 | info: &QueryStackDeferred<'tcx>, | |
| 115 | ) -> rustc_query_system::query::QueryStackFrameExtra { | |
| 116 | info.extract() | |
| 117 | } | |
| 118 | ||
| 106 | 119 | // Interactions with on_disk_cache |
| 107 | 120 | fn load_side_effect( |
| 108 | 121 | self, |
| ... | ... | @@ -166,7 +179,10 @@ impl QueryContext for QueryCtxt<'_> { |
| 166 | 179 | |
| 167 | 180 | self.tcx.sess.dcx().emit_fatal(QueryOverflow { |
| 168 | 181 | span: info.job.span, |
| 169 | note: QueryOverflowNote { desc: info.query.description, depth }, | |
| 182 | note: QueryOverflowNote { | |
| 183 | desc: self.lift_query_info(&info.query.info).description, | |
| 184 | depth, | |
| 185 | }, | |
| 170 | 186 | suggested_limit, |
| 171 | 187 | crate_name: self.tcx.crate_name(LOCAL_CRATE), |
| 172 | 188 | }); |
| ... | ... | @@ -303,16 +319,17 @@ macro_rules! should_ever_cache_on_disk { |
| 303 | 319 | }; |
| 304 | 320 | } |
| 305 | 321 | |
| 306 | pub(crate) fn create_query_frame< | |
| 307 | 'tcx, | |
| 308 | K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>, | |
| 309 | >( | |
| 310 | tcx: TyCtxt<'tcx>, | |
| 311 | do_describe: fn(TyCtxt<'tcx>, K) -> String, | |
| 312 | key: K, | |
| 313 | kind: DepKind, | |
| 314 | name: &'static str, | |
| 315 | ) -> QueryStackFrame { | |
| 322 | fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( | |
| 323 | (tcx, key, kind, name, do_describe): ( | |
| 324 | TyCtxt<'tcx>, | |
| 325 | K, | |
| 326 | DepKind, | |
| 327 | &'static str, | |
| 328 | fn(TyCtxt<'tcx>, K) -> String, | |
| 329 | ), | |
| 330 | ) -> QueryStackFrameExtra { | |
| 331 | let def_id = key.key_as_def_id(); | |
| 332 | ||
| 316 | 333 | // If reduced queries are requested, we may be printing a query stack due |
| 317 | 334 | // to a panic. Avoid using `default_span` and `def_kind` in that case. |
| 318 | 335 | let reduce_queries = with_reduced_queries(); |
| ... | ... | @@ -324,36 +341,49 @@ pub(crate) fn create_query_frame< |
| 324 | 341 | } else { |
| 325 | 342 | description |
| 326 | 343 | }; |
| 327 | ||
| 328 | let span = if reduce_queries { | |
| 344 | let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { | |
| 329 | 345 | // The `def_span` query is used to calculate `default_span`, |
| 330 | 346 | // so exit to avoid infinite recursion. |
| 331 | 347 | None |
| 332 | 348 | } else { |
| 333 | Some(tcx.with_reduced_queries(|| key.default_span(tcx))) | |
| 349 | Some(key.default_span(tcx)) | |
| 334 | 350 | }; |
| 335 | 351 | |
| 336 | let def_id = key.key_as_def_id(); | |
| 337 | ||
| 338 | let def_kind = if reduce_queries { | |
| 352 | let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { | |
| 339 | 353 | // Try to avoid infinite recursion. |
| 340 | 354 | None |
| 341 | 355 | } else { |
| 342 | def_id | |
| 343 | .and_then(|def_id| def_id.as_local()) | |
| 344 | .map(|def_id| tcx.with_reduced_queries(|| tcx.def_kind(def_id))) | |
| 356 | def_id.and_then(|def_id| def_id.as_local()).map(|def_id| tcx.def_kind(def_id)) | |
| 345 | 357 | }; |
| 358 | QueryStackFrameExtra::new(description, span, def_kind) | |
| 359 | } | |
| 360 | ||
| 361 | pub(crate) fn create_query_frame< | |
| 362 | 'tcx, | |
| 363 | K: Copy + DynSend + DynSync + Key + for<'a> HashStable<StableHashingContext<'a>> + 'tcx, | |
| 364 | >( | |
| 365 | tcx: TyCtxt<'tcx>, | |
| 366 | do_describe: fn(TyCtxt<'tcx>, K) -> String, | |
| 367 | key: K, | |
| 368 | kind: DepKind, | |
| 369 | name: &'static str, | |
| 370 | ) -> QueryStackFrame<QueryStackDeferred<'tcx>> { | |
| 371 | let def_id = key.key_as_def_id(); | |
| 346 | 372 | |
| 373 | let hash = || { | |
| 374 | tcx.with_stable_hashing_context(|mut hcx| { | |
| 375 | let mut hasher = StableHasher::new(); | |
| 376 | kind.as_usize().hash_stable(&mut hcx, &mut hasher); | |
| 377 | key.hash_stable(&mut hcx, &mut hasher); | |
| 378 | hasher.finish::<Hash64>() | |
| 379 | }) | |
| 380 | }; | |
| 347 | 381 | let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); |
| 348 | 382 | |
| 349 | let hash = tcx.with_stable_hashing_context(|mut hcx| { | |
| 350 | let mut hasher = StableHasher::new(); | |
| 351 | kind.as_usize().hash_stable(&mut hcx, &mut hasher); | |
| 352 | key.hash_stable(&mut hcx, &mut hasher); | |
| 353 | hasher.finish::<Hash64>() | |
| 354 | }); | |
| 383 | let info = | |
| 384 | QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra); | |
| 355 | 385 | |
| 356 | QueryStackFrame::new(description, span, def_id, def_kind, kind, def_id_for_ty_in_cycle, hash) | |
| 386 | QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) | |
| 357 | 387 | } |
| 358 | 388 | |
| 359 | 389 | pub(crate) fn encode_query_results<'a, 'tcx, Q>( |
| ... | ... | @@ -707,7 +737,7 @@ macro_rules! define_queries { |
| 707 | 737 | |
| 708 | 738 | pub(crate) fn collect_active_jobs<'tcx>( |
| 709 | 739 | tcx: TyCtxt<'tcx>, |
| 710 | qmap: &mut QueryMap, | |
| 740 | qmap: &mut QueryMap<QueryStackDeferred<'tcx>>, | |
| 711 | 741 | require_complete: bool, |
| 712 | 742 | ) -> Option<()> { |
| 713 | 743 | let make_query = |tcx, key| { |
| ... | ... | @@ -791,7 +821,7 @@ macro_rules! define_queries { |
| 791 | 821 | // These arrays are used for iteration and can't be indexed by `DepKind`. |
| 792 | 822 | |
| 793 | 823 | const COLLECT_ACTIVE_JOBS: &[ |
| 794 | for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap, bool) -> Option<()> | |
| 824 | for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<QueryStackDeferred<'tcx>>, bool) -> Option<()> | |
| 795 | 825 | ] = |
| 796 | 826 | &[$(query_impl::$name::collect_active_jobs),*]; |
| 797 | 827 |
compiler/rustc_query_system/src/query/config.rs+3-2| ... | ... | @@ -6,6 +6,7 @@ use std::hash::Hash; |
| 6 | 6 | use rustc_data_structures::fingerprint::Fingerprint; |
| 7 | 7 | use rustc_span::ErrorGuaranteed; |
| 8 | 8 | |
| 9 | use super::QueryStackFrameExtra; | |
| 9 | 10 | use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex}; |
| 10 | 11 | use crate::ich::StableHashingContext; |
| 11 | 12 | use crate::query::caches::QueryCache; |
| ... | ... | @@ -26,7 +27,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy { |
| 26 | 27 | fn format_value(self) -> fn(&Self::Value) -> String; |
| 27 | 28 | |
| 28 | 29 | // Don't use this method to access query results, instead use the methods on TyCtxt |
| 29 | fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key> | |
| 30 | fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::QueryInfo> | |
| 30 | 31 | where |
| 31 | 32 | Qcx: 'a; |
| 32 | 33 | |
| ... | ... | @@ -56,7 +57,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy { |
| 56 | 57 | fn value_from_cycle_error( |
| 57 | 58 | self, |
| 58 | 59 | tcx: Qcx::DepContext, |
| 59 | cycle_error: &CycleError, | |
| 60 | cycle_error: &CycleError<QueryStackFrameExtra>, | |
| 60 | 61 | guar: ErrorGuaranteed, |
| 61 | 62 | ) -> Self::Value; |
| 62 | 63 |
compiler/rustc_query_system/src/query/job.rs+75-56| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use std::fmt::Debug; | |
| 1 | 2 | use std::hash::Hash; |
| 2 | 3 | use std::io::Write; |
| 3 | 4 | use std::iter; |
| ... | ... | @@ -11,6 +12,7 @@ use rustc_hir::def::DefKind; |
| 11 | 12 | use rustc_session::Session; |
| 12 | 13 | use rustc_span::{DUMMY_SP, Span}; |
| 13 | 14 | |
| 15 | use super::QueryStackFrameExtra; | |
| 14 | 16 | use crate::dep_graph::DepContext; |
| 15 | 17 | use crate::error::CycleStack; |
| 16 | 18 | use crate::query::plumbing::CycleError; |
| ... | ... | @@ -18,45 +20,54 @@ use crate::query::{QueryContext, QueryStackFrame}; |
| 18 | 20 | |
| 19 | 21 | /// Represents a span and a query key. |
| 20 | 22 | #[derive(Clone, Debug)] |
| 21 | pub struct QueryInfo { | |
| 23 | pub struct QueryInfo<I> { | |
| 22 | 24 | /// The span corresponding to the reason for which this query was required. |
| 23 | 25 | pub span: Span, |
| 24 | pub query: QueryStackFrame, | |
| 26 | pub query: QueryStackFrame<I>, | |
| 25 | 27 | } |
| 26 | 28 | |
| 27 | pub type QueryMap = FxHashMap<QueryJobId, QueryJobInfo>; | |
| 29 | impl<I> QueryInfo<I> { | |
| 30 | pub(crate) fn lift<Qcx: QueryContext<QueryInfo = I>>( | |
| 31 | &self, | |
| 32 | qcx: Qcx, | |
| 33 | ) -> QueryInfo<QueryStackFrameExtra> { | |
| 34 | QueryInfo { span: self.span, query: self.query.lift(qcx) } | |
| 35 | } | |
| 36 | } | |
| 37 | ||
| 38 | pub type QueryMap<I> = FxHashMap<QueryJobId, QueryJobInfo<I>>; | |
| 28 | 39 | |
| 29 | 40 | /// A value uniquely identifying an active query job. |
| 30 | 41 | #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| 31 | 42 | pub struct QueryJobId(pub NonZero<u64>); |
| 32 | 43 | |
| 33 | 44 | impl QueryJobId { |
| 34 | fn query(self, map: &QueryMap) -> QueryStackFrame { | |
| 45 | fn query<I: Clone>(self, map: &QueryMap<I>) -> QueryStackFrame<I> { | |
| 35 | 46 | map.get(&self).unwrap().query.clone() |
| 36 | 47 | } |
| 37 | 48 | |
| 38 | fn span(self, map: &QueryMap) -> Span { | |
| 49 | fn span<I>(self, map: &QueryMap<I>) -> Span { | |
| 39 | 50 | map.get(&self).unwrap().job.span |
| 40 | 51 | } |
| 41 | 52 | |
| 42 | fn parent(self, map: &QueryMap) -> Option<QueryJobId> { | |
| 53 | fn parent<I>(self, map: &QueryMap<I>) -> Option<QueryJobId> { | |
| 43 | 54 | map.get(&self).unwrap().job.parent |
| 44 | 55 | } |
| 45 | 56 | |
| 46 | fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { | |
| 57 | fn latch<I>(self, map: &QueryMap<I>) -> Option<&QueryLatch<I>> { | |
| 47 | 58 | map.get(&self).unwrap().job.latch.as_ref() |
| 48 | 59 | } |
| 49 | 60 | } |
| 50 | 61 | |
| 51 | 62 | #[derive(Clone, Debug)] |
| 52 | pub struct QueryJobInfo { | |
| 53 | pub query: QueryStackFrame, | |
| 54 | pub job: QueryJob, | |
| 63 | pub struct QueryJobInfo<I> { | |
| 64 | pub query: QueryStackFrame<I>, | |
| 65 | pub job: QueryJob<I>, | |
| 55 | 66 | } |
| 56 | 67 | |
| 57 | 68 | /// Represents an active query job. |
| 58 | 69 | #[derive(Debug)] |
| 59 | pub struct QueryJob { | |
| 70 | pub struct QueryJob<I> { | |
| 60 | 71 | pub id: QueryJobId, |
| 61 | 72 | |
| 62 | 73 | /// The span corresponding to the reason for which this query was required. |
| ... | ... | @@ -66,23 +77,23 @@ pub struct QueryJob { |
| 66 | 77 | pub parent: Option<QueryJobId>, |
| 67 | 78 | |
| 68 | 79 | /// The latch that is used to wait on this job. |
| 69 | latch: Option<QueryLatch>, | |
| 80 | latch: Option<QueryLatch<I>>, | |
| 70 | 81 | } |
| 71 | 82 | |
| 72 | impl Clone for QueryJob { | |
| 83 | impl<I> Clone for QueryJob<I> { | |
| 73 | 84 | fn clone(&self) -> Self { |
| 74 | 85 | Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() } |
| 75 | 86 | } |
| 76 | 87 | } |
| 77 | 88 | |
| 78 | impl QueryJob { | |
| 89 | impl<I> QueryJob<I> { | |
| 79 | 90 | /// Creates a new query job. |
| 80 | 91 | #[inline] |
| 81 | 92 | pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self { |
| 82 | 93 | QueryJob { id, span, parent, latch: None } |
| 83 | 94 | } |
| 84 | 95 | |
| 85 | pub(super) fn latch(&mut self) -> QueryLatch { | |
| 96 | pub(super) fn latch(&mut self) -> QueryLatch<I> { | |
| 86 | 97 | if self.latch.is_none() { |
| 87 | 98 | self.latch = Some(QueryLatch::new()); |
| 88 | 99 | } |
| ... | ... | @@ -102,12 +113,12 @@ impl QueryJob { |
| 102 | 113 | } |
| 103 | 114 | |
| 104 | 115 | impl QueryJobId { |
| 105 | pub(super) fn find_cycle_in_stack( | |
| 116 | pub(super) fn find_cycle_in_stack<I: Clone>( | |
| 106 | 117 | &self, |
| 107 | query_map: QueryMap, | |
| 118 | query_map: QueryMap<I>, | |
| 108 | 119 | current_job: &Option<QueryJobId>, |
| 109 | 120 | span: Span, |
| 110 | ) -> CycleError { | |
| 121 | ) -> CycleError<I> { | |
| 111 | 122 | // Find the waitee amongst `current_job` parents |
| 112 | 123 | let mut cycle = Vec::new(); |
| 113 | 124 | let mut current_job = Option::clone(current_job); |
| ... | ... | @@ -141,7 +152,7 @@ impl QueryJobId { |
| 141 | 152 | |
| 142 | 153 | #[cold] |
| 143 | 154 | #[inline(never)] |
| 144 | pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) { | |
| 155 | pub fn find_dep_kind_root<I: Clone>(&self, query_map: QueryMap<I>) -> (QueryJobInfo<I>, usize) { | |
| 145 | 156 | let mut depth = 1; |
| 146 | 157 | let info = query_map.get(&self).unwrap(); |
| 147 | 158 | let dep_kind = info.query.dep_kind; |
| ... | ... | @@ -161,31 +172,31 @@ impl QueryJobId { |
| 161 | 172 | } |
| 162 | 173 | |
| 163 | 174 | #[derive(Debug)] |
| 164 | struct QueryWaiter { | |
| 175 | struct QueryWaiter<I> { | |
| 165 | 176 | query: Option<QueryJobId>, |
| 166 | 177 | condvar: Condvar, |
| 167 | 178 | span: Span, |
| 168 | cycle: Mutex<Option<CycleError>>, | |
| 179 | cycle: Mutex<Option<CycleError<I>>>, | |
| 169 | 180 | } |
| 170 | 181 | |
| 171 | 182 | #[derive(Debug)] |
| 172 | struct QueryLatchInfo { | |
| 183 | struct QueryLatchInfo<I> { | |
| 173 | 184 | complete: bool, |
| 174 | waiters: Vec<Arc<QueryWaiter>>, | |
| 185 | waiters: Vec<Arc<QueryWaiter<I>>>, | |
| 175 | 186 | } |
| 176 | 187 | |
| 177 | 188 | #[derive(Debug)] |
| 178 | pub(super) struct QueryLatch { | |
| 179 | info: Arc<Mutex<QueryLatchInfo>>, | |
| 189 | pub(super) struct QueryLatch<I> { | |
| 190 | info: Arc<Mutex<QueryLatchInfo<I>>>, | |
| 180 | 191 | } |
| 181 | 192 | |
| 182 | impl Clone for QueryLatch { | |
| 193 | impl<I> Clone for QueryLatch<I> { | |
| 183 | 194 | fn clone(&self) -> Self { |
| 184 | 195 | Self { info: Arc::clone(&self.info) } |
| 185 | 196 | } |
| 186 | 197 | } |
| 187 | 198 | |
| 188 | impl QueryLatch { | |
| 199 | impl<I> QueryLatch<I> { | |
| 189 | 200 | fn new() -> Self { |
| 190 | 201 | QueryLatch { |
| 191 | 202 | info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), |
| ... | ... | @@ -198,7 +209,7 @@ impl QueryLatch { |
| 198 | 209 | qcx: impl QueryContext, |
| 199 | 210 | query: Option<QueryJobId>, |
| 200 | 211 | span: Span, |
| 201 | ) -> Result<(), CycleError> { | |
| 212 | ) -> Result<(), CycleError<I>> { | |
| 202 | 213 | let waiter = |
| 203 | 214 | Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); |
| 204 | 215 | self.wait_on_inner(qcx, &waiter); |
| ... | ... | @@ -213,7 +224,7 @@ impl QueryLatch { |
| 213 | 224 | } |
| 214 | 225 | |
| 215 | 226 | /// Awaits the caller on this latch by blocking the current thread. |
| 216 | fn wait_on_inner(&self, qcx: impl QueryContext, waiter: &Arc<QueryWaiter>) { | |
| 227 | fn wait_on_inner(&self, qcx: impl QueryContext, waiter: &Arc<QueryWaiter<I>>) { | |
| 217 | 228 | let mut info = self.info.lock(); |
| 218 | 229 | if !info.complete { |
| 219 | 230 | // We push the waiter on to the `waiters` list. It can be accessed inside |
| ... | ... | @@ -249,7 +260,7 @@ impl QueryLatch { |
| 249 | 260 | |
| 250 | 261 | /// Removes a single waiter from the list of waiters. |
| 251 | 262 | /// This is used to break query cycles. |
| 252 | fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter> { | |
| 263 | fn extract_waiter(&self, waiter: usize) -> Arc<QueryWaiter<I>> { | |
| 253 | 264 | let mut info = self.info.lock(); |
| 254 | 265 | debug_assert!(!info.complete); |
| 255 | 266 | // Remove the waiter from the list of waiters |
| ... | ... | @@ -269,7 +280,11 @@ type Waiter = (QueryJobId, usize); |
| 269 | 280 | /// For visits of resumable waiters it returns Some(Some(Waiter)) which has the |
| 270 | 281 | /// required information to resume the waiter. |
| 271 | 282 | /// If all `visit` calls returns None, this function also returns None. |
| 272 | fn visit_waiters<F>(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option<Option<Waiter>> | |
| 283 | fn visit_waiters<I, F>( | |
| 284 | query_map: &QueryMap<I>, | |
| 285 | query: QueryJobId, | |
| 286 | mut visit: F, | |
| 287 | ) -> Option<Option<Waiter>> | |
| 273 | 288 | where |
| 274 | 289 | F: FnMut(Span, QueryJobId) -> Option<Option<Waiter>>, |
| 275 | 290 | { |
| ... | ... | @@ -299,8 +314,8 @@ where |
| 299 | 314 | /// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. |
| 300 | 315 | /// If a cycle is detected, this initial value is replaced with the span causing |
| 301 | 316 | /// the cycle. |
| 302 | fn cycle_check( | |
| 303 | query_map: &QueryMap, | |
| 317 | fn cycle_check<I>( | |
| 318 | query_map: &QueryMap<I>, | |
| 304 | 319 | query: QueryJobId, |
| 305 | 320 | span: Span, |
| 306 | 321 | stack: &mut Vec<(Span, QueryJobId)>, |
| ... | ... | @@ -339,8 +354,8 @@ fn cycle_check( |
| 339 | 354 | /// Finds out if there's a path to the compiler root (aka. code which isn't in a query) |
| 340 | 355 | /// from `query` without going through any of the queries in `visited`. |
| 341 | 356 | /// This is achieved with a depth first search. |
| 342 | fn connected_to_root( | |
| 343 | query_map: &QueryMap, | |
| 357 | fn connected_to_root<I>( | |
| 358 | query_map: &QueryMap<I>, | |
| 344 | 359 | query: QueryJobId, |
| 345 | 360 | visited: &mut FxHashSet<QueryJobId>, |
| 346 | 361 | ) -> bool { |
| ... | ... | @@ -361,7 +376,7 @@ fn connected_to_root( |
| 361 | 376 | } |
| 362 | 377 | |
| 363 | 378 | // Deterministically pick an query from a list |
| 364 | fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T | |
| 379 | fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap<I>, queries: &'a [T], f: F) -> &'a T | |
| 365 | 380 | where |
| 366 | 381 | F: Fn(&T) -> (Span, QueryJobId), |
| 367 | 382 | { |
| ... | ... | @@ -386,10 +401,10 @@ where |
| 386 | 401 | /// the function return true. |
| 387 | 402 | /// If a cycle was not found, the starting query is removed from `jobs` and |
| 388 | 403 | /// the function returns false. |
| 389 | fn remove_cycle( | |
| 390 | query_map: &QueryMap, | |
| 404 | fn remove_cycle<I: Clone>( | |
| 405 | query_map: &QueryMap<I>, | |
| 391 | 406 | jobs: &mut Vec<QueryJobId>, |
| 392 | wakelist: &mut Vec<Arc<QueryWaiter>>, | |
| 407 | wakelist: &mut Vec<Arc<QueryWaiter<I>>>, | |
| 393 | 408 | ) -> bool { |
| 394 | 409 | let mut visited = FxHashSet::default(); |
| 395 | 410 | let mut stack = Vec::new(); |
| ... | ... | @@ -490,7 +505,10 @@ fn remove_cycle( |
| 490 | 505 | /// uses a query latch and then resuming that waiter. |
| 491 | 506 | /// There may be multiple cycles involved in a deadlock, so this searches |
| 492 | 507 | /// all active queries for cycles before finally resuming all the waiters at once. |
| 493 | pub fn break_query_cycles(query_map: QueryMap, registry: &rustc_thread_pool::Registry) { | |
| 508 | pub fn break_query_cycles<I: Clone + Debug>( | |
| 509 | query_map: QueryMap<I>, | |
| 510 | registry: &rustc_thread_pool::Registry, | |
| 511 | ) { | |
| 494 | 512 | let mut wakelist = Vec::new(); |
| 495 | 513 | // It is OK per the comments: |
| 496 | 514 | // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932 |
| ... | ... | @@ -541,7 +559,7 @@ pub fn report_cycle<'a>( |
| 541 | 559 | ) -> Diag<'a> { |
| 542 | 560 | assert!(!stack.is_empty()); |
| 543 | 561 | |
| 544 | let span = stack[0].query.default_span(stack[1 % stack.len()].span); | |
| 562 | let span = stack[0].query.info.default_span(stack[1 % stack.len()].span); | |
| 545 | 563 | |
| 546 | 564 | let mut cycle_stack = Vec::new(); |
| 547 | 565 | |
| ... | ... | @@ -550,31 +568,31 @@ pub fn report_cycle<'a>( |
| 550 | 568 | |
| 551 | 569 | for i in 1..stack.len() { |
| 552 | 570 | let query = &stack[i].query; |
| 553 | let span = query.default_span(stack[(i + 1) % stack.len()].span); | |
| 554 | cycle_stack.push(CycleStack { span, desc: query.description.to_owned() }); | |
| 571 | let span = query.info.default_span(stack[(i + 1) % stack.len()].span); | |
| 572 | cycle_stack.push(CycleStack { span, desc: query.info.description.to_owned() }); | |
| 555 | 573 | } |
| 556 | 574 | |
| 557 | 575 | let mut cycle_usage = None; |
| 558 | 576 | if let Some((span, ref query)) = *usage { |
| 559 | 577 | cycle_usage = Some(crate::error::CycleUsage { |
| 560 | span: query.default_span(span), | |
| 561 | usage: query.description.to_string(), | |
| 578 | span: query.info.default_span(span), | |
| 579 | usage: query.info.description.to_string(), | |
| 562 | 580 | }); |
| 563 | 581 | } |
| 564 | 582 | |
| 565 | let alias = if stack.iter().all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias))) | |
| 566 | { | |
| 567 | Some(crate::error::Alias::Ty) | |
| 568 | } else if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TraitAlias)) { | |
| 569 | Some(crate::error::Alias::Trait) | |
| 570 | } else { | |
| 571 | None | |
| 572 | }; | |
| 583 | let alias = | |
| 584 | if stack.iter().all(|entry| matches!(entry.query.info.def_kind, Some(DefKind::TyAlias))) { | |
| 585 | Some(crate::error::Alias::Ty) | |
| 586 | } else if stack.iter().all(|entry| entry.query.info.def_kind == Some(DefKind::TraitAlias)) { | |
| 587 | Some(crate::error::Alias::Trait) | |
| 588 | } else { | |
| 589 | None | |
| 590 | }; | |
| 573 | 591 | |
| 574 | 592 | let cycle_diag = crate::error::Cycle { |
| 575 | 593 | span, |
| 576 | 594 | cycle_stack, |
| 577 | stack_bottom: stack[0].query.description.to_owned(), | |
| 595 | stack_bottom: stack[0].query.info.description.to_owned(), | |
| 578 | 596 | alias, |
| 579 | 597 | cycle_usage, |
| 580 | 598 | stack_count, |
| ... | ... | @@ -610,11 +628,12 @@ pub fn print_query_stack<Qcx: QueryContext>( |
| 610 | 628 | let Some(query_info) = query_map.get(&query) else { |
| 611 | 629 | break; |
| 612 | 630 | }; |
| 631 | let query_extra = qcx.lift_query_info(&query_info.query.info); | |
| 613 | 632 | if Some(count_printed) < limit_frames || limit_frames.is_none() { |
| 614 | 633 | // Only print to stderr as many stack frames as `num_frames` when present. |
| 615 | 634 | dcx.struct_failure_note(format!( |
| 616 | 635 | "#{} [{:?}] {}", |
| 617 | count_printed, query_info.query.dep_kind, query_info.query.description | |
| 636 | count_printed, query_info.query.dep_kind, query_extra.description | |
| 618 | 637 | )) |
| 619 | 638 | .with_span(query_info.job.span) |
| 620 | 639 | .emit(); |
| ... | ... | @@ -627,7 +646,7 @@ pub fn print_query_stack<Qcx: QueryContext>( |
| 627 | 646 | "#{} [{}] {}", |
| 628 | 647 | count_total, |
| 629 | 648 | qcx.dep_context().dep_kind_vtable(query_info.query.dep_kind).name, |
| 630 | query_info.query.description | |
| 649 | query_extra.description | |
| 631 | 650 | ); |
| 632 | 651 | } |
| 633 | 652 |
compiler/rustc_query_system/src/query/mod.rs+90-15| ... | ... | @@ -1,4 +1,10 @@ |
| 1 | use std::fmt::Debug; | |
| 2 | use std::marker::PhantomData; | |
| 3 | use std::mem::transmute; | |
| 4 | use std::sync::Arc; | |
| 5 | ||
| 1 | 6 | use rustc_data_structures::jobserver::Proxy; |
| 7 | use rustc_data_structures::sync::{DynSend, DynSync}; | |
| 2 | 8 | use rustc_errors::DiagInner; |
| 3 | 9 | use rustc_hashes::Hash64; |
| 4 | 10 | use rustc_hir::def::DefKind; |
| ... | ... | @@ -36,31 +42,59 @@ pub enum CycleErrorHandling { |
| 36 | 42 | /// |
| 37 | 43 | /// This is mostly used in case of cycles for error reporting. |
| 38 | 44 | #[derive(Clone, Debug)] |
| 39 | pub struct QueryStackFrame { | |
| 40 | pub description: String, | |
| 41 | span: Option<Span>, | |
| 42 | pub def_id: Option<DefId>, | |
| 43 | pub def_kind: Option<DefKind>, | |
| 44 | /// A def-id that is extracted from a `Ty` in a query key | |
| 45 | pub def_id_for_ty_in_cycle: Option<DefId>, | |
| 45 | pub struct QueryStackFrame<I> { | |
| 46 | /// This field initially stores a `QueryStackDeferred` during collection, | |
| 47 | /// but can later be changed to `QueryStackFrameExtra` containing concrete information | |
| 48 | /// by calling `lift`. This is done so that collecting query does not need to invoke | |
| 49 | /// queries, instead `lift` will call queries in a more appropriate location. | |
| 50 | pub info: I, | |
| 51 | ||
| 46 | 52 | pub dep_kind: DepKind, |
| 47 | 53 | /// This hash is used to deterministically pick |
| 48 | 54 | /// a query to remove cycles in the parallel compiler. |
| 49 | 55 | hash: Hash64, |
| 56 | pub def_id: Option<DefId>, | |
| 57 | /// A def-id that is extracted from a `Ty` in a query key | |
| 58 | pub def_id_for_ty_in_cycle: Option<DefId>, | |
| 50 | 59 | } |
| 51 | 60 | |
| 52 | impl QueryStackFrame { | |
| 61 | impl<I> QueryStackFrame<I> { | |
| 53 | 62 | #[inline] |
| 54 | 63 | pub fn new( |
| 55 | description: String, | |
| 56 | span: Option<Span>, | |
| 57 | def_id: Option<DefId>, | |
| 58 | def_kind: Option<DefKind>, | |
| 64 | info: I, | |
| 59 | 65 | dep_kind: DepKind, |
| 66 | hash: impl FnOnce() -> Hash64, | |
| 67 | def_id: Option<DefId>, | |
| 60 | 68 | def_id_for_ty_in_cycle: Option<DefId>, |
| 61 | hash: Hash64, | |
| 62 | 69 | ) -> Self { |
| 63 | Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash } | |
| 70 | Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle } | |
| 71 | } | |
| 72 | ||
| 73 | fn lift<Qcx: QueryContext<QueryInfo = I>>( | |
| 74 | &self, | |
| 75 | qcx: Qcx, | |
| 76 | ) -> QueryStackFrame<QueryStackFrameExtra> { | |
| 77 | QueryStackFrame { | |
| 78 | info: qcx.lift_query_info(&self.info), | |
| 79 | dep_kind: self.dep_kind, | |
| 80 | hash: self.hash, | |
| 81 | def_id: self.def_id, | |
| 82 | def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle, | |
| 83 | } | |
| 84 | } | |
| 85 | } | |
| 86 | ||
| 87 | #[derive(Clone, Debug)] | |
| 88 | pub struct QueryStackFrameExtra { | |
| 89 | pub description: String, | |
| 90 | span: Option<Span>, | |
| 91 | pub def_kind: Option<DefKind>, | |
| 92 | } | |
| 93 | ||
| 94 | impl QueryStackFrameExtra { | |
| 95 | #[inline] | |
| 96 | pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self { | |
| 97 | Self { description, span, def_kind } | |
| 64 | 98 | } |
| 65 | 99 | |
| 66 | 100 | // FIXME(eddyb) Get more valid `Span`s on queries. |
| ... | ... | @@ -73,6 +107,40 @@ impl QueryStackFrame { |
| 73 | 107 | } |
| 74 | 108 | } |
| 75 | 109 | |
| 110 | /// Track a 'side effect' for a particular query. | |
| 111 | /// This is used to hold a closure which can create `QueryStackFrameExtra`. | |
| 112 | #[derive(Clone)] | |
| 113 | pub struct QueryStackDeferred<'tcx> { | |
| 114 | _dummy: PhantomData<&'tcx ()>, | |
| 115 | ||
| 116 | // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't | |
| 117 | // access it in the destructor. | |
| 118 | extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend>, | |
| 119 | } | |
| 120 | ||
| 121 | impl<'tcx> QueryStackDeferred<'tcx> { | |
| 122 | pub fn new<C: Copy + DynSync + DynSend + 'tcx>( | |
| 123 | context: C, | |
| 124 | extract: fn(C) -> QueryStackFrameExtra, | |
| 125 | ) -> Self { | |
| 126 | let extract: Arc<dyn Fn() -> QueryStackFrameExtra + DynSync + DynSend + 'tcx> = | |
| 127 | Arc::new(move || extract(context)); | |
| 128 | // SAFETY: The `extract` closure does not access 'tcx in its destructor as the only | |
| 129 | // captured variable is `context` which is Copy and cannot have a destructor. | |
| 130 | Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } } | |
| 131 | } | |
| 132 | ||
| 133 | pub fn extract(&self) -> QueryStackFrameExtra { | |
| 134 | (self.extract)() | |
| 135 | } | |
| 136 | } | |
| 137 | ||
| 138 | impl<'tcx> Debug for QueryStackDeferred<'tcx> { | |
| 139 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| 140 | f.write_str("QueryStackDeferred") | |
| 141 | } | |
| 142 | } | |
| 143 | ||
| 76 | 144 | /// Tracks 'side effects' for a particular query. |
| 77 | 145 | /// This struct is saved to disk along with the query result, |
| 78 | 146 | /// and loaded from disk if we mark the query as green. |
| ... | ... | @@ -92,6 +160,8 @@ pub enum QuerySideEffect { |
| 92 | 160 | } |
| 93 | 161 | |
| 94 | 162 | pub trait QueryContext: HasDepContext { |
| 163 | type QueryInfo: Clone; | |
| 164 | ||
| 95 | 165 | /// Gets a jobserver reference which is used to release then acquire |
| 96 | 166 | /// a token while waiting on a query. |
| 97 | 167 | fn jobserver_proxy(&self) -> &Proxy; |
| ... | ... | @@ -101,7 +171,12 @@ pub trait QueryContext: HasDepContext { |
| 101 | 171 | /// Get the query information from the TLS context. |
| 102 | 172 | fn current_query_job(self) -> Option<QueryJobId>; |
| 103 | 173 | |
| 104 | fn collect_active_jobs(self, require_complete: bool) -> Result<QueryMap, QueryMap>; | |
| 174 | fn collect_active_jobs( | |
| 175 | self, | |
| 176 | require_complete: bool, | |
| 177 | ) -> Result<QueryMap<Self::QueryInfo>, QueryMap<Self::QueryInfo>>; | |
| 178 | ||
| 179 | fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra; | |
| 105 | 180 | |
| 106 | 181 | /// Load a side effect associated to the node in the previous session. |
| 107 | 182 | fn load_side_effect( |
compiler/rustc_query_system/src/query/plumbing.rs+35-26| ... | ... | @@ -18,7 +18,7 @@ use rustc_errors::{Diag, FatalError, StashKey}; |
| 18 | 18 | use rustc_span::{DUMMY_SP, Span}; |
| 19 | 19 | use tracing::instrument; |
| 20 | 20 | |
| 21 | use super::QueryConfig; | |
| 21 | use super::{QueryConfig, QueryStackFrameExtra}; | |
| 22 | 22 | use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams}; |
| 23 | 23 | use crate::ich::StableHashingContext; |
| 24 | 24 | use crate::query::caches::QueryCache; |
| ... | ... | @@ -32,23 +32,23 @@ fn equivalent_key<K: Eq, V>(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { |
| 32 | 32 | move |x| x.0 == *k |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | pub struct QueryState<K> { | |
| 36 | active: Sharded<hashbrown::HashTable<(K, QueryResult)>>, | |
| 35 | pub struct QueryState<K, I> { | |
| 36 | active: Sharded<hashbrown::HashTable<(K, QueryResult<I>)>>, | |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | /// Indicates the state of a query for a given key in a query map. |
| 40 | enum QueryResult { | |
| 40 | enum QueryResult<I> { | |
| 41 | 41 | /// An already executing query. The query job can be used to await for its completion. |
| 42 | Started(QueryJob), | |
| 42 | Started(QueryJob<I>), | |
| 43 | 43 | |
| 44 | 44 | /// The query panicked. Queries trying to wait on this will raise a fatal error which will |
| 45 | 45 | /// silently panic. |
| 46 | 46 | Poisoned, |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | impl QueryResult { | |
| 49 | impl<I> QueryResult<I> { | |
| 50 | 50 | /// Unwraps the query job expecting that it has started. |
| 51 | fn expect_job(self) -> QueryJob { | |
| 51 | fn expect_job(self) -> QueryJob<I> { | |
| 52 | 52 | match self { |
| 53 | 53 | Self::Started(job) => job, |
| 54 | 54 | Self::Poisoned => { |
| ... | ... | @@ -58,7 +58,7 @@ impl QueryResult { |
| 58 | 58 | } |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | impl<K> QueryState<K> | |
| 61 | impl<K, I> QueryState<K, I> | |
| 62 | 62 | where |
| 63 | 63 | K: Eq + Hash + Copy + Debug, |
| 64 | 64 | { |
| ... | ... | @@ -69,13 +69,13 @@ where |
| 69 | 69 | pub fn collect_active_jobs<Qcx: Copy>( |
| 70 | 70 | &self, |
| 71 | 71 | qcx: Qcx, |
| 72 | make_query: fn(Qcx, K) -> QueryStackFrame, | |
| 73 | jobs: &mut QueryMap, | |
| 72 | make_query: fn(Qcx, K) -> QueryStackFrame<I>, | |
| 73 | jobs: &mut QueryMap<I>, | |
| 74 | 74 | require_complete: bool, |
| 75 | 75 | ) -> Option<()> { |
| 76 | 76 | let mut active = Vec::new(); |
| 77 | 77 | |
| 78 | let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult)>>| { | |
| 78 | let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<I>)>>| { | |
| 79 | 79 | for (k, v) in iter.iter() { |
| 80 | 80 | if let QueryResult::Started(ref job) = *v { |
| 81 | 81 | active.push((*k, job.clone())); |
| ... | ... | @@ -106,19 +106,19 @@ where |
| 106 | 106 | } |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | impl<K> Default for QueryState<K> { | |
| 110 | fn default() -> QueryState<K> { | |
| 109 | impl<K, I> Default for QueryState<K, I> { | |
| 110 | fn default() -> QueryState<K, I> { | |
| 111 | 111 | QueryState { active: Default::default() } |
| 112 | 112 | } |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | 115 | /// A type representing the responsibility to execute the job in the `job` field. |
| 116 | 116 | /// This will poison the relevant query if dropped. |
| 117 | struct JobOwner<'tcx, K> | |
| 117 | struct JobOwner<'tcx, K, I> | |
| 118 | 118 | where |
| 119 | 119 | K: Eq + Hash + Copy, |
| 120 | 120 | { |
| 121 | state: &'tcx QueryState<K>, | |
| 121 | state: &'tcx QueryState<K, I>, | |
| 122 | 122 | key: K, |
| 123 | 123 | } |
| 124 | 124 | |
| ... | ... | @@ -159,7 +159,7 @@ where |
| 159 | 159 | } |
| 160 | 160 | CycleErrorHandling::Stash => { |
| 161 | 161 | let guar = if let Some(root) = cycle_error.cycle.first() |
| 162 | && let Some(span) = root.query.span | |
| 162 | && let Some(span) = root.query.info.span | |
| 163 | 163 | { |
| 164 | 164 | error.stash(span, StashKey::Cycle).unwrap() |
| 165 | 165 | } else { |
| ... | ... | @@ -170,7 +170,7 @@ where |
| 170 | 170 | } |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | impl<'tcx, K> JobOwner<'tcx, K> | |
| 173 | impl<'tcx, K, I> JobOwner<'tcx, K, I> | |
| 174 | 174 | where |
| 175 | 175 | K: Eq + Hash + Copy, |
| 176 | 176 | { |
| ... | ... | @@ -207,7 +207,7 @@ where |
| 207 | 207 | } |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | impl<'tcx, K> Drop for JobOwner<'tcx, K> | |
| 210 | impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I> | |
| 211 | 211 | where |
| 212 | 212 | K: Eq + Hash + Copy, |
| 213 | 213 | { |
| ... | ... | @@ -235,10 +235,19 @@ where |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | 237 | #[derive(Clone, Debug)] |
| 238 | pub struct CycleError { | |
| 238 | pub struct CycleError<I = QueryStackFrameExtra> { | |
| 239 | 239 | /// The query and related span that uses the cycle. |
| 240 | pub usage: Option<(Span, QueryStackFrame)>, | |
| 241 | pub cycle: Vec<QueryInfo>, | |
| 240 | pub usage: Option<(Span, QueryStackFrame<I>)>, | |
| 241 | pub cycle: Vec<QueryInfo<I>>, | |
| 242 | } | |
| 243 | ||
| 244 | impl<I> CycleError<I> { | |
| 245 | fn lift<Qcx: QueryContext<QueryInfo = I>>(&self, qcx: Qcx) -> CycleError<QueryStackFrameExtra> { | |
| 246 | CycleError { | |
| 247 | usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))), | |
| 248 | cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(), | |
| 249 | } | |
| 250 | } | |
| 242 | 251 | } |
| 243 | 252 | |
| 244 | 253 | /// Checks whether there is already a value for this key in the in-memory |
| ... | ... | @@ -275,10 +284,10 @@ where |
| 275 | 284 | { |
| 276 | 285 | // Ensure there was no errors collecting all active jobs. |
| 277 | 286 | // We need the complete map to ensure we find a cycle to break. |
| 278 | let query_map = qcx.collect_active_jobs(false).expect("failed to collect active queries"); | |
| 287 | let query_map = qcx.collect_active_jobs(false).ok().expect("failed to collect active queries"); | |
| 279 | 288 | |
| 280 | 289 | let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span); |
| 281 | (mk_cycle(query, qcx, error), None) | |
| 290 | (mk_cycle(query, qcx, error.lift(qcx)), None) | |
| 282 | 291 | } |
| 283 | 292 | |
| 284 | 293 | #[inline(always)] |
| ... | ... | @@ -287,7 +296,7 @@ fn wait_for_query<Q, Qcx>( |
| 287 | 296 | qcx: Qcx, |
| 288 | 297 | span: Span, |
| 289 | 298 | key: Q::Key, |
| 290 | latch: QueryLatch, | |
| 299 | latch: QueryLatch<Qcx::QueryInfo>, | |
| 291 | 300 | current: Option<QueryJobId>, |
| 292 | 301 | ) -> (Q::Value, Option<DepNodeIndex>) |
| 293 | 302 | where |
| ... | ... | @@ -327,7 +336,7 @@ where |
| 327 | 336 | |
| 328 | 337 | (v, Some(index)) |
| 329 | 338 | } |
| 330 | Err(cycle) => (mk_cycle(query, qcx, cycle), None), | |
| 339 | Err(cycle) => (mk_cycle(query, qcx, cycle.lift(qcx)), None), | |
| 331 | 340 | } |
| 332 | 341 | } |
| 333 | 342 | |
| ... | ... | @@ -405,7 +414,7 @@ where |
| 405 | 414 | fn execute_job<Q, Qcx, const INCR: bool>( |
| 406 | 415 | query: Q, |
| 407 | 416 | qcx: Qcx, |
| 408 | state: &QueryState<Q::Key>, | |
| 417 | state: &QueryState<Q::Key, Qcx::QueryInfo>, | |
| 409 | 418 | key: Q::Key, |
| 410 | 419 | key_hash: u64, |
| 411 | 420 | id: QueryJobId, |
library/core/src/slice/ascii.rs+78| ... | ... | @@ -62,6 +62,25 @@ impl [u8] { |
| 62 | 62 | return false; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] | |
| 66 | { | |
| 67 | const CHUNK_SIZE: usize = 16; | |
| 68 | // The following function has two invariants: | |
| 69 | // 1. The slice lengths must be equal, which we checked above. | |
| 70 | // 2. The slice lengths must greater than or equal to N, which this | |
| 71 | // if-statement is checking. | |
| 72 | if self.len() >= CHUNK_SIZE { | |
| 73 | return self.eq_ignore_ascii_case_chunks::<CHUNK_SIZE>(other); | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 77 | self.eq_ignore_ascii_case_simple(other) | |
| 78 | } | |
| 79 | ||
| 80 | /// ASCII case-insensitive equality check without chunk-at-a-time | |
| 81 | /// optimization. | |
| 82 | #[inline] | |
| 83 | const fn eq_ignore_ascii_case_simple(&self, other: &[u8]) -> bool { | |
| 65 | 84 | // FIXME(const-hack): This implementation can be reverted when |
| 66 | 85 | // `core::iter::zip` is allowed in const. The original implementation: |
| 67 | 86 | // self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b)) |
| ... | ... | @@ -80,6 +99,65 @@ impl [u8] { |
| 80 | 99 | true |
| 81 | 100 | } |
| 82 | 101 | |
| 102 | /// Optimized version of `eq_ignore_ascii_case` to process chunks at a time. | |
| 103 | /// | |
| 104 | /// Platforms that have SIMD instructions may benefit from this | |
| 105 | /// implementation over `eq_ignore_ascii_case_simple`. | |
| 106 | /// | |
| 107 | /// # Invariants | |
| 108 | /// | |
| 109 | /// The caller must guarantee that the slices are equal in length, and the | |
| 110 | /// slice lengths are greater than or equal to `N` bytes. | |
| 111 | #[cfg(all(target_arch = "x86_64", target_feature = "sse2"))] | |
| 112 | #[inline] | |
| 113 | const fn eq_ignore_ascii_case_chunks<const N: usize>(&self, other: &[u8]) -> bool { | |
| 114 | // FIXME(const-hack): The while-loops that follow should be replaced by | |
| 115 | // for-loops when available in const. | |
| 116 | ||
| 117 | let (self_chunks, self_rem) = self.as_chunks::<N>(); | |
| 118 | let (other_chunks, _) = other.as_chunks::<N>(); | |
| 119 | ||
| 120 | // Branchless check to encourage auto-vectorization | |
| 121 | #[inline(always)] | |
| 122 | const fn eq_ignore_ascii_inner<const L: usize>(lhs: &[u8; L], rhs: &[u8; L]) -> bool { | |
| 123 | let mut equal_ascii = true; | |
| 124 | let mut j = 0; | |
| 125 | while j < L { | |
| 126 | equal_ascii &= lhs[j].eq_ignore_ascii_case(&rhs[j]); | |
| 127 | j += 1; | |
| 128 | } | |
| 129 | ||
| 130 | equal_ascii | |
| 131 | } | |
| 132 | ||
| 133 | // Process the chunks, returning early if an inequality is found | |
| 134 | let mut i = 0; | |
| 135 | while i < self_chunks.len() && i < other_chunks.len() { | |
| 136 | if !eq_ignore_ascii_inner(&self_chunks[i], &other_chunks[i]) { | |
| 137 | return false; | |
| 138 | } | |
| 139 | i += 1; | |
| 140 | } | |
| 141 | ||
| 142 | // Check the length invariant which is necessary for the tail-handling | |
| 143 | // logic to be correct. This should have been upheld by the caller, | |
| 144 | // otherwise lengths less than N will compare as true without any | |
| 145 | // checking. | |
| 146 | debug_assert!(self.len() >= N); | |
| 147 | ||
| 148 | // If there are remaining tails, load the last N bytes in the slices to | |
| 149 | // avoid falling back to per-byte checking. | |
| 150 | if !self_rem.is_empty() { | |
| 151 | if let (Some(a_rem), Some(b_rem)) = (self.last_chunk::<N>(), other.last_chunk::<N>()) { | |
| 152 | if !eq_ignore_ascii_inner(a_rem, b_rem) { | |
| 153 | return false; | |
| 154 | } | |
| 155 | } | |
| 156 | } | |
| 157 | ||
| 158 | true | |
| 159 | } | |
| 160 | ||
| 83 | 161 | /// Converts this slice to its ASCII upper case equivalent in-place. |
| 84 | 162 | /// |
| 85 | 163 | /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', |
library/coretests/benches/str.rs+1| ... | ... | @@ -5,6 +5,7 @@ use test::{Bencher, black_box}; |
| 5 | 5 | mod char_count; |
| 6 | 6 | mod corpora; |
| 7 | 7 | mod debug; |
| 8 | mod eq_ignore_ascii_case; | |
| 8 | 9 | mod iter; |
| 9 | 10 | |
| 10 | 11 | #[bench] |
library/coretests/benches/str/eq_ignore_ascii_case.rs created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | use test::{Bencher, black_box}; | |
| 2 | ||
| 3 | use super::corpora::*; | |
| 4 | ||
| 5 | #[bench] | |
| 6 | fn bench_str_under_8_bytes_eq(b: &mut Bencher) { | |
| 7 | let s = black_box("foo"); | |
| 8 | let other = black_box("foo"); | |
| 9 | b.iter(|| assert!(s.eq_ignore_ascii_case(other))) | |
| 10 | } | |
| 11 | ||
| 12 | #[bench] | |
| 13 | fn bench_str_of_8_bytes_eq(b: &mut Bencher) { | |
| 14 | let s = black_box(en::TINY); | |
| 15 | let other = black_box(en::TINY); | |
| 16 | b.iter(|| assert!(s.eq_ignore_ascii_case(other))) | |
| 17 | } | |
| 18 | ||
| 19 | #[bench] | |
| 20 | fn bench_str_17_bytes_eq(b: &mut Bencher) { | |
| 21 | let s = black_box(&en::SMALL[..17]); | |
| 22 | let other = black_box(&en::SMALL[..17]); | |
| 23 | b.iter(|| assert!(s.eq_ignore_ascii_case(other))) | |
| 24 | } | |
| 25 | ||
| 26 | #[bench] | |
| 27 | fn bench_str_31_bytes_eq(b: &mut Bencher) { | |
| 28 | let s = black_box(&en::SMALL[..31]); | |
| 29 | let other = black_box(&en::SMALL[..31]); | |
| 30 | b.iter(|| assert!(s.eq_ignore_ascii_case(other))) | |
| 31 | } | |
| 32 | ||
| 33 | #[bench] | |
| 34 | fn bench_medium_str_eq(b: &mut Bencher) { | |
| 35 | let s = black_box(en::MEDIUM); | |
| 36 | let other = black_box(en::MEDIUM); | |
| 37 | b.iter(|| assert!(s.eq_ignore_ascii_case(other))) | |
| 38 | } | |
| 39 | ||
| 40 | #[bench] | |
| 41 | fn bench_large_str_eq(b: &mut Bencher) { | |
| 42 | let s = black_box(en::LARGE); | |
| 43 | let other = black_box(en::LARGE); | |
| 44 | b.iter(|| assert!(s.eq_ignore_ascii_case(other))) | |
| 45 | } |
package.json+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | { |
| 2 | 2 | "dependencies": { |
| 3 | "browser-ui-test": "^0.23.1", | |
| 3 | "browser-ui-test": "^0.23.2", | |
| 4 | 4 | "es-check": "^9.4.4", |
| 5 | 5 | "eslint": "^8.57.1", |
| 6 | 6 | "typescript": "^5.8.3" |
src/doc/rustc-dev-guide/src/conventions.md+1-2| ... | ... | @@ -76,8 +76,7 @@ These use a pinned version of `ruff`, to avoid relying on the local environment. |
| 76 | 76 | <!-- REUSE-IgnoreEnd --> |
| 77 | 77 | |
| 78 | 78 | In the past, files began with a copyright and license notice. |
| 79 | Please **omit** this notice for new files licensed under the standard terms (dual | |
| 80 | MIT/Apache-2.0). | |
| 79 | Please **omit** this notice for new files licensed under the standard terms (MIT OR Apache-2.0). | |
| 81 | 80 | |
| 82 | 81 | All of the copyright notices should be gone by now, but if you come across one |
| 83 | 82 | in the rust-lang/rust repo, feel free to open a PR to remove it. |
src/tools/miri/tests/pass/intrinsics/integer.rs-3| ... | ... | @@ -1,6 +1,3 @@ |
| 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 | |
| 2 | // SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org) | |
| 3 | ||
| 4 | 1 | #![feature(core_intrinsics, funnel_shifts)] |
| 5 | 2 | use std::intrinsics::*; |
| 6 | 3 |
src/tools/miri/tests/pass/issues/issue-30530.rs-3| ... | ... | @@ -1,6 +1,3 @@ |
| 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 | |
| 2 | // SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org) | |
| 3 | ||
| 4 | 1 | // Regression test for Issue #30530: alloca's created for storing |
| 5 | 2 | // intermediate scratch values during brace-less match arms need to be |
| 6 | 3 | // initialized with their drop-flag set to "dropped" (or else we end |
src/tools/miri/tests/pass/tag-align-dyn-u64.rs-3| ... | ... | @@ -1,6 +1,3 @@ |
| 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 | |
| 2 | // SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org) | |
| 3 | ||
| 4 | 1 | use std::mem; |
| 5 | 2 | |
| 6 | 3 | enum Tag<A> { |
tests/codegen-llvm/lib-optimizations/eq_ignore_ascii_case.rs created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | //@ compile-flags: -Copt-level=3 | |
| 2 | //@ only-x86_64 | |
| 3 | #![crate_type = "lib"] | |
| 4 | ||
| 5 | // Ensure that the optimized variant of the function gets auto-vectorized and | |
| 6 | // that the inner helper function is inlined. | |
| 7 | // CHECK-LABEL: @eq_ignore_ascii_case_autovectorized | |
| 8 | #[no_mangle] | |
| 9 | pub fn eq_ignore_ascii_case_autovectorized(s: &str, other: &str) -> bool { | |
| 10 | // CHECK: load <16 x i8> | |
| 11 | // CHECK: load <16 x i8> | |
| 12 | // CHECK: bitcast <16 x i1> | |
| 13 | // CHECK-NOT: call {{.*}}eq_ignore_ascii_inner | |
| 14 | // CHECK-NOT: panic | |
| 15 | s.eq_ignore_ascii_case(other) | |
| 16 | } |
tests/rustdoc-gui/utils.goml+1| ... | ... | @@ -110,6 +110,7 @@ define-function: ( |
| 110 | 110 | call-function: ("open-search", {}) |
| 111 | 111 | // We empty the search input in case it wasn't empty. |
| 112 | 112 | set-property: (".search-input", {"value": ""}) |
| 113 | focus: ".search-input" | |
| 113 | 114 | // We write the actual query. |
| 114 | 115 | write-into: (".search-input", |query|) |
| 115 | 116 | press-key: 'Enter' |
tests/ui/query-system/query-cycle-printing-issue-151226.rs created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | struct A<T>(std::sync::OnceLock<Self>); | |
| 2 | //~^ ERROR recursive type `A` has infinite size | |
| 3 | //~| ERROR cycle detected when computing layout of `A<()>` | |
| 4 | ||
| 5 | static B: A<()> = todo!(); | |
| 6 | //~^ ERROR cycle occurred during layout computation | |
| 7 | ||
| 8 | fn main() {} |
tests/ui/query-system/query-cycle-printing-issue-151226.stderr created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | error[E0072]: recursive type `A` has infinite size | |
| 2 | --> $DIR/query-cycle-printing-issue-151226.rs:1:1 | |
| 3 | | | |
| 4 | LL | struct A<T>(std::sync::OnceLock<Self>); | |
| 5 | | ^^^^^^^^^^^ ------------------------- recursive without indirection | |
| 6 | | | |
| 7 | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | |
| 8 | | | |
| 9 | LL | struct A<T>(Box<std::sync::OnceLock<Self>>); | |
| 10 | | ++++ + | |
| 11 | ||
| 12 | error[E0391]: cycle detected when computing layout of `A<()>` | |
| 13 | | | |
| 14 | = note: ...which requires computing layout of `std::sync::once_lock::OnceLock<A<()>>`... | |
| 15 | = note: ...which requires computing layout of `core::cell::UnsafeCell<core::mem::maybe_uninit::MaybeUninit<A<()>>>`... | |
| 16 | = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<A<()>>`... | |
| 17 | = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<A<()>>`... | |
| 18 | = note: ...which requires computing layout of `core::mem::maybe_dangling::MaybeDangling<A<()>>`... | |
| 19 | = note: ...which again requires computing layout of `A<()>`, completing the cycle | |
| 20 | note: cycle used when checking that `B` is well-formed | |
| 21 | --> $DIR/query-cycle-printing-issue-151226.rs:5:1 | |
| 22 | | | |
| 23 | LL | static B: A<()> = todo!(); | |
| 24 | | ^^^^^^^^^^^^^^^ | |
| 25 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 26 | ||
| 27 | error[E0080]: a cycle occurred during layout computation | |
| 28 | --> $DIR/query-cycle-printing-issue-151226.rs:5:1 | |
| 29 | | | |
| 30 | LL | static B: A<()> = todo!(); | |
| 31 | | ^^^^^^^^^^^^^^^ evaluation of `B` failed here | |
| 32 | ||
| 33 | error: aborting due to 3 previous errors | |
| 34 | ||
| 35 | Some errors have detailed explanations: E0072, E0080, E0391. | |
| 36 | For more information about an error, try `rustc --explain E0072`. |
tests/ui/query-system/query-cycle-printing-issue-151358.rs created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | //~ ERROR: cycle detected when looking up span for `Default` | |
| 2 | trait Default {} | |
| 3 | use std::num::NonZero; | |
| 4 | fn main() { | |
| 5 | NonZero(); | |
| 6 | format!("{}", 0); | |
| 7 | } |
tests/ui/query-system/query-cycle-printing-issue-151358.stderr created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | error[E0391]: cycle detected when looking up span for `Default` | |
| 2 | | | |
| 3 | = note: ...which immediately requires looking up span for `Default` again | |
| 4 | = note: cycle used when perform lints prior to AST lowering | |
| 5 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 | ||
| 9 | For more information about this error, try `rustc --explain E0391`. |
tests/ui/resolve/query-cycle-issue-124901.rs+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | //~ ERROR: cycle detected when getting HIR ID of `Default` | |
| 1 | //~ ERROR: cycle detected when looking up span for `Default` | |
| 2 | 2 | trait Default { |
| 3 | 3 | type Id; |
| 4 | 4 |
tests/ui/resolve/query-cycle-issue-124901.stderr+3-6| ... | ... | @@ -1,10 +1,7 @@ |
| 1 | error[E0391]: cycle detected when getting HIR ID of `Default` | |
| 1 | error[E0391]: cycle detected when looking up span for `Default` | |
| 2 | 2 | | |
| 3 | = note: ...which requires getting the crate HIR... | |
| 4 | = note: ...which requires perform lints prior to AST lowering... | |
| 5 | = note: ...which requires looking up span for `Default`... | |
| 6 | = note: ...which again requires getting HIR ID of `Default`, completing the cycle | |
| 7 | = note: cycle used when getting the resolver for lowering | |
| 3 | = note: ...which immediately requires looking up span for `Default` again | |
| 4 | = note: cycle used when perform lints prior to AST lowering | |
| 8 | 5 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information |
| 9 | 6 | |
| 10 | 7 | error: aborting due to 1 previous error |