pub trait TypeRelation<'tcx>: Sized {
fn tcx(&self) -> TyCtxt<'tcx>;
+ fn intercrate(&self) -> bool;
+
fn param_env(&self) -> ty::ParamEnv<'tcx>;
/// Returns a static string we can use for printouts.
/// relation. Just affects error messages.
fn a_is_expected(&self) -> bool;
+ /// Used during coherence. If called, must emit an always-ambiguous obligation.
+ fn mark_ambiguous(&mut self);
+
fn with_cause<F, R>(&mut self, _cause: Cause, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id);
- relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst)
+ relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst, true)
}
/// Switch variance for the purpose of relating `a` and `b`.
variances: &[ty::Variance],
a_subst: SubstsRef<'tcx>,
b_subst: SubstsRef<'tcx>,
+ fetch_ty_for_diag: bool,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
let tcx = relation.tcx();
let mut cached_ty = None;
let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
let variance = variances[i];
- let variance_info = if variance == ty::Invariant {
+ let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
let ty =
*cached_ty.get_or_insert_with(|| tcx.bound_type_of(ty_def_id).subst(tcx, a_subst));
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
if a_def_id == b_def_id =>
{
- let substs = relate_substs(relation, a_substs, b_substs)?;
- Ok(tcx.mk_opaque(a_def_id, substs))
+ if relation.intercrate() {
+ // During coherence, opaque types should be treated as equal to each other, even if their generic params
+ // differ, as they could resolve to the same hidden type, even for different generic params.
+ relation.mark_ambiguous();
+ Ok(a)
+ } else {
+ let opt_variances = tcx.variances_of(a_def_id);
+ let substs = relate_substs_with_variances(
+ relation,
+ a_def_id,
+ opt_variances,
+ a_substs,
+ b_substs,
+ false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+ )?;
+ Ok(tcx.mk_opaque(a_def_id, substs))
+ }
}
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) }
}
-impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
+impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Self,