Check that all hidden types are the same and then deduplicate them.

This commit is contained in:
Oli Scherer 2022-04-06 15:02:37 +00:00
parent 201cf3dba3
commit 27dc503556
2 changed files with 111 additions and 63 deletions

View File

@ -55,9 +55,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
infcx: &InferCtxt<'_, 'tcx>,
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
) -> VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> {
opaque_ty_decls
.into_iter()
.map(|(opaque_type_key, (concrete_type, origin))| {
let mut result: VecMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>> = VecMap::new();
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
let substs = opaque_type_key.substs;
debug!(?concrete_type, ?substs);
@ -121,9 +120,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
} else {
infcx.tcx.ty_error()
};
(opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span })
})
.collect()
// Sometimes two opaque types are the same only after we remap the generic parameters
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
// once we convert the generic parameters to those of the opaque type.
if let Some(prev) = result.get_mut(&opaque_type_key) {
if prev.ty != ty {
let mut err = infcx.tcx.sess.struct_span_err(
concrete_type.span,
&format!("hidden type `{}` differed from previous `{}`", ty, prev.ty),
);
err.span_note(prev.span, "previous hidden type bound here");
err.emit();
prev.ty = infcx.tcx.ty_error();
}
// Pick a better span if there is one.
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
prev.span = prev.span.substitute_dummy(concrete_type.span);
} else {
result.insert(opaque_type_key, OpaqueHiddenType { ty, span: concrete_type.span });
}
}
result
}
/// Map the regions in the type to named regions. This is similar to what

View File

@ -0,0 +1,30 @@
// check-pass
use std::marker::PhantomData;
pub struct ConcreteError {}
pub trait IoBase {}
struct X {}
impl IoBase for X {}
pub struct ClusterIterator<B, E, S = B> {
pub fat: B,
phantom_s: PhantomData<S>,
phantom_e: PhantomData<E>,
}
pub struct FileSystem<IO: IoBase> {
pub disk: IO,
}
impl<IO: IoBase> FileSystem<IO> {
pub fn cluster_iter(&self) -> ClusterIterator<impl IoBase + '_, ConcreteError> {
ClusterIterator {
fat: X {},
phantom_s: PhantomData::default(),
phantom_e: PhantomData::default(),
}
}
}
fn main() {}