Skip to content

Commit 5461836

Browse files
committed
specialization_graph_of's errored field is used in the only call site, and used to immediately throw away the rest of the value. Let's use Result to statically signal that this is happening
1 parent 3a6bf35 commit 5461836

File tree

5 files changed

+49
-46
lines changed

5 files changed

+49
-46
lines changed

compiler/rustc_middle/src/arena.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ macro_rules! arena_types {
113113
[] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,
114114
[] mod_child: rustc_middle::metadata::ModChild,
115115
[] features: rustc_feature::Features,
116+
[decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph,
116117
]);
117118
)
118119
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,8 +1294,7 @@ rustc_queries! {
12941294
desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) }
12951295
}
12961296

1297-
query specialization_graph_of(trait_id: DefId) -> &'tcx specialization_graph::Graph {
1298-
arena_cache
1297+
query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> {
12991298
desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
13001299
cache_on_disk_if { true }
13011300
}

compiler/rustc_middle/src/query/on_disk_cache.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,15 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsm
786786
}
787787
}
788788

789+
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
790+
for &'tcx crate::traits::specialization_graph::Graph
791+
{
792+
#[inline]
793+
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
794+
RefDecodable::decode(d)
795+
}
796+
}
797+
789798
macro_rules! impl_ref_decoder {
790799
(<$tcx:tt> $($ty:ty,)*) => {
791800
$(impl<'a, $tcx> Decodable<CacheDecoder<'a, $tcx>> for &$tcx [$ty] {

compiler/rustc_middle/src/traits/specialization_graph.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,16 @@ pub struct Graph {
3030

3131
/// The "root" impls are found by looking up the trait's def_id.
3232
pub children: DefIdMap<Children>,
33-
34-
/// Whether an error was emitted while constructing the graph.
35-
pub has_errored: Option<ErrorGuaranteed>,
3633
}
3734

3835
impl Graph {
3936
pub fn new() -> Graph {
40-
Graph { parent: Default::default(), children: Default::default(), has_errored: None }
37+
Graph { parent: Default::default(), children: Default::default() }
4138
}
4239

4340
/// The parent of a given impl, which is the `DefId` of the trait when the
4441
/// impl is a "specialization root".
42+
#[track_caller]
4543
pub fn parent(&self, child: DefId) -> DefId {
4644
*self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {child:?}"))
4745
}
@@ -255,13 +253,9 @@ pub fn ancestors(
255253
trait_def_id: DefId,
256254
start_from_impl: DefId,
257255
) -> Result<Ancestors<'_>, ErrorGuaranteed> {
258-
let specialization_graph = tcx.specialization_graph_of(trait_def_id);
256+
let specialization_graph = tcx.specialization_graph_of(trait_def_id)?;
259257

260-
if let Some(reported) = specialization_graph.has_errored {
261-
Err(reported)
262-
} else if let Err(reported) =
263-
tcx.type_of(start_from_impl).instantiate_identity().error_reported()
264-
{
258+
if let Err(reported) = tcx.type_of(start_from_impl).instantiate_identity().error_reported() {
265259
Err(reported)
266260
} else {
267261
Ok(Ancestors {

compiler/rustc_trait_selection/src/traits/specialize/mod.rs

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
2626
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
2727
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
2828
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
29-
use rustc_span::{Span, DUMMY_SP};
29+
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
3030

3131
use super::util;
3232
use super::SelectionContext;
@@ -258,7 +258,7 @@ fn fulfill_implication<'tcx>(
258258
pub(super) fn specialization_graph_provider(
259259
tcx: TyCtxt<'_>,
260260
trait_id: DefId,
261-
) -> specialization_graph::Graph {
261+
) -> Result<&'_ specialization_graph::Graph, ErrorGuaranteed> {
262262
let mut sg = specialization_graph::Graph::new();
263263
let overlap_mode = specialization_graph::OverlapMode::get(tcx, trait_id);
264264

@@ -271,6 +271,8 @@ pub(super) fn specialization_graph_provider(
271271
trait_impls
272272
.sort_unstable_by_key(|def_id| (-(def_id.krate.as_u32() as i64), def_id.index.index()));
273273

274+
let mut errored = Ok(());
275+
274276
for impl_def_id in trait_impls {
275277
if let Some(impl_def_id) = impl_def_id.as_local() {
276278
// This is where impl overlap checking happens:
@@ -283,15 +285,21 @@ pub(super) fn specialization_graph_provider(
283285
};
284286

285287
if let Some(overlap) = overlap {
286-
report_overlap_conflict(tcx, overlap, impl_def_id, used_to_be_allowed, &mut sg);
288+
errored = errored.and(report_overlap_conflict(
289+
tcx,
290+
overlap,
291+
impl_def_id,
292+
used_to_be_allowed,
293+
));
287294
}
288295
} else {
289296
let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
290297
sg.record_impl_from_cstore(tcx, parent, impl_def_id)
291298
}
292299
}
300+
errored?;
293301

294-
sg
302+
Ok(tcx.arena.alloc(sg))
295303
}
296304

297305
// This function is only used when
@@ -304,36 +312,31 @@ fn report_overlap_conflict<'tcx>(
304312
overlap: OverlapError<'tcx>,
305313
impl_def_id: LocalDefId,
306314
used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
307-
sg: &mut specialization_graph::Graph,
308-
) {
315+
) -> Result<(), ErrorGuaranteed> {
309316
let impl_polarity = tcx.impl_polarity(impl_def_id.to_def_id());
310317
let other_polarity = tcx.impl_polarity(overlap.with_impl);
311318
match (impl_polarity, other_polarity) {
312319
(ty::ImplPolarity::Negative, ty::ImplPolarity::Positive) => {
313-
report_negative_positive_conflict(
320+
Err(report_negative_positive_conflict(
314321
tcx,
315322
&overlap,
316323
impl_def_id,
317324
impl_def_id.to_def_id(),
318325
overlap.with_impl,
319-
sg,
320-
);
326+
))
321327
}
322328

323329
(ty::ImplPolarity::Positive, ty::ImplPolarity::Negative) => {
324-
report_negative_positive_conflict(
330+
Err(report_negative_positive_conflict(
325331
tcx,
326332
&overlap,
327333
impl_def_id,
328334
overlap.with_impl,
329335
impl_def_id.to_def_id(),
330-
sg,
331-
);
336+
))
332337
}
333338

334-
_ => {
335-
report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed, sg);
336-
}
339+
_ => report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed),
337340
}
338341
}
339342

@@ -343,25 +346,24 @@ fn report_negative_positive_conflict<'tcx>(
343346
local_impl_def_id: LocalDefId,
344347
negative_impl_def_id: DefId,
345348
positive_impl_def_id: DefId,
346-
sg: &mut specialization_graph::Graph,
347-
) {
348-
let err = tcx.dcx().create_err(NegativePositiveConflict {
349-
impl_span: tcx.def_span(local_impl_def_id),
350-
trait_desc: overlap.trait_ref,
351-
self_ty: overlap.self_ty,
352-
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
353-
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
354-
});
355-
sg.has_errored = Some(err.emit());
349+
) -> ErrorGuaranteed {
350+
tcx.dcx()
351+
.create_err(NegativePositiveConflict {
352+
impl_span: tcx.def_span(local_impl_def_id),
353+
trait_desc: overlap.trait_ref,
354+
self_ty: overlap.self_ty,
355+
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
356+
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
357+
})
358+
.emit()
356359
}
357360

358361
fn report_conflicting_impls<'tcx>(
359362
tcx: TyCtxt<'tcx>,
360363
overlap: OverlapError<'tcx>,
361364
impl_def_id: LocalDefId,
362365
used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
363-
sg: &mut specialization_graph::Graph,
364-
) {
366+
) -> Result<(), ErrorGuaranteed> {
365367
let impl_span = tcx.def_span(impl_def_id);
366368

367369
// Work to be done after we've built the DiagnosticBuilder. We have to define it
@@ -429,14 +431,11 @@ fn report_conflicting_impls<'tcx>(
429431
let mut err = tcx.dcx().struct_span_err(impl_span, msg);
430432
err.code(error_code!(E0119));
431433
decorate(tcx, &overlap, impl_span, &mut err);
432-
Some(err.emit())
434+
err.emit()
433435
} else {
434-
Some(
435-
tcx.dcx()
436-
.span_delayed_bug(impl_span, "impl should have failed the orphan check"),
437-
)
436+
tcx.dcx().span_delayed_bug(impl_span, "impl should have failed the orphan check")
438437
};
439-
sg.has_errored = reported;
438+
Err(reported)
440439
}
441440
Some(kind) => {
442441
let lint = match kind {
@@ -452,8 +451,9 @@ fn report_conflicting_impls<'tcx>(
452451
decorate(tcx, &overlap, impl_span, err);
453452
},
454453
);
454+
Ok(())
455455
}
456-
};
456+
}
457457
}
458458

459459
/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a

0 commit comments

Comments
 (0)