Skip to content

Commit 767d253

Browse files
committed
Make crate_inherent_impls fallible and stop using track_errors for it
1 parent d74b60d commit 767d253

File tree

19 files changed

+115
-73
lines changed

19 files changed

+115
-73
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14471447
}
14481448

14491449
let candidates: Vec<_> = tcx
1450-
.inherent_impls(adt_did)
1450+
.inherent_impls(adt_did)?
14511451
.iter()
14521452
.filter_map(|&impl_| Some((impl_, self.lookup_assoc_ty_unchecked(name, block, impl_)?)))
14531453
.collect();

compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs

+48-31
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,41 @@ use rustc_hir::def_id::{DefId, LocalDefId};
1313
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
1414
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
1515
use rustc_span::symbol::sym;
16+
use rustc_span::ErrorGuaranteed;
1617

1718
use crate::errors;
1819

1920
/// On-demand query: yields a map containing all types mapped to their inherent impls.
20-
pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
21+
pub fn crate_inherent_impls(
22+
tcx: TyCtxt<'_>,
23+
(): (),
24+
) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> {
2125
let mut collect = InherentCollect { tcx, impls_map: Default::default() };
26+
let mut res = Ok(());
2227
for id in tcx.hir().items() {
23-
collect.check_item(id);
28+
res = res.and(collect.check_item(id));
2429
}
25-
collect.impls_map
30+
res?;
31+
Ok(tcx.arena.alloc(collect.impls_map))
2632
}
2733

28-
pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
29-
let crate_map = tcx.crate_inherent_impls(());
30-
tcx.arena.alloc_from_iter(
34+
pub fn crate_incoherent_impls(
35+
tcx: TyCtxt<'_>,
36+
simp: SimplifiedType,
37+
) -> Result<&[DefId], ErrorGuaranteed> {
38+
let crate_map = tcx.crate_inherent_impls(())?;
39+
Ok(tcx.arena.alloc_from_iter(
3140
crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()),
32-
)
41+
))
3342
}
3443

3544
/// On-demand query: yields a vector of the inherent impls for a specific type.
36-
pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] {
37-
let crate_map = tcx.crate_inherent_impls(());
38-
match crate_map.inherent_impls.get(&ty_def_id) {
45+
pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> Result<&[DefId], ErrorGuaranteed> {
46+
let crate_map = tcx.crate_inherent_impls(())?;
47+
Ok(match crate_map.inherent_impls.get(&ty_def_id) {
3948
Some(v) => &v[..],
4049
None => &[],
41-
}
50+
})
4251
}
4352

4453
struct InherentCollect<'tcx> {
@@ -47,33 +56,36 @@ struct InherentCollect<'tcx> {
4756
}
4857

4958
impl<'tcx> InherentCollect<'tcx> {
50-
fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) {
59+
fn check_def_id(
60+
&mut self,
61+
impl_def_id: LocalDefId,
62+
self_ty: Ty<'tcx>,
63+
ty_def_id: DefId,
64+
) -> Result<(), ErrorGuaranteed> {
5165
if let Some(ty_def_id) = ty_def_id.as_local() {
5266
// Add the implementation to the mapping from implementation to base
5367
// type def ID, if there is a base type for this implementation and
5468
// the implementation does not have any associated traits.
5569
let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default();
5670
vec.push(impl_def_id.to_def_id());
57-
return;
71+
return Ok(());
5872
}
5973

6074
if self.tcx.features().rustc_attrs {
6175
let items = self.tcx.associated_item_def_ids(impl_def_id);
6276

6377
if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
6478
let impl_span = self.tcx.def_span(impl_def_id);
65-
self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span });
66-
return;
79+
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span }));
6780
}
6881

6982
for &impl_item in items {
7083
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
7184
let impl_span = self.tcx.def_span(impl_def_id);
72-
self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant {
85+
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant {
7386
span: impl_span,
7487
help_span: self.tcx.def_span(impl_item),
75-
});
76-
return;
88+
}));
7789
}
7890
}
7991

@@ -82,24 +94,28 @@ impl<'tcx> InherentCollect<'tcx> {
8294
} else {
8395
bug!("unexpected self type: {:?}", self_ty);
8496
}
97+
Ok(())
8598
} else {
8699
let impl_span = self.tcx.def_span(impl_def_id);
87-
self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span });
100+
Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }))
88101
}
89102
}
90103

91-
fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) {
104+
fn check_primitive_impl(
105+
&mut self,
106+
impl_def_id: LocalDefId,
107+
ty: Ty<'tcx>,
108+
) -> Result<(), ErrorGuaranteed> {
92109
let items = self.tcx.associated_item_def_ids(impl_def_id);
93110
if !self.tcx.hir().rustc_coherence_is_core() {
94111
if self.tcx.features().rustc_attrs {
95112
for &impl_item in items {
96113
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
97114
let span = self.tcx.def_span(impl_def_id);
98-
self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive {
115+
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive {
99116
span,
100117
help_span: self.tcx.def_span(impl_item),
101-
});
102-
return;
118+
}));
103119
}
104120
}
105121
} else {
@@ -108,8 +124,7 @@ impl<'tcx> InherentCollect<'tcx> {
108124
if let ty::Ref(_, subty, _) = ty.kind() {
109125
note = Some(errors::InherentPrimitiveTyNote { subty: *subty });
110126
}
111-
self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note });
112-
return;
127+
return Err(self.tcx.dcx().emit_err(errors::InherentPrimitiveTy { span, note }));
113128
}
114129
}
115130

@@ -118,11 +133,12 @@ impl<'tcx> InherentCollect<'tcx> {
118133
} else {
119134
bug!("unexpected primitive type: {:?}", ty);
120135
}
136+
Ok(())
121137
}
122138

123-
fn check_item(&mut self, id: hir::ItemId) {
139+
fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> {
124140
if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) {
125-
return;
141+
return Ok(());
126142
}
127143

128144
let id = id.owner_id.def_id;
@@ -132,10 +148,10 @@ impl<'tcx> InherentCollect<'tcx> {
132148
ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
133149
ty::Foreign(did) => self.check_def_id(id, self_ty, did),
134150
ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
135-
self.check_def_id(id, self_ty, data.principal_def_id().unwrap());
151+
self.check_def_id(id, self_ty, data.principal_def_id().unwrap())
136152
}
137153
ty::Dynamic(..) => {
138-
self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span });
154+
Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }))
139155
}
140156
ty::Bool
141157
| ty::Char
@@ -151,7 +167,7 @@ impl<'tcx> InherentCollect<'tcx> {
151167
| ty::FnPtr(_)
152168
| ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
153169
ty::Alias(..) | ty::Param(_) => {
154-
self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span });
170+
Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }))
155171
}
156172
ty::FnDef(..)
157173
| ty::Closure(..)
@@ -162,7 +178,8 @@ impl<'tcx> InherentCollect<'tcx> {
162178
| ty::Infer(_) => {
163179
bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty);
164180
}
165-
ty::Error(_) => {}
181+
// We could bail out here, but that will silence other useful errors.
182+
ty::Error(_) => Ok(()),
166183
}
167184
}
168185
}

compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
168168
return Ok(());
169169
}
170170

171-
let impls = self.tcx.inherent_impls(id.owner_id);
171+
let impls = self.tcx.inherent_impls(id.owner_id)?;
172172

173173
let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id());
174174

compiler/rustc_hir_analysis/src/lib.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
185185
for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
186186
tcx.ensure().coherent_trait(trait_def_id);
187187
}
188-
189-
// these queries are executed for side-effects (error reporting):
190-
tcx.ensure().crate_inherent_impls(());
191188
}))
189+
// these queries are executed for side-effects (error reporting):
190+
.and(tcx.ensure().crate_inherent_impls(()))
192191
.and(tcx.ensure().crate_inherent_impls_overlap_check(()))
193192
})?;
194193

compiler/rustc_hir_typeck/src/expr.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2104,7 +2104,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21042104
let mut items = self
21052105
.tcx
21062106
.inherent_impls(def_id)
2107-
.iter()
2107+
.into_iter()
2108+
.flatten()
21082109
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
21092110
// Only assoc fn with no receivers.
21102111
.filter(|item| {

compiler/rustc_hir_typeck/src/method/probe.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -711,14 +711,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
711711
let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else {
712712
bug!("unexpected incoherent type: {:?}", self_ty)
713713
};
714-
for &impl_def_id in self.tcx.incoherent_impls(simp) {
714+
for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
715715
self.assemble_inherent_impl_probe(impl_def_id);
716716
}
717717
}
718718

719719
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
720-
let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id);
721-
for &impl_def_id in impl_def_ids.iter() {
720+
let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten();
721+
for &impl_def_id in impl_def_ids {
722722
self.assemble_inherent_impl_probe(impl_def_id);
723723
}
724724
}

compiler/rustc_hir_typeck/src/method/suggest.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
359359
if let ty::Adt(adt_def, _) = ty.kind() {
360360
self.tcx
361361
.inherent_impls(adt_def.did())
362-
.iter()
362+
.into_iter()
363+
.flatten()
363364
.any(|def_id| self.associated_value(*def_id, item_name).is_some())
364365
} else {
365366
false
@@ -1043,7 +1044,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10431044
let mut inherent_impls_candidate = self
10441045
.tcx
10451046
.inherent_impls(adt.did())
1046-
.iter()
1047+
.into_iter()
1048+
.flatten()
10471049
.copied()
10481050
.filter(|def_id| {
10491051
if let Some(assoc) = self.associated_value(*def_id, item_name) {
@@ -1098,7 +1100,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10981100
"the {item_kind} was found for\n{type_candidates}{additional_types}"
10991101
));
11001102
} else {
1101-
'outer: for inherent_impl_did in self.tcx.inherent_impls(adt.did()) {
1103+
'outer: for inherent_impl_did in
1104+
self.tcx.inherent_impls(adt.did()).into_iter().flatten()
1105+
{
11021106
for inherent_method in
11031107
self.tcx.associated_items(inherent_impl_did).in_definition_order()
11041108
{
@@ -1452,9 +1456,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14521456
let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
14531457
return;
14541458
};
1455-
let mut items = self
1456-
.tcx
1457-
.inherent_impls(adt_def.did())
1459+
// FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case.
1460+
let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return };
1461+
let mut items = impls
14581462
.iter()
14591463
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
14601464
// Only assoc fn with no receivers.
@@ -1818,7 +1822,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18181822
simplify_type(tcx, ty, TreatParams::AsCandidateKey)
18191823
.and_then(|simp| {
18201824
tcx.incoherent_impls(simp)
1821-
.iter()
1825+
.into_iter()
1826+
.flatten()
18221827
.find_map(|&id| self.associated_value(id, item_name))
18231828
})
18241829
.is_some()

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ provide! { tcx, def_id, other, cdata,
283283
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
284284
}
285285
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
286-
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
286+
inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) }
287287
item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
288288
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
289289
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
@@ -328,7 +328,7 @@ provide! { tcx, def_id, other, cdata,
328328
traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
329329
trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
330330
implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
331-
crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
331+
crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) }
332332

333333
dep_kind => { cdata.dep_kind }
334334
module_children => {

compiler/rustc_metadata/src/rmeta/encoder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14851485
}
14861486

14871487
let inherent_impls = tcx.with_stable_hashing_context(|hcx| {
1488-
tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)
1488+
tcx.crate_inherent_impls(()).unwrap().inherent_impls.to_sorted(&hcx, true)
14891489
});
14901490
for (def_id, impls) in inherent_impls {
14911491
record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
@@ -2028,7 +2028,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20282028
empty_proc_macro!(self);
20292029
let tcx = self.tcx;
20302030
let all_impls = tcx.with_stable_hashing_context(|hcx| {
2031-
tcx.crate_inherent_impls(()).incoherent_impls.to_sorted(&hcx, true)
2031+
tcx.crate_inherent_impls(()).unwrap().incoherent_impls.to_sorted(&hcx, true)
20322032
});
20332033

20342034
let all_impls: Vec<_> = all_impls

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ macro_rules! arena_types {
114114
[] mod_child: rustc_middle::metadata::ModChild,
115115
[] features: rustc_feature::Features,
116116
[decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph,
117+
[] crate_inherent_impls: rustc_middle::ty::CrateInherentImpls,
117118
]);
118119
)
119120
}

compiler/rustc_middle/src/query/erase.rs

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ impl<T> EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
7878
type Result = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
7979
}
8080

81+
impl<T> EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> {
82+
type Result = [u8; size_of::<Result<&'static [()], rustc_errors::ErrorGuaranteed>>()];
83+
}
84+
8185
impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
8286
type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
8387
}

compiler/rustc_middle/src/query/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -859,13 +859,13 @@ rustc_queries! {
859859
/// Maps a `DefId` of a type to a list of its inherent impls.
860860
/// Contains implementations of methods that are inherent to a type.
861861
/// Methods in these implementations don't need to be exported.
862-
query inherent_impls(key: DefId) -> &'tcx [DefId] {
862+
query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> {
863863
desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) }
864864
cache_on_disk_if { key.is_local() }
865865
separate_provide_extern
866866
}
867867

868-
query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] {
868+
query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> {
869869
desc { |tcx| "collecting all inherent impls for `{:?}`", key }
870870
}
871871

@@ -1012,9 +1012,9 @@ rustc_queries! {
10121012

10131013
/// Gets a complete map from all types to their inherent impls.
10141014
/// Not meant to be used directly outside of coherence.
1015-
query crate_inherent_impls(k: ()) -> &'tcx CrateInherentImpls {
1016-
arena_cache
1015+
query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> {
10171016
desc { "finding all inherent impls defined in crate" }
1017+
ensure_forwards_result_if_red
10181018
}
10191019

10201020
/// Checks all types in the crate for overlap in their inherent impls. Reports errors.
@@ -1647,7 +1647,7 @@ rustc_queries! {
16471647
///
16481648
/// Do not call this directly, but instead use the `incoherent_impls` query.
16491649
/// This query is only used to get the data necessary for that query.
1650-
query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] {
1650+
query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> {
16511651
desc { |tcx| "collecting all impls for a type in a crate" }
16521652
separate_provide_extern
16531653
}

0 commit comments

Comments
 (0)