Skip to content

Commit ebba894

Browse files
authored
Rollup merge of #95731 - oli-obk:lazy_tait_regression, r=compiler-errors
Check that all hidden types are the same and then deduplicate them. fixes #95538 This used to trigger a sanity check. Now we accept that there may be multiple places where a hidden type is constrained and we merge all of these at the end. Ideally we'd merge eagerly, but that is a larger refactoring that I don't want to put into a backport
2 parents d2697e3 + 27dc503 commit ebba894

File tree

2 files changed

+110
-62
lines changed

2 files changed

+110
-62
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+80-62
Original file line numberDiff line numberDiff line change
@@ -55,75 +55,93 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5555
infcx: &InferCtxt<'_, 'tcx>,
5656
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
5757
) -> VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> {
58-
opaque_ty_decls
59-
.into_iter()
60-
.map(|(opaque_type_key, (concrete_type, origin))| {
61-
let substs = opaque_type_key.substs;
62-
debug!(?concrete_type, ?substs);
58+
let mut result: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> = VecMap::new();
59+
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
60+
let substs = opaque_type_key.substs;
61+
debug!(?concrete_type, ?substs);
6362

64-
let mut subst_regions = vec![self.universal_regions.fr_static];
65-
let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
66-
if let ty::RePlaceholder(..) = region.kind() {
67-
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
68-
return region;
63+
let mut subst_regions = vec![self.universal_regions.fr_static];
64+
let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
65+
if let ty::RePlaceholder(..) = region.kind() {
66+
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
67+
return region;
68+
}
69+
let vid = self.to_region_vid(region);
70+
trace!(?vid);
71+
let scc = self.constraint_sccs.scc(vid);
72+
trace!(?scc);
73+
match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| {
74+
self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?)
75+
}) {
76+
Some(region) => {
77+
let vid = self.universal_regions.to_region_vid(region);
78+
subst_regions.push(vid);
79+
region
6980
}
70-
let vid = self.to_region_vid(region);
71-
trace!(?vid);
72-
let scc = self.constraint_sccs.scc(vid);
73-
trace!(?scc);
74-
match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| {
75-
self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?)
76-
}) {
77-
Some(region) => {
78-
let vid = self.universal_regions.to_region_vid(region);
79-
subst_regions.push(vid);
80-
region
81-
}
82-
None => {
83-
subst_regions.push(vid);
84-
infcx.tcx.sess.delay_span_bug(
85-
concrete_type.span,
86-
"opaque type with non-universal region substs",
87-
);
88-
infcx.tcx.lifetimes.re_static
89-
}
81+
None => {
82+
subst_regions.push(vid);
83+
infcx.tcx.sess.delay_span_bug(
84+
concrete_type.span,
85+
"opaque type with non-universal region substs",
86+
);
87+
infcx.tcx.lifetimes.re_static
9088
}
91-
});
89+
}
90+
});
9291

93-
subst_regions.sort();
94-
subst_regions.dedup();
92+
subst_regions.sort();
93+
subst_regions.dedup();
9594

96-
let universal_concrete_type =
97-
infcx.tcx.fold_regions(concrete_type, &mut false, |region, _| match *region {
98-
ty::ReVar(vid) => subst_regions
99-
.iter()
100-
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
101-
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
102-
.unwrap_or(infcx.tcx.lifetimes.re_root_empty),
103-
_ => region,
104-
});
95+
let universal_concrete_type =
96+
infcx.tcx.fold_regions(concrete_type, &mut false, |region, _| match *region {
97+
ty::ReVar(vid) => subst_regions
98+
.iter()
99+
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
100+
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
101+
.unwrap_or(infcx.tcx.lifetimes.re_root_empty),
102+
_ => region,
103+
});
105104

106-
debug!(?universal_concrete_type, ?universal_substs);
105+
debug!(?universal_concrete_type, ?universal_substs);
107106

108-
let opaque_type_key =
109-
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
110-
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
111-
opaque_type_key,
112-
universal_concrete_type,
113-
);
114-
let ty = if check_opaque_type_parameter_valid(
115-
infcx.tcx,
116-
opaque_type_key,
117-
origin,
118-
concrete_type.span,
119-
) {
120-
remapped_type
121-
} else {
122-
infcx.tcx.ty_error()
123-
};
124-
(opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span })
125-
})
126-
.collect()
107+
let opaque_type_key =
108+
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
109+
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
110+
opaque_type_key,
111+
universal_concrete_type,
112+
);
113+
let ty = if check_opaque_type_parameter_valid(
114+
infcx.tcx,
115+
opaque_type_key,
116+
origin,
117+
concrete_type.span,
118+
) {
119+
remapped_type
120+
} else {
121+
infcx.tcx.ty_error()
122+
};
123+
// Sometimes two opaque types are the same only after we remap the generic parameters
124+
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
125+
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
126+
// once we convert the generic parameters to those of the opaque type.
127+
if let Some(prev) = result.get_mut(&opaque_type_key) {
128+
if prev.ty != ty {
129+
let mut err = infcx.tcx.sess.struct_span_err(
130+
concrete_type.span,
131+
&format!("hidden type `{}` differed from previous `{}`", ty, prev.ty),
132+
);
133+
err.span_note(prev.span, "previous hidden type bound here");
134+
err.emit();
135+
prev.ty = infcx.tcx.ty_error();
136+
}
137+
// Pick a better span if there is one.
138+
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
139+
prev.span = prev.span.substitute_dummy(concrete_type.span);
140+
} else {
141+
result.insert(opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span });
142+
}
143+
}
144+
result
127145
}
128146

129147
/// Map the regions in the type to named regions. This is similar to what
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// check-pass
2+
3+
use std::marker::PhantomData;
4+
5+
pub struct ConcreteError {}
6+
pub trait IoBase {}
7+
struct X {}
8+
impl IoBase for X {}
9+
10+
pub struct ClusterIterator<B, E, S = B> {
11+
pub fat: B,
12+
phantom_s: PhantomData<S>,
13+
phantom_e: PhantomData<E>,
14+
}
15+
16+
pub struct FileSystem<IO: IoBase> {
17+
pub disk: IO,
18+
}
19+
20+
impl<IO: IoBase> FileSystem<IO> {
21+
pub fn cluster_iter(&self) -> ClusterIterator<impl IoBase + '_, ConcreteError> {
22+
ClusterIterator {
23+
fat: X {},
24+
phantom_s: PhantomData::default(),
25+
phantom_e: PhantomData::default(),
26+
}
27+
}
28+
}
29+
30+
fn main() {}

0 commit comments

Comments
 (0)