mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Check that all hidden types are the same and then deduplicate them.
This commit is contained in:
parent
201cf3dba3
commit
27dc503556
@ -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
|
||||
|
30
src/test/ui/type-alias-impl-trait/multiple_definitions.rs
Normal file
30
src/test/ui/type-alias-impl-trait/multiple_definitions.rs
Normal 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() {}
|
Loading…
Reference in New Issue
Block a user