about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-01-11 10:05:12 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-01-11 20:34:59 +0000
commit5461836281e86ba34b3164c4d20ee7ab907d39da (patch)
tree79734541fda8c4c4ff94165d07cff633cade529a
parent3a6bf351a39b35a662022c151621b932b4ae0bc8 (diff)
downloadrust-5461836281e86ba34b3164c4d20ee7ab907d39da.tar.gz
rust-5461836281e86ba34b3164c4d20ee7ab907d39da.zip
`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
-rw-r--r--compiler/rustc_middle/src/arena.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs3
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs9
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs68
5 files changed, 49 insertions, 46 deletions
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 0ab09dadf58..8a4fd01437f 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -113,6 +113,7 @@ macro_rules! arena_types {
             [] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,
             [] mod_child: rustc_middle::metadata::ModChild,
             [] features: rustc_feature::Features,
+            [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph,
         ]);
     )
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0e3b9984423..1dc77220881 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1294,8 +1294,7 @@ rustc_queries! {
         desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) }
     }
 
-    query specialization_graph_of(trait_id: DefId) -> &'tcx specialization_graph::Graph {
-        arena_cache
+    query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> {
         desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
         cache_on_disk_if { true }
     }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 31db4ba62fb..f4dfbe059eb 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -786,6 +786,15 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsm
     }
 }
 
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+    for &'tcx crate::traits::specialization_graph::Graph
+{
+    #[inline]
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
+        RefDecodable::decode(d)
+    }
+}
+
 macro_rules! impl_ref_decoder {
     (<$tcx:tt> $($ty:ty,)*) => {
         $(impl<'a, $tcx> Decodable<CacheDecoder<'a, $tcx>> for &$tcx [$ty] {
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index 898258445dc..ba29d4040a1 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -30,18 +30,16 @@ pub struct Graph {
 
     /// The "root" impls are found by looking up the trait's def_id.
     pub children: DefIdMap<Children>,
-
-    /// Whether an error was emitted while constructing the graph.
-    pub has_errored: Option<ErrorGuaranteed>,
 }
 
 impl Graph {
     pub fn new() -> Graph {
-        Graph { parent: Default::default(), children: Default::default(), has_errored: None }
+        Graph { parent: Default::default(), children: Default::default() }
     }
 
     /// The parent of a given impl, which is the `DefId` of the trait when the
     /// impl is a "specialization root".
+    #[track_caller]
     pub fn parent(&self, child: DefId) -> DefId {
         *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {child:?}"))
     }
@@ -255,13 +253,9 @@ pub fn ancestors(
     trait_def_id: DefId,
     start_from_impl: DefId,
 ) -> Result<Ancestors<'_>, ErrorGuaranteed> {
-    let specialization_graph = tcx.specialization_graph_of(trait_def_id);
+    let specialization_graph = tcx.specialization_graph_of(trait_def_id)?;
 
-    if let Some(reported) = specialization_graph.has_errored {
-        Err(reported)
-    } else if let Err(reported) =
-        tcx.type_of(start_from_impl).instantiate_identity().error_reported()
-    {
+    if let Err(reported) = tcx.type_of(start_from_impl).instantiate_identity().error_reported() {
         Err(reported)
     } else {
         Ok(Ancestors {
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 10329c623b3..200d022c80c 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
 
 use super::util;
 use super::SelectionContext;
@@ -258,7 +258,7 @@ fn fulfill_implication<'tcx>(
 pub(super) fn specialization_graph_provider(
     tcx: TyCtxt<'_>,
     trait_id: DefId,
-) -> specialization_graph::Graph {
+) -> Result<&'_ specialization_graph::Graph, ErrorGuaranteed> {
     let mut sg = specialization_graph::Graph::new();
     let overlap_mode = specialization_graph::OverlapMode::get(tcx, trait_id);
 
@@ -271,6 +271,8 @@ pub(super) fn specialization_graph_provider(
     trait_impls
         .sort_unstable_by_key(|def_id| (-(def_id.krate.as_u32() as i64), def_id.index.index()));
 
+    let mut errored = Ok(());
+
     for impl_def_id in trait_impls {
         if let Some(impl_def_id) = impl_def_id.as_local() {
             // This is where impl overlap checking happens:
@@ -283,15 +285,21 @@ pub(super) fn specialization_graph_provider(
             };
 
             if let Some(overlap) = overlap {
-                report_overlap_conflict(tcx, overlap, impl_def_id, used_to_be_allowed, &mut sg);
+                errored = errored.and(report_overlap_conflict(
+                    tcx,
+                    overlap,
+                    impl_def_id,
+                    used_to_be_allowed,
+                ));
             }
         } else {
             let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
             sg.record_impl_from_cstore(tcx, parent, impl_def_id)
         }
     }
+    errored?;
 
-    sg
+    Ok(tcx.arena.alloc(sg))
 }
 
 // This function is only used when
@@ -304,36 +312,31 @@ fn report_overlap_conflict<'tcx>(
     overlap: OverlapError<'tcx>,
     impl_def_id: LocalDefId,
     used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
-    sg: &mut specialization_graph::Graph,
-) {
+) -> Result<(), ErrorGuaranteed> {
     let impl_polarity = tcx.impl_polarity(impl_def_id.to_def_id());
     let other_polarity = tcx.impl_polarity(overlap.with_impl);
     match (impl_polarity, other_polarity) {
         (ty::ImplPolarity::Negative, ty::ImplPolarity::Positive) => {
-            report_negative_positive_conflict(
+            Err(report_negative_positive_conflict(
                 tcx,
                 &overlap,
                 impl_def_id,
                 impl_def_id.to_def_id(),
                 overlap.with_impl,
-                sg,
-            );
+            ))
         }
 
         (ty::ImplPolarity::Positive, ty::ImplPolarity::Negative) => {
-            report_negative_positive_conflict(
+            Err(report_negative_positive_conflict(
                 tcx,
                 &overlap,
                 impl_def_id,
                 overlap.with_impl,
                 impl_def_id.to_def_id(),
-                sg,
-            );
+            ))
         }
 
-        _ => {
-            report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed, sg);
-        }
+        _ => report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed),
     }
 }
 
@@ -343,16 +346,16 @@ fn report_negative_positive_conflict<'tcx>(
     local_impl_def_id: LocalDefId,
     negative_impl_def_id: DefId,
     positive_impl_def_id: DefId,
-    sg: &mut specialization_graph::Graph,
-) {
-    let err = tcx.dcx().create_err(NegativePositiveConflict {
-        impl_span: tcx.def_span(local_impl_def_id),
-        trait_desc: overlap.trait_ref,
-        self_ty: overlap.self_ty,
-        negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
-        positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
-    });
-    sg.has_errored = Some(err.emit());
+) -> ErrorGuaranteed {
+    tcx.dcx()
+        .create_err(NegativePositiveConflict {
+            impl_span: tcx.def_span(local_impl_def_id),
+            trait_desc: overlap.trait_ref,
+            self_ty: overlap.self_ty,
+            negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
+            positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
+        })
+        .emit()
 }
 
 fn report_conflicting_impls<'tcx>(
@@ -360,8 +363,7 @@ fn report_conflicting_impls<'tcx>(
     overlap: OverlapError<'tcx>,
     impl_def_id: LocalDefId,
     used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
-    sg: &mut specialization_graph::Graph,
-) {
+) -> Result<(), ErrorGuaranteed> {
     let impl_span = tcx.def_span(impl_def_id);
 
     // Work to be done after we've built the DiagnosticBuilder. We have to define it
@@ -429,14 +431,11 @@ fn report_conflicting_impls<'tcx>(
                 let mut err = tcx.dcx().struct_span_err(impl_span, msg);
                 err.code(error_code!(E0119));
                 decorate(tcx, &overlap, impl_span, &mut err);
-                Some(err.emit())
+                err.emit()
             } else {
-                Some(
-                    tcx.dcx()
-                        .span_delayed_bug(impl_span, "impl should have failed the orphan check"),
-                )
+                tcx.dcx().span_delayed_bug(impl_span, "impl should have failed the orphan check")
             };
-            sg.has_errored = reported;
+            Err(reported)
         }
         Some(kind) => {
             let lint = match kind {
@@ -452,8 +451,9 @@ fn report_conflicting_impls<'tcx>(
                     decorate(tcx, &overlap, impl_span, err);
                 },
             );
+            Ok(())
         }
-    };
+    }
 }
 
 /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a