Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 69fabc3

Browse files
authored
Rollup merge of rust-lang#140641 - lcnr:opaque-type-storage-entries, r=compiler-errors
detect additional uses of opaques after writeback Based on rust-lang#140607. It's a lot harder to encounter in practice than I though 😅 😁 I've still added it with the expectation that somebody will encounter it at some point. Also modifies the `EvalCtxt` to use the same impl to detect newly added opaque types. r? `@compiler-errors`
2 parents 7b771f2 + e7979ea commit 69fabc3

File tree

14 files changed

+204
-139
lines changed

14 files changed

+204
-139
lines changed

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod gather_locals;
3232
mod intrinsicck;
3333
mod method;
3434
mod op;
35+
mod opaque_types;
3536
mod pat;
3637
mod place_op;
3738
mod rvalue_scopes;
@@ -245,9 +246,7 @@ fn typeck_with_inspect<'tcx>(
245246

246247
let typeck_results = fcx.resolve_type_vars_in_body(body);
247248

248-
// We clone the defined opaque types during writeback in the new solver
249-
// because we have to use them during normalization.
250-
let _ = fcx.infcx.take_opaque_types();
249+
fcx.detect_opaque_types_added_during_writeback();
251250

252251
// Consistency check our TypeckResults instance can hold all ItemLocalIds
253252
// it will need to hold.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use super::FnCtxt;
2+
impl<'tcx> FnCtxt<'_, 'tcx> {
3+
/// We may in theory add further uses of an opaque after cloning the opaque
4+
/// types storage during writeback when computing the defining uses.
5+
///
6+
/// Silently ignoring them is dangerous and could result in ICE or even in
7+
/// unsoundness, so we make sure we catch such cases here. There's currently
8+
/// no known code where this actually happens, even with the new solver which
9+
/// does normalize types in writeback after cloning the opaque type storage.
10+
///
11+
/// FIXME(@lcnr): I believe this should be possible in theory and would like
12+
/// an actual test here. After playing around with this for an hour, I wasn't
13+
/// able to do anything which didn't already try to normalize the opaque before
14+
/// then, either allowing compilation to succeed or causing an ambiguity error.
15+
pub(super) fn detect_opaque_types_added_during_writeback(&self) {
16+
let num_entries = self.checked_opaque_types_storage_entries.take().unwrap();
17+
for (key, hidden_type) in
18+
self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries)
19+
{
20+
let opaque_type_string = self.tcx.def_path_str(key.def_id);
21+
let msg = format!("unexpected cyclic definition of `{opaque_type_string}`");
22+
self.dcx().span_delayed_bug(hidden_type.span, msg);
23+
}
24+
let _ = self.take_opaque_types();
25+
}
26+
}

compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use std::cell::RefCell;
1+
use std::cell::{Cell, RefCell};
22
use std::ops::Deref;
33

44
use rustc_data_structures::unord::{UnordMap, UnordSet};
55
use rustc_hir::def_id::LocalDefId;
66
use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
7-
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
7+
use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt};
88
use rustc_middle::span_bug;
99
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
1010
use rustc_span::Span;
@@ -37,6 +37,11 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
3737

3838
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>,
3939

40+
// Used to detect opaque types uses added after we've already checked them.
41+
//
42+
// See [FnCtxt::detect_opaque_types_added_during_writeback] for more details.
43+
pub(super) checked_opaque_types_storage_entries: Cell<Option<OpaqueTypeStorageEntries>>,
44+
4045
/// Some additional `Sized` obligations badly affect type inference.
4146
/// These obligations are added in a later stage of typeck.
4247
/// Removing these may also cause additional complications, see #101066.
@@ -85,12 +90,14 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
8590
let infcx =
8691
tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id));
8792
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
93+
let fulfillment_cx = RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx));
8894

8995
TypeckRootCtxt {
90-
typeck_results,
91-
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)),
9296
infcx,
97+
typeck_results,
9398
locals: RefCell::new(Default::default()),
99+
fulfillment_cx,
100+
checked_opaque_types_storage_entries: Cell::new(None),
94101
deferred_sized_obligations: RefCell::new(Vec::new()),
95102
deferred_call_resolutions: RefCell::new(Default::default()),
96103
deferred_cast_checks: RefCell::new(Vec::new()),

compiler/rustc_hir_typeck/src/writeback.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -535,13 +535,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
535535
let tcx = self.tcx();
536536
// We clone the opaques instead of stealing them here as they are still used for
537537
// normalization in the next generation trait solver.
538-
//
539-
// FIXME(-Znext-solver): Opaque types defined after this would simply get dropped
540-
// at the end of typeck. While this seems unlikely to happen in practice this
541-
// should still get fixed. Either by preventing writeback from defining new opaque
542-
// types or by using this function at the end of writeback and running it as a
543-
// fixpoint.
544538
let opaque_types = self.fcx.infcx.clone_opaque_types();
539+
let num_entries = self.fcx.inner.borrow_mut().opaque_types().num_entries();
540+
let prev = self.fcx.checked_opaque_types_storage_entries.replace(Some(num_entries));
541+
debug_assert_eq!(prev, None);
545542
for (opaque_type_key, hidden_type) in opaque_types {
546543
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
547544
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);

compiler/rustc_infer/src/infer/context.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
66
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
77
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
88

9-
use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
9+
use super::{
10+
BoundRegionConversionTime, InferCtxt, OpaqueTypeStorageEntries, RegionVariableOrigin,
11+
SubregionOrigin,
12+
};
1013

1114
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
1215
type Interner = TyCtxt<'tcx>;
@@ -213,4 +216,58 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
213216
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
214217
self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span));
215218
}
219+
220+
type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries;
221+
fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries {
222+
self.inner.borrow_mut().opaque_types().num_entries()
223+
}
224+
fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
225+
self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect()
226+
}
227+
fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
228+
self.inner
229+
.borrow_mut()
230+
.opaque_types()
231+
.iter_duplicate_entries()
232+
.map(|(k, h)| (k, h.ty))
233+
.collect()
234+
}
235+
fn clone_opaque_types_added_since(
236+
&self,
237+
prev_entries: OpaqueTypeStorageEntries,
238+
) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
239+
self.inner
240+
.borrow_mut()
241+
.opaque_types()
242+
.opaque_types_added_since(prev_entries)
243+
.map(|(k, h)| (k, h.ty))
244+
.collect()
245+
}
246+
247+
fn register_hidden_type_in_storage(
248+
&self,
249+
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
250+
hidden_ty: Ty<'tcx>,
251+
span: Span,
252+
) -> Option<Ty<'tcx>> {
253+
self.register_hidden_type_in_storage(
254+
opaque_type_key,
255+
ty::OpaqueHiddenType { span, ty: hidden_ty },
256+
)
257+
}
258+
fn add_duplicate_opaque_type(
259+
&self,
260+
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
261+
hidden_ty: Ty<'tcx>,
262+
span: Span,
263+
) {
264+
self.inner
265+
.borrow_mut()
266+
.opaque_types()
267+
.add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty })
268+
}
269+
270+
fn reset_opaque_types(&self) {
271+
let _ = self.take_opaque_types();
272+
}
216273
}

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use free_regions::RegionRelations;
99
pub use freshen::TypeFreshener;
1010
use lexical_region_resolve::LexicalRegionResolutions;
1111
pub use lexical_region_resolve::RegionResolutionError;
12-
use opaque_types::OpaqueTypeStorage;
12+
pub use opaque_types::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
1313
use region_constraints::{
1414
GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound,
1515
};

compiler/rustc_infer/src/infer/opaque_types/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::traits::{self, Obligation, PredicateObligations};
1818

1919
mod table;
2020

21-
pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable};
21+
pub use table::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
2222

2323
impl<'tcx> InferCtxt<'tcx> {
2424
/// This is a backwards compatibility hack to prevent breaking changes from

compiler/rustc_infer/src/infer/opaque_types/table.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ pub struct OpaqueTypeStorage<'tcx> {
1414
duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
1515
}
1616

17+
/// The number of entries in the opaque type storage at a given point.
18+
///
19+
/// Used to check that we haven't added any new opaque types after checking
20+
/// the opaque types currently in the storage.
21+
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
22+
pub struct OpaqueTypeStorageEntries {
23+
opaque_types: usize,
24+
duplicate_entries: usize,
25+
}
26+
1727
impl<'tcx> OpaqueTypeStorage<'tcx> {
1828
#[instrument(level = "debug")]
1929
pub(crate) fn remove(
@@ -49,6 +59,24 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
4959
std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))
5060
}
5161

62+
pub fn num_entries(&self) -> OpaqueTypeStorageEntries {
63+
OpaqueTypeStorageEntries {
64+
opaque_types: self.opaque_types.len(),
65+
duplicate_entries: self.duplicate_entries.len(),
66+
}
67+
}
68+
69+
pub fn opaque_types_added_since(
70+
&self,
71+
prev_entries: OpaqueTypeStorageEntries,
72+
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
73+
self.opaque_types
74+
.iter()
75+
.skip(prev_entries.opaque_types)
76+
.map(|(k, v)| (*k, *v))
77+
.chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied())
78+
}
79+
5280
/// Only returns the opaque types from the lookup table. These are used
5381
/// when normalizing opaque types and have a unique key.
5482
///

compiler/rustc_next_trait_solver/src/delegate.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
3939
term: <Self::Interner as Interner>::Term,
4040
) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>;
4141

42-
fn clone_opaque_types_lookup_table(
43-
&self,
44-
) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
45-
fn clone_duplicate_opaque_types(
46-
&self,
47-
) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
48-
4942
fn make_deduplicated_outlives_constraints(
5043
&self,
5144
) -> Vec<ty::OutlivesPredicate<Self::Interner, <Self::Interner as Interner>::GenericArg>>;
@@ -64,20 +57,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
6457
span: <Self::Interner as Interner>::Span,
6558
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
6659
) -> <Self::Interner as Interner>::GenericArg;
67-
68-
fn register_hidden_type_in_storage(
69-
&self,
70-
opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
71-
hidden_ty: <Self::Interner as Interner>::Ty,
72-
span: <Self::Interner as Interner>::Span,
73-
) -> Option<<Self::Interner as Interner>::Ty>;
74-
fn add_duplicate_opaque_type(
75-
&self,
76-
opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
77-
hidden_ty: <Self::Interner as Interner>::Ty,
78-
span: <Self::Interner as Interner>::Span,
79-
);
80-
8160
fn add_item_bounds_for_hidden_type(
8261
&self,
8362
def_id: <Self::Interner as Interner>::DefId,
@@ -86,7 +65,6 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
8665
hidden_ty: <Self::Interner as Interner>::Ty,
8766
goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
8867
);
89-
fn reset_opaque_types(&self);
9068

9169
fn fetch_eligible_assoc_item(
9270
&self,

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,7 @@ where
250250
// to the `var_values`.
251251
let opaque_types = self
252252
.delegate
253-
.clone_opaque_types_lookup_table()
254-
.into_iter()
255-
.filter(|(a, _)| {
256-
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
257-
})
258-
.chain(self.delegate.clone_duplicate_opaque_types())
259-
.collect();
253+
.clone_opaque_types_added_since(self.initial_opaque_types_storage_num_entries);
260254

261255
ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
262256
}

0 commit comments

Comments
 (0)