authorbors <bors@rust-lang.org> 2026-01-27 06:37:15 UTC
committerbors <bors@rust-lang.org> 2026-01-27 06:37:15 UTC
log78df2f92de1da3601d967dc8beb9f9cea267e45f
treef968b6ab4870faf534b672347078b7722a3733cf
parentebf13cca58b551b83133d4895e123f7d1e795111
parent6ec16a409905d07f773575c9ec7dad6d776e4e33

Auto merge of #151727 - Zalathar:rollup-goIJldt, r=Zalathar

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 = [
5353]
5454precedence = "override"
5555SPDX-FileCopyrightText = "The Rust Project Developers (see https://thanks.rust-lang.org)"
56SPDX-License-Identifier = "MIT or Apache-2.0"
56SPDX-License-Identifier = "MIT OR Apache-2.0"
5757
5858[[annotations]]
5959path = "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
41#![no_std]
52#![feature(allocator_api, rustc_private)]
63
compiler/rustc_middle/src/query/keys.rs+4-278
......@@ -3,8 +3,8 @@
33use std::ffi::OsStr;
44
55use rustc_ast::tokenstream::TokenStream;
6use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
7use rustc_hir::hir_id::{HirId, OwnerId};
6use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
7use rustc_hir::hir_id::OwnerId;
88use rustc_query_system::dep_graph::DepNodeIndex;
99use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
1010use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol};
......@@ -12,7 +12,7 @@ use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol};
1212use crate::infer::canonical::CanonicalQueryInput;
1313use crate::mir::mono::CollectionMode;
1414use crate::ty::fast_reject::SimplifiedType;
15use crate::ty::layout::{TyAndLayout, ValidityRequirement};
15use crate::ty::layout::ValidityRequirement;
1616use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
1717use crate::{mir, traits};
1818
......@@ -29,15 +29,7 @@ pub trait Key: Sized {
2929 /// constraint is not enforced here.
3030 ///
3131 /// [`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>;
4133
4234 /// In the event that a cycle occurs, if no explicit span has been
4335 /// given for a query with key `self`, what span should we use?
......@@ -72,49 +64,30 @@ impl Key for () {
7264}
7365
7466impl<'tcx> Key for ty::InstanceKind<'tcx> {
75 type Cache<V> = DefaultCache<Self, V>;
76
7767 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
7868 tcx.def_span(self.def_id())
7969 }
8070}
8171
82impl<'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
9172impl<'tcx> Key for ty::Instance<'tcx> {
92 type Cache<V> = DefaultCache<Self, V>;
93
9473 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
9574 tcx.def_span(self.def_id())
9675 }
9776}
9877
9978impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
100 type Cache<V> = DefaultCache<Self, V>;
101
10279 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
10380 self.instance.default_span(tcx)
10481 }
10582}
10683
10784impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
108 type Cache<V> = DefaultCache<Self, V>;
109
11085 fn default_span(&self, _: TyCtxt<'_>) -> Span {
11186 DUMMY_SP
11287 }
11388}
11489
11590impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
116 type Cache<V> = DefaultCache<Self, V>;
117
11891 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
11992 DUMMY_SP
12093 }
......@@ -184,8 +157,6 @@ impl AsLocalKey for DefId {
184157}
185158
186159impl Key for LocalModDefId {
187 type Cache<V> = DefaultCache<Self, V>;
188
189160 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
190161 tcx.def_span(*self)
191162 }
......@@ -196,79 +167,19 @@ impl Key for LocalModDefId {
196167 }
197168}
198169
199impl 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
212impl 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
221170impl Key for SimplifiedType {
222 type Cache<V> = DefaultCache<Self, V>;
223
224171 fn default_span(&self, _: TyCtxt<'_>) -> Span {
225172 DUMMY_SP
226173 }
227174}
228175
229176impl Key for (DefId, DefId) {
230 type Cache<V> = DefaultCache<Self, V>;
231
232177 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
233178 self.1.default_span(tcx)
234179 }
235180}
236181
237impl<'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
245impl 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
253impl 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
261impl 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
269182impl Key for (DefId, Ident) {
270 type Cache<V> = DefaultCache<Self, V>;
271
272183 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
273184 tcx.def_span(self.0)
274185 }
......@@ -280,16 +191,12 @@ impl Key for (DefId, Ident) {
280191}
281192
282193impl Key for (LocalDefId, LocalDefId, Ident) {
283 type Cache<V> = DefaultCache<Self, V>;
284
285194 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
286195 self.1.default_span(tcx)
287196 }
288197}
289198
290199impl Key for (CrateNum, DefId) {
291 type Cache<V> = DefaultCache<Self, V>;
292
293200 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
294201 self.1.default_span(tcx)
295202 }
......@@ -305,8 +212,6 @@ impl AsLocalKey for (CrateNum, DefId) {
305212}
306213
307214impl Key for (CrateNum, SimplifiedType) {
308 type Cache<V> = DefaultCache<Self, V>;
309
310215 fn default_span(&self, _: TyCtxt<'_>) -> Span {
311216 DUMMY_SP
312217 }
......@@ -321,121 +226,37 @@ impl AsLocalKey for (CrateNum, SimplifiedType) {
321226 }
322227}
323228
324impl 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
332229impl Key for (DefId, ty::SizedTraitKind) {
333 type Cache<V> = DefaultCache<Self, V>;
334
335230 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
336231 self.0.default_span(tcx)
337232 }
338233}
339234
340235impl<'tcx> Key for GenericArgsRef<'tcx> {
341 type Cache<V> = DefaultCache<Self, V>;
342
343236 fn default_span(&self, _: TyCtxt<'_>) -> Span {
344237 DUMMY_SP
345238 }
346239}
347240
348241impl<'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
356impl<'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
364impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) {
365 type Cache<V> = DefaultCache<Self, V>;
366
367242 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
368243 self.0.default_span(tcx)
369244 }
370245}
371246
372impl<'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
380impl<'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
388247impl<'tcx> Key for ty::TraitRef<'tcx> {
389 type Cache<V> = DefaultCache<Self, V>;
390
391248 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
392249 tcx.def_span(self.def_id)
393250 }
394251}
395252
396impl<'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
404impl<'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
412impl<'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
420253impl<'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
428impl<'tcx> Key for ty::Const<'tcx> {
429 type Cache<V> = DefaultCache<Self, V>;
430
431254 fn default_span(&self, _: TyCtxt<'_>) -> Span {
432255 DUMMY_SP
433256 }
434257}
435258
436259impl<'tcx> Key for Ty<'tcx> {
437 type Cache<V> = DefaultCache<Self, V>;
438
439260 fn default_span(&self, _: TyCtxt<'_>) -> Span {
440261 DUMMY_SP
441262 }
......@@ -449,41 +270,19 @@ impl<'tcx> Key for Ty<'tcx> {
449270 }
450271}
451272
452impl<'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
460273impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
461 type Cache<V> = DefaultCache<Self, V>;
462
463274 fn default_span(&self, _: TyCtxt<'_>) -> Span {
464275 DUMMY_SP
465276 }
466277}
467278
468279impl<'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
476impl<'tcx> Key for ty::ParamEnv<'tcx> {
477 type Cache<V> = DefaultCache<Self, V>;
478
479280 fn default_span(&self, _: TyCtxt<'_>) -> Span {
480281 DUMMY_SP
481282 }
482283}
483284
484285impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> {
485 type Cache<V> = DefaultCache<Self, V>;
486
487286 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
488287 self.value.default_span(tcx)
489288 }
......@@ -494,24 +293,18 @@ impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> {
494293}
495294
496295impl Key for Symbol {
497 type Cache<V> = DefaultCache<Self, V>;
498
499296 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
500297 DUMMY_SP
501298 }
502299}
503300
504301impl Key for Option<Symbol> {
505 type Cache<V> = DefaultCache<Self, V>;
506
507302 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
508303 DUMMY_SP
509304 }
510305}
511306
512307impl<'tcx> Key for &'tcx OsStr {
513 type Cache<V> = DefaultCache<Self, V>;
514
515308 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
516309 DUMMY_SP
517310 }
......@@ -520,119 +313,54 @@ impl<'tcx> Key for &'tcx OsStr {
520313/// Canonical query goals correspond to abstract trait operations that
521314/// are not tied to any crate in particular.
522315impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> {
523 type Cache<V> = DefaultCache<Self, V>;
524
525316 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
526317 DUMMY_SP
527318 }
528319}
529320
530321impl<'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
538impl 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
546impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) {
547 type Cache<V> = DefaultCache<Self, V>;
548
549322 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
550323 DUMMY_SP
551324 }
552325}
553326
554327impl<'tcx> Key for (Ty<'tcx>, rustc_abi::VariantIdx) {
555 type Cache<V> = DefaultCache<Self, V>;
556
557328 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
558329 DUMMY_SP
559330 }
560331}
561332
562333impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
563 type Cache<V> = DefaultCache<Self, V>;
564
565334 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
566335 DUMMY_SP
567336 }
568337}
569338
570339impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
571 type Cache<V> = DefaultCache<Self, V>;
572
573340 fn default_span(&self, _: TyCtxt<'_>) -> Span {
574341 DUMMY_SP
575342 }
576343}
577344
578345impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
579 type Cache<V> = DefaultCache<Self, V>;
580
581346 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
582347 self.0.default_span(tcx)
583348 }
584349}
585350
586351impl<'tcx> Key for ty::Value<'tcx> {
587 type Cache<V> = DefaultCache<Self, V>;
588
589352 fn default_span(&self, _: TyCtxt<'_>) -> Span {
590353 DUMMY_SP
591354 }
592355}
593356
594impl 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
607impl 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
620357impl<'tcx> Key for (LocalExpnId, &'tcx TokenStream) {
621 type Cache<V> = DefaultCache<Self, V>;
622
623358 fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
624359 self.0.expn_data().call_site
625360 }
626
627 #[inline(always)]
628 fn key_as_def_id(&self) -> Option<DefId> {
629 None
630 }
631361}
632362
633363impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) {
634 type Cache<V> = DefaultCache<Self, V>;
635
636364 // Just forward to `Ty<'tcx>`
637365
638366 fn default_span(&self, _: TyCtxt<'_>) -> Span {
......@@ -648,8 +376,6 @@ impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>
648376}
649377
650378impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) {
651 type Cache<V> = DefaultCache<Self, V>;
652
653379 fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
654380 self.0.default_span(tcx)
655381 }
compiler/rustc_middle/src/query/mod.rs+1-1
......@@ -88,7 +88,7 @@ use rustc_index::IndexVec;
8888use rustc_lint_defs::LintId;
8989use rustc_macros::rustc_queries;
9090use rustc_query_system::ich::StableHashingContext;
91use rustc_query_system::query::{QueryMode, QueryState};
91use rustc_query_system::query::{QueryMode, QueryStackDeferred, QueryState};
9292use rustc_session::Limits;
9393use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
9494use rustc_session::cstore::{
compiler/rustc_middle/src/query/plumbing.rs+1-1
......@@ -427,7 +427,7 @@ macro_rules! define_callbacks {
427427 #[derive(Default)]
428428 pub struct QueryStates<'tcx> {
429429 $(
430 pub $name: QueryState<$($K)*>,
430 pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>,
431431 )*
432432 }
433433
compiler/rustc_middle/src/ty/print/pretty.rs+1-3
......@@ -159,9 +159,7 @@ pub macro with_types_for_signature($e:expr) {{
159159/// Avoids running any queries during prints.
160160pub macro with_no_queries($e:expr) {{
161161 $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))
165163 ))
166164}}
167165
compiler/rustc_middle/src/values.rs+2-2
......@@ -88,7 +88,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
8888 if info.query.dep_kind == dep_kinds::representability
8989 && let Some(field_id) = info.query.def_id
9090 && 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
9292 {
9393 let parent_id = tcx.parent(field_id.to_def_id());
9494 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<'_>>
224224 continue;
225225 };
226226 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);
228228 if frame_span.is_dummy() {
229229 continue;
230230 }
compiler/rustc_query_impl/src/lib.rs+6-3
......@@ -23,7 +23,7 @@ use rustc_query_system::dep_graph::SerializedDepNodeIndex;
2323use rustc_query_system::ich::StableHashingContext;
2424use rustc_query_system::query::{
2525 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,
2727};
2828use rustc_span::{ErrorGuaranteed, Span};
2929
......@@ -79,7 +79,10 @@ where
7979 }
8080
8181 #[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>>
8386 where
8487 QueryCtxt<'tcx>: 'a,
8588 {
......@@ -88,7 +91,7 @@ where
8891 unsafe {
8992 &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>)
9093 .byte_add(self.dynamic.query_state)
91 .cast::<QueryState<Self::Key>>()
94 .cast::<QueryState<Self::Key, QueryStackDeferred<'tcx>>>()
9295 }
9396 }
9497
compiler/rustc_query_impl/src/plumbing.rs+63-33
......@@ -6,6 +6,7 @@ use std::num::NonZero;
66
77use rustc_data_structures::jobserver::Proxy;
88use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
9use rustc_data_structures::sync::{DynSend, DynSync};
910use rustc_data_structures::unord::UnordMap;
1011use rustc_hashes::Hash64;
1112use rustc_hir::limit::Limit;
......@@ -26,8 +27,8 @@ use rustc_middle::ty::{self, TyCtxt};
2627use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
2728use rustc_query_system::ich::StableHashingContext;
2829use 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,
3132};
3233use rustc_query_system::{QueryOverflow, QueryOverflowNote};
3334use rustc_serialize::{Decodable, Encodable};
......@@ -59,7 +60,9 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
5960 }
6061}
6162
62impl QueryContext for QueryCtxt<'_> {
63impl<'tcx> QueryContext for QueryCtxt<'tcx> {
64 type QueryInfo = QueryStackDeferred<'tcx>;
65
6366 #[inline]
6467 fn jobserver_proxy(&self) -> &Proxy {
6568 &self.tcx.jobserver_proxy
......@@ -90,7 +93,10 @@ impl QueryContext for QueryCtxt<'_> {
9093 /// Prefer passing `false` to `require_complete` to avoid potential deadlocks,
9194 /// especially when called from within a deadlock handler, unless a
9295 /// 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>>> {
94100 let mut jobs = QueryMap::default();
95101 let mut complete = true;
96102
......@@ -103,6 +109,13 @@ impl QueryContext for QueryCtxt<'_> {
103109 if complete { Ok(jobs) } else { Err(jobs) }
104110 }
105111
112 fn lift_query_info(
113 self,
114 info: &QueryStackDeferred<'tcx>,
115 ) -> rustc_query_system::query::QueryStackFrameExtra {
116 info.extract()
117 }
118
106119 // Interactions with on_disk_cache
107120 fn load_side_effect(
108121 self,
......@@ -166,7 +179,10 @@ impl QueryContext for QueryCtxt<'_> {
166179
167180 self.tcx.sess.dcx().emit_fatal(QueryOverflow {
168181 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 },
170186 suggested_limit,
171187 crate_name: self.tcx.crate_name(LOCAL_CRATE),
172188 });
......@@ -303,16 +319,17 @@ macro_rules! should_ever_cache_on_disk {
303319 };
304320}
305321
306pub(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 {
322fn 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
316333 // If reduced queries are requested, we may be printing a query stack due
317334 // to a panic. Avoid using `default_span` and `def_kind` in that case.
318335 let reduce_queries = with_reduced_queries();
......@@ -324,36 +341,49 @@ pub(crate) fn create_query_frame<
324341 } else {
325342 description
326343 };
327
328 let span = if reduce_queries {
344 let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries {
329345 // The `def_span` query is used to calculate `default_span`,
330346 // so exit to avoid infinite recursion.
331347 None
332348 } else {
333 Some(tcx.with_reduced_queries(|| key.default_span(tcx)))
349 Some(key.default_span(tcx))
334350 };
335351
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 {
339353 // Try to avoid infinite recursion.
340354 None
341355 } 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))
345357 };
358 QueryStackFrameExtra::new(description, span, def_kind)
359}
360
361pub(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();
346372
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 };
347381 let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle();
348382
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);
355385
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)
357387}
358388
359389pub(crate) fn encode_query_results<'a, 'tcx, Q>(
......@@ -707,7 +737,7 @@ macro_rules! define_queries {
707737
708738 pub(crate) fn collect_active_jobs<'tcx>(
709739 tcx: TyCtxt<'tcx>,
710 qmap: &mut QueryMap,
740 qmap: &mut QueryMap<QueryStackDeferred<'tcx>>,
711741 require_complete: bool,
712742 ) -> Option<()> {
713743 let make_query = |tcx, key| {
......@@ -791,7 +821,7 @@ macro_rules! define_queries {
791821 // These arrays are used for iteration and can't be indexed by `DepKind`.
792822
793823 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<()>
795825 ] =
796826 &[$(query_impl::$name::collect_active_jobs),*];
797827
compiler/rustc_query_system/src/query/config.rs+3-2
......@@ -6,6 +6,7 @@ use std::hash::Hash;
66use rustc_data_structures::fingerprint::Fingerprint;
77use rustc_span::ErrorGuaranteed;
88
9use super::QueryStackFrameExtra;
910use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
1011use crate::ich::StableHashingContext;
1112use crate::query::caches::QueryCache;
......@@ -26,7 +27,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
2627 fn format_value(self) -> fn(&Self::Value) -> String;
2728
2829 // 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>
3031 where
3132 Qcx: 'a;
3233
......@@ -56,7 +57,7 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
5657 fn value_from_cycle_error(
5758 self,
5859 tcx: Qcx::DepContext,
59 cycle_error: &CycleError,
60 cycle_error: &CycleError<QueryStackFrameExtra>,
6061 guar: ErrorGuaranteed,
6162 ) -> Self::Value;
6263
compiler/rustc_query_system/src/query/job.rs+75-56
......@@ -1,3 +1,4 @@
1use std::fmt::Debug;
12use std::hash::Hash;
23use std::io::Write;
34use std::iter;
......@@ -11,6 +12,7 @@ use rustc_hir::def::DefKind;
1112use rustc_session::Session;
1213use rustc_span::{DUMMY_SP, Span};
1314
15use super::QueryStackFrameExtra;
1416use crate::dep_graph::DepContext;
1517use crate::error::CycleStack;
1618use crate::query::plumbing::CycleError;
......@@ -18,45 +20,54 @@ use crate::query::{QueryContext, QueryStackFrame};
1820
1921/// Represents a span and a query key.
2022#[derive(Clone, Debug)]
21pub struct QueryInfo {
23pub struct QueryInfo<I> {
2224 /// The span corresponding to the reason for which this query was required.
2325 pub span: Span,
24 pub query: QueryStackFrame,
26 pub query: QueryStackFrame<I>,
2527}
2628
27pub type QueryMap = FxHashMap<QueryJobId, QueryJobInfo>;
29impl<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
38pub type QueryMap<I> = FxHashMap<QueryJobId, QueryJobInfo<I>>;
2839
2940/// A value uniquely identifying an active query job.
3041#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
3142pub struct QueryJobId(pub NonZero<u64>);
3243
3344impl QueryJobId {
34 fn query(self, map: &QueryMap) -> QueryStackFrame {
45 fn query<I: Clone>(self, map: &QueryMap<I>) -> QueryStackFrame<I> {
3546 map.get(&self).unwrap().query.clone()
3647 }
3748
38 fn span(self, map: &QueryMap) -> Span {
49 fn span<I>(self, map: &QueryMap<I>) -> Span {
3950 map.get(&self).unwrap().job.span
4051 }
4152
42 fn parent(self, map: &QueryMap) -> Option<QueryJobId> {
53 fn parent<I>(self, map: &QueryMap<I>) -> Option<QueryJobId> {
4354 map.get(&self).unwrap().job.parent
4455 }
4556
46 fn latch(self, map: &QueryMap) -> Option<&QueryLatch> {
57 fn latch<I>(self, map: &QueryMap<I>) -> Option<&QueryLatch<I>> {
4758 map.get(&self).unwrap().job.latch.as_ref()
4859 }
4960}
5061
5162#[derive(Clone, Debug)]
52pub struct QueryJobInfo {
53 pub query: QueryStackFrame,
54 pub job: QueryJob,
63pub struct QueryJobInfo<I> {
64 pub query: QueryStackFrame<I>,
65 pub job: QueryJob<I>,
5566}
5667
5768/// Represents an active query job.
5869#[derive(Debug)]
59pub struct QueryJob {
70pub struct QueryJob<I> {
6071 pub id: QueryJobId,
6172
6273 /// The span corresponding to the reason for which this query was required.
......@@ -66,23 +77,23 @@ pub struct QueryJob {
6677 pub parent: Option<QueryJobId>,
6778
6879 /// The latch that is used to wait on this job.
69 latch: Option<QueryLatch>,
80 latch: Option<QueryLatch<I>>,
7081}
7182
72impl Clone for QueryJob {
83impl<I> Clone for QueryJob<I> {
7384 fn clone(&self) -> Self {
7485 Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() }
7586 }
7687}
7788
78impl QueryJob {
89impl<I> QueryJob<I> {
7990 /// Creates a new query job.
8091 #[inline]
8192 pub fn new(id: QueryJobId, span: Span, parent: Option<QueryJobId>) -> Self {
8293 QueryJob { id, span, parent, latch: None }
8394 }
8495
85 pub(super) fn latch(&mut self) -> QueryLatch {
96 pub(super) fn latch(&mut self) -> QueryLatch<I> {
8697 if self.latch.is_none() {
8798 self.latch = Some(QueryLatch::new());
8899 }
......@@ -102,12 +113,12 @@ impl QueryJob {
102113}
103114
104115impl QueryJobId {
105 pub(super) fn find_cycle_in_stack(
116 pub(super) fn find_cycle_in_stack<I: Clone>(
106117 &self,
107 query_map: QueryMap,
118 query_map: QueryMap<I>,
108119 current_job: &Option<QueryJobId>,
109120 span: Span,
110 ) -> CycleError {
121 ) -> CycleError<I> {
111122 // Find the waitee amongst `current_job` parents
112123 let mut cycle = Vec::new();
113124 let mut current_job = Option::clone(current_job);
......@@ -141,7 +152,7 @@ impl QueryJobId {
141152
142153 #[cold]
143154 #[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) {
145156 let mut depth = 1;
146157 let info = query_map.get(&self).unwrap();
147158 let dep_kind = info.query.dep_kind;
......@@ -161,31 +172,31 @@ impl QueryJobId {
161172}
162173
163174#[derive(Debug)]
164struct QueryWaiter {
175struct QueryWaiter<I> {
165176 query: Option<QueryJobId>,
166177 condvar: Condvar,
167178 span: Span,
168 cycle: Mutex<Option<CycleError>>,
179 cycle: Mutex<Option<CycleError<I>>>,
169180}
170181
171182#[derive(Debug)]
172struct QueryLatchInfo {
183struct QueryLatchInfo<I> {
173184 complete: bool,
174 waiters: Vec<Arc<QueryWaiter>>,
185 waiters: Vec<Arc<QueryWaiter<I>>>,
175186}
176187
177188#[derive(Debug)]
178pub(super) struct QueryLatch {
179 info: Arc<Mutex<QueryLatchInfo>>,
189pub(super) struct QueryLatch<I> {
190 info: Arc<Mutex<QueryLatchInfo<I>>>,
180191}
181192
182impl Clone for QueryLatch {
193impl<I> Clone for QueryLatch<I> {
183194 fn clone(&self) -> Self {
184195 Self { info: Arc::clone(&self.info) }
185196 }
186197}
187198
188impl QueryLatch {
199impl<I> QueryLatch<I> {
189200 fn new() -> Self {
190201 QueryLatch {
191202 info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })),
......@@ -198,7 +209,7 @@ impl QueryLatch {
198209 qcx: impl QueryContext,
199210 query: Option<QueryJobId>,
200211 span: Span,
201 ) -> Result<(), CycleError> {
212 ) -> Result<(), CycleError<I>> {
202213 let waiter =
203214 Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() });
204215 self.wait_on_inner(qcx, &waiter);
......@@ -213,7 +224,7 @@ impl QueryLatch {
213224 }
214225
215226 /// 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>>) {
217228 let mut info = self.info.lock();
218229 if !info.complete {
219230 // We push the waiter on to the `waiters` list. It can be accessed inside
......@@ -249,7 +260,7 @@ impl QueryLatch {
249260
250261 /// Removes a single waiter from the list of waiters.
251262 /// 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>> {
253264 let mut info = self.info.lock();
254265 debug_assert!(!info.complete);
255266 // Remove the waiter from the list of waiters
......@@ -269,7 +280,11 @@ type Waiter = (QueryJobId, usize);
269280/// For visits of resumable waiters it returns Some(Some(Waiter)) which has the
270281/// required information to resume the waiter.
271282/// If all `visit` calls returns None, this function also returns None.
272fn visit_waiters<F>(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option<Option<Waiter>>
283fn visit_waiters<I, F>(
284 query_map: &QueryMap<I>,
285 query: QueryJobId,
286 mut visit: F,
287) -> Option<Option<Waiter>>
273288where
274289 F: FnMut(Span, QueryJobId) -> Option<Option<Waiter>>,
275290{
......@@ -299,8 +314,8 @@ where
299314/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP.
300315/// If a cycle is detected, this initial value is replaced with the span causing
301316/// the cycle.
302fn cycle_check(
303 query_map: &QueryMap,
317fn cycle_check<I>(
318 query_map: &QueryMap<I>,
304319 query: QueryJobId,
305320 span: Span,
306321 stack: &mut Vec<(Span, QueryJobId)>,
......@@ -339,8 +354,8 @@ fn cycle_check(
339354/// Finds out if there's a path to the compiler root (aka. code which isn't in a query)
340355/// from `query` without going through any of the queries in `visited`.
341356/// This is achieved with a depth first search.
342fn connected_to_root(
343 query_map: &QueryMap,
357fn connected_to_root<I>(
358 query_map: &QueryMap<I>,
344359 query: QueryJobId,
345360 visited: &mut FxHashSet<QueryJobId>,
346361) -> bool {
......@@ -361,7 +376,7 @@ fn connected_to_root(
361376}
362377
363378// Deterministically pick an query from a list
364fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T
379fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap<I>, queries: &'a [T], f: F) -> &'a T
365380where
366381 F: Fn(&T) -> (Span, QueryJobId),
367382{
......@@ -386,10 +401,10 @@ where
386401/// the function return true.
387402/// If a cycle was not found, the starting query is removed from `jobs` and
388403/// the function returns false.
389fn remove_cycle(
390 query_map: &QueryMap,
404fn remove_cycle<I: Clone>(
405 query_map: &QueryMap<I>,
391406 jobs: &mut Vec<QueryJobId>,
392 wakelist: &mut Vec<Arc<QueryWaiter>>,
407 wakelist: &mut Vec<Arc<QueryWaiter<I>>>,
393408) -> bool {
394409 let mut visited = FxHashSet::default();
395410 let mut stack = Vec::new();
......@@ -490,7 +505,10 @@ fn remove_cycle(
490505/// uses a query latch and then resuming that waiter.
491506/// There may be multiple cycles involved in a deadlock, so this searches
492507/// all active queries for cycles before finally resuming all the waiters at once.
493pub fn break_query_cycles(query_map: QueryMap, registry: &rustc_thread_pool::Registry) {
508pub fn break_query_cycles<I: Clone + Debug>(
509 query_map: QueryMap<I>,
510 registry: &rustc_thread_pool::Registry,
511) {
494512 let mut wakelist = Vec::new();
495513 // It is OK per the comments:
496514 // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932
......@@ -541,7 +559,7 @@ pub fn report_cycle<'a>(
541559) -> Diag<'a> {
542560 assert!(!stack.is_empty());
543561
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);
545563
546564 let mut cycle_stack = Vec::new();
547565
......@@ -550,31 +568,31 @@ pub fn report_cycle<'a>(
550568
551569 for i in 1..stack.len() {
552570 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() });
555573 }
556574
557575 let mut cycle_usage = None;
558576 if let Some((span, ref query)) = *usage {
559577 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(),
562580 });
563581 }
564582
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 };
573591
574592 let cycle_diag = crate::error::Cycle {
575593 span,
576594 cycle_stack,
577 stack_bottom: stack[0].query.description.to_owned(),
595 stack_bottom: stack[0].query.info.description.to_owned(),
578596 alias,
579597 cycle_usage,
580598 stack_count,
......@@ -610,11 +628,12 @@ pub fn print_query_stack<Qcx: QueryContext>(
610628 let Some(query_info) = query_map.get(&query) else {
611629 break;
612630 };
631 let query_extra = qcx.lift_query_info(&query_info.query.info);
613632 if Some(count_printed) < limit_frames || limit_frames.is_none() {
614633 // Only print to stderr as many stack frames as `num_frames` when present.
615634 dcx.struct_failure_note(format!(
616635 "#{} [{:?}] {}",
617 count_printed, query_info.query.dep_kind, query_info.query.description
636 count_printed, query_info.query.dep_kind, query_extra.description
618637 ))
619638 .with_span(query_info.job.span)
620639 .emit();
......@@ -627,7 +646,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
627646 "#{} [{}] {}",
628647 count_total,
629648 qcx.dep_context().dep_kind_vtable(query_info.query.dep_kind).name,
630 query_info.query.description
649 query_extra.description
631650 );
632651 }
633652
compiler/rustc_query_system/src/query/mod.rs+90-15
......@@ -1,4 +1,10 @@
1use std::fmt::Debug;
2use std::marker::PhantomData;
3use std::mem::transmute;
4use std::sync::Arc;
5
16use rustc_data_structures::jobserver::Proxy;
7use rustc_data_structures::sync::{DynSend, DynSync};
28use rustc_errors::DiagInner;
39use rustc_hashes::Hash64;
410use rustc_hir::def::DefKind;
......@@ -36,31 +42,59 @@ pub enum CycleErrorHandling {
3642///
3743/// This is mostly used in case of cycles for error reporting.
3844#[derive(Clone, Debug)]
39pub 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>,
45pub 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
4652 pub dep_kind: DepKind,
4753 /// This hash is used to deterministically pick
4854 /// a query to remove cycles in the parallel compiler.
4955 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>,
5059}
5160
52impl QueryStackFrame {
61impl<I> QueryStackFrame<I> {
5362 #[inline]
5463 pub fn new(
55 description: String,
56 span: Option<Span>,
57 def_id: Option<DefId>,
58 def_kind: Option<DefKind>,
64 info: I,
5965 dep_kind: DepKind,
66 hash: impl FnOnce() -> Hash64,
67 def_id: Option<DefId>,
6068 def_id_for_ty_in_cycle: Option<DefId>,
61 hash: Hash64,
6269 ) -> 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)]
88pub struct QueryStackFrameExtra {
89 pub description: String,
90 span: Option<Span>,
91 pub def_kind: Option<DefKind>,
92}
93
94impl QueryStackFrameExtra {
95 #[inline]
96 pub fn new(description: String, span: Option<Span>, def_kind: Option<DefKind>) -> Self {
97 Self { description, span, def_kind }
6498 }
6599
66100 // FIXME(eddyb) Get more valid `Span`s on queries.
......@@ -73,6 +107,40 @@ impl QueryStackFrame {
73107 }
74108}
75109
110/// Track a 'side effect' for a particular query.
111/// This is used to hold a closure which can create `QueryStackFrameExtra`.
112#[derive(Clone)]
113pub 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
121impl<'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
138impl<'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
76144/// Tracks 'side effects' for a particular query.
77145/// This struct is saved to disk along with the query result,
78146/// and loaded from disk if we mark the query as green.
......@@ -92,6 +160,8 @@ pub enum QuerySideEffect {
92160}
93161
94162pub trait QueryContext: HasDepContext {
163 type QueryInfo: Clone;
164
95165 /// Gets a jobserver reference which is used to release then acquire
96166 /// a token while waiting on a query.
97167 fn jobserver_proxy(&self) -> &Proxy;
......@@ -101,7 +171,12 @@ pub trait QueryContext: HasDepContext {
101171 /// Get the query information from the TLS context.
102172 fn current_query_job(self) -> Option<QueryJobId>;
103173
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;
105180
106181 /// Load a side effect associated to the node in the previous session.
107182 fn load_side_effect(
compiler/rustc_query_system/src/query/plumbing.rs+35-26
......@@ -18,7 +18,7 @@ use rustc_errors::{Diag, FatalError, StashKey};
1818use rustc_span::{DUMMY_SP, Span};
1919use tracing::instrument;
2020
21use super::QueryConfig;
21use super::{QueryConfig, QueryStackFrameExtra};
2222use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
2323use crate::ich::StableHashingContext;
2424use crate::query::caches::QueryCache;
......@@ -32,23 +32,23 @@ fn equivalent_key<K: Eq, V>(k: &K) -> impl Fn(&(K, V)) -> bool + '_ {
3232 move |x| x.0 == *k
3333}
3434
35pub struct QueryState<K> {
36 active: Sharded<hashbrown::HashTable<(K, QueryResult)>>,
35pub struct QueryState<K, I> {
36 active: Sharded<hashbrown::HashTable<(K, QueryResult<I>)>>,
3737}
3838
3939/// Indicates the state of a query for a given key in a query map.
40enum QueryResult {
40enum QueryResult<I> {
4141 /// An already executing query. The query job can be used to await for its completion.
42 Started(QueryJob),
42 Started(QueryJob<I>),
4343
4444 /// The query panicked. Queries trying to wait on this will raise a fatal error which will
4545 /// silently panic.
4646 Poisoned,
4747}
4848
49impl QueryResult {
49impl<I> QueryResult<I> {
5050 /// Unwraps the query job expecting that it has started.
51 fn expect_job(self) -> QueryJob {
51 fn expect_job(self) -> QueryJob<I> {
5252 match self {
5353 Self::Started(job) => job,
5454 Self::Poisoned => {
......@@ -58,7 +58,7 @@ impl QueryResult {
5858 }
5959}
6060
61impl<K> QueryState<K>
61impl<K, I> QueryState<K, I>
6262where
6363 K: Eq + Hash + Copy + Debug,
6464{
......@@ -69,13 +69,13 @@ where
6969 pub fn collect_active_jobs<Qcx: Copy>(
7070 &self,
7171 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>,
7474 require_complete: bool,
7575 ) -> Option<()> {
7676 let mut active = Vec::new();
7777
78 let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult)>>| {
78 let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<I>)>>| {
7979 for (k, v) in iter.iter() {
8080 if let QueryResult::Started(ref job) = *v {
8181 active.push((*k, job.clone()));
......@@ -106,19 +106,19 @@ where
106106 }
107107}
108108
109impl<K> Default for QueryState<K> {
110 fn default() -> QueryState<K> {
109impl<K, I> Default for QueryState<K, I> {
110 fn default() -> QueryState<K, I> {
111111 QueryState { active: Default::default() }
112112 }
113113}
114114
115115/// A type representing the responsibility to execute the job in the `job` field.
116116/// This will poison the relevant query if dropped.
117struct JobOwner<'tcx, K>
117struct JobOwner<'tcx, K, I>
118118where
119119 K: Eq + Hash + Copy,
120120{
121 state: &'tcx QueryState<K>,
121 state: &'tcx QueryState<K, I>,
122122 key: K,
123123}
124124
......@@ -159,7 +159,7 @@ where
159159 }
160160 CycleErrorHandling::Stash => {
161161 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
163163 {
164164 error.stash(span, StashKey::Cycle).unwrap()
165165 } else {
......@@ -170,7 +170,7 @@ where
170170 }
171171}
172172
173impl<'tcx, K> JobOwner<'tcx, K>
173impl<'tcx, K, I> JobOwner<'tcx, K, I>
174174where
175175 K: Eq + Hash + Copy,
176176{
......@@ -207,7 +207,7 @@ where
207207 }
208208}
209209
210impl<'tcx, K> Drop for JobOwner<'tcx, K>
210impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I>
211211where
212212 K: Eq + Hash + Copy,
213213{
......@@ -235,10 +235,19 @@ where
235235}
236236
237237#[derive(Clone, Debug)]
238pub struct CycleError {
238pub struct CycleError<I = QueryStackFrameExtra> {
239239 /// 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
244impl<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 }
242251}
243252
244253/// Checks whether there is already a value for this key in the in-memory
......@@ -275,10 +284,10 @@ where
275284{
276285 // Ensure there was no errors collecting all active jobs.
277286 // 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");
279288
280289 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)
282291}
283292
284293#[inline(always)]
......@@ -287,7 +296,7 @@ fn wait_for_query<Q, Qcx>(
287296 qcx: Qcx,
288297 span: Span,
289298 key: Q::Key,
290 latch: QueryLatch,
299 latch: QueryLatch<Qcx::QueryInfo>,
291300 current: Option<QueryJobId>,
292301) -> (Q::Value, Option<DepNodeIndex>)
293302where
......@@ -327,7 +336,7 @@ where
327336
328337 (v, Some(index))
329338 }
330 Err(cycle) => (mk_cycle(query, qcx, cycle), None),
339 Err(cycle) => (mk_cycle(query, qcx, cycle.lift(qcx)), None),
331340 }
332341}
333342
......@@ -405,7 +414,7 @@ where
405414fn execute_job<Q, Qcx, const INCR: bool>(
406415 query: Q,
407416 qcx: Qcx,
408 state: &QueryState<Q::Key>,
417 state: &QueryState<Q::Key, Qcx::QueryInfo>,
409418 key: Q::Key,
410419 key_hash: u64,
411420 id: QueryJobId,
library/core/src/slice/ascii.rs+78
......@@ -62,6 +62,25 @@ impl [u8] {
6262 return false;
6363 }
6464
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 {
6584 // FIXME(const-hack): This implementation can be reverted when
6685 // `core::iter::zip` is allowed in const. The original implementation:
6786 // self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b))
......@@ -80,6 +99,65 @@ impl [u8] {
8099 true
81100 }
82101
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
83161 /// Converts this slice to its ASCII upper case equivalent in-place.
84162 ///
85163 /// 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};
55mod char_count;
66mod corpora;
77mod debug;
8mod eq_ignore_ascii_case;
89mod iter;
910
1011#[bench]
library/coretests/benches/str/eq_ignore_ascii_case.rs created+45
......@@ -0,0 +1,45 @@
1use test::{Bencher, black_box};
2
3use super::corpora::*;
4
5#[bench]
6fn 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]
13fn 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]
20fn 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]
27fn 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]
34fn 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]
41fn 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 @@
11{
22 "dependencies": {
3 "browser-ui-test": "^0.23.1",
3 "browser-ui-test": "^0.23.2",
44 "es-check": "^9.4.4",
55 "eslint": "^8.57.1",
66 "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.
7676<!-- REUSE-IgnoreEnd -->
7777
7878In the past, files began with a copyright and license notice.
79Please **omit** this notice for new files licensed under the standard terms (dual
80MIT/Apache-2.0).
79Please **omit** this notice for new files licensed under the standard terms (MIT OR Apache-2.0).
8180
8281All of the copyright notices should be gone by now, but if you come across one
8382in 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
41#![feature(core_intrinsics, funnel_shifts)]
52use std::intrinsics::*;
63
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
41// Regression test for Issue #30530: alloca's created for storing
52// intermediate scratch values during brace-less match arms need to be
63// 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
41use std::mem;
52
63enum 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]
9pub 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: (
110110 call-function: ("open-search", {})
111111 // We empty the search input in case it wasn't empty.
112112 set-property: (".search-input", {"value": ""})
113 focus: ".search-input"
113114 // We write the actual query.
114115 write-into: (".search-input", |query|)
115116 press-key: 'Enter'
tests/ui/query-system/query-cycle-printing-issue-151226.rs created+8
......@@ -0,0 +1,8 @@
1struct A<T>(std::sync::OnceLock<Self>);
2//~^ ERROR recursive type `A` has infinite size
3//~| ERROR cycle detected when computing layout of `A<()>`
4
5static B: A<()> = todo!();
6//~^ ERROR cycle occurred during layout computation
7
8fn main() {}
tests/ui/query-system/query-cycle-printing-issue-151226.stderr created+36
......@@ -0,0 +1,36 @@
1error[E0072]: recursive type `A` has infinite size
2 --> $DIR/query-cycle-printing-issue-151226.rs:1:1
3 |
4LL | struct A<T>(std::sync::OnceLock<Self>);
5 | ^^^^^^^^^^^ ------------------------- recursive without indirection
6 |
7help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
8 |
9LL | struct A<T>(Box<std::sync::OnceLock<Self>>);
10 | ++++ +
11
12error[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
20note: cycle used when checking that `B` is well-formed
21 --> $DIR/query-cycle-printing-issue-151226.rs:5:1
22 |
23LL | 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
27error[E0080]: a cycle occurred during layout computation
28 --> $DIR/query-cycle-printing-issue-151226.rs:5:1
29 |
30LL | static B: A<()> = todo!();
31 | ^^^^^^^^^^^^^^^ evaluation of `B` failed here
32
33error: aborting due to 3 previous errors
34
35Some errors have detailed explanations: E0072, E0080, E0391.
36For 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`
2trait Default {}
3use std::num::NonZero;
4fn main() {
5 NonZero();
6 format!("{}", 0);
7}
tests/ui/query-system/query-cycle-printing-issue-151358.stderr created+9
......@@ -0,0 +1,9 @@
1error[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
7error: aborting due to 1 previous error
8
9For 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`
22trait Default {
33 type Id;
44
tests/ui/resolve/query-cycle-issue-124901.stderr+3-6
......@@ -1,10 +1,7 @@
1error[E0391]: cycle detected when getting HIR ID of `Default`
1error[E0391]: cycle detected when looking up span for `Default`
22 |
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
85 = 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
96
107error: aborting due to 1 previous error