diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty/relate.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/relate.rs | 102 |
1 files changed, 41 insertions, 61 deletions
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 65fd8d975..3fc5f5bed 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -9,7 +9,6 @@ use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldabl use crate::ty::{GenericArg, GenericArgKind, SubstsRef}; use rustc_hir as ast; use rustc_hir::def_id::DefId; -use rustc_span::DUMMY_SP; use rustc_target::spec::abi; use std::iter; @@ -106,7 +105,7 @@ pub trait TypeRelation<'tcx>: Sized { T: Relate<'tcx>; } -pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy { +pub trait Relate<'tcx>: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, a: Self, @@ -145,7 +144,7 @@ pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>( a_subst: SubstsRef<'tcx>, b_subst: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { - relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| { + relation.tcx().mk_substs_from_iter(iter::zip(a_subst, b_subst).map(|(a, b)| { relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b) })) } @@ -164,8 +163,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>( let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { let variance = variances[i]; 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)); + let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } } else { ty::VarianceDiagInfo::default() @@ -173,7 +171,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>( relation.relate_with_variance(variance, variance_info, a, b) }); - tcx.mk_substs(params) + tcx.mk_substs_from_iter(params) } impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { @@ -224,7 +222,7 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> { r => r, }); Ok(ty::FnSig { - inputs_and_output: tcx.mk_type_list(inputs_and_output)?, + inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?, c_variadic: a.c_variadic, unsafety, abi, @@ -354,7 +352,8 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { ) -> RelateResult<'tcx, GeneratorWitness<'tcx>> { assert_eq!(a.0.len(), b.0.len()); let tcx = relation.tcx(); - let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?; + let types = + tcx.mk_type_list_from_iter(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?; Ok(GeneratorWitness(types)) } } @@ -414,7 +413,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( bug!("bound types encountered in super_relate_tys") } - (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error_with_guaranteed(guar)), + (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)), (&ty::Never, _) | (&ty::Char, _) @@ -443,12 +442,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( if a_repr == b_repr => { let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { - relation.relate_with_variance( - ty::Contravariant, - ty::VarianceDiagInfo::default(), - a_region, - b_region, - ) + relation.relate(a_region, b_region) })?; Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr)) } @@ -473,6 +467,16 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(tcx.mk_generator_witness(types)) } + (&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs)) + if a_id == b_id => + { + // All GeneratorWitness types with the same id represent + // the (anonymous) type of the same generator expression. So + // all of their regions should be equated. + let substs = relation.relate(a_substs, b_substs)?; + Ok(tcx.mk_generator_witness_mir(a_id, substs)) + } + (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => { // All Closure types with the same id represent // the (anonymous) type of the same closure expression. So @@ -487,12 +491,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( } (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { - let r = relation.relate_with_variance( - ty::Contravariant, - ty::VarianceDiagInfo::default(), - a_r, - b_r, - )?; + let r = relation.relate(a_r, b_r)?; let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; @@ -502,7 +501,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { let t = relation.relate(a_t, b_t)?; match relation.relate(sz_a, sz_b) { - Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))), + Ok(sz) => Ok(tcx.mk_array_with_const_len(t, sz)), Err(err) => { // Check whether the lengths are both concrete/known values, // but are unequal, for better diagnostics. @@ -511,8 +510,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( // we however cannot end up with errors in `Relate` during both // `type_of` and `predicates_of`. This means that evaluating the // constants should not cause cycle errors here. - let sz_a = sz_a.try_eval_usize(tcx, relation.param_env()); - let sz_b = sz_b.try_eval_usize(tcx, relation.param_env()); + let sz_a = sz_a.try_eval_target_usize(tcx, relation.param_env()); + let sz_b = sz_b.try_eval_target_usize(tcx, relation.param_env()); match (sz_a, sz_b) { (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), @@ -530,7 +529,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { - Ok(tcx.mk_tup(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) + Ok(tcx.mk_tup_from_iter(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) } else { @@ -594,25 +593,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); let tcx = relation.tcx(); - let a_ty; - let b_ty; - if relation.tcx().features().adt_const_params { - a_ty = tcx.normalize_erasing_regions(relation.param_env(), a.ty()); - b_ty = tcx.normalize_erasing_regions(relation.param_env(), b.ty()); - } else { - a_ty = tcx.erase_regions(a.ty()); - b_ty = tcx.erase_regions(b.ty()); - } - if a_ty != b_ty { - relation.tcx().sess.delay_span_bug( - DUMMY_SP, - &format!( - "cannot relate constants ({:?}, {:?}) of different types: {} != {}", - a, b, a_ty, b_ty - ), - ); - } - // HACK(const_generics): We still need to eagerly evaluate consts when // relating them because during `normalize_param_env_or_error`, // we may relate an evaluated constant in a obligation against @@ -629,6 +609,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( b = tcx.expand_abstract_consts(b); } + debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b); + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. @@ -665,36 +647,34 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical // exprs? Should we care about that? + // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to + // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought + // of as being generic over the argument types, however this is implicit so these types don't get + // related when we relate the substs of the item this const arg is for. let expr = match (ae, be) { - (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) - if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() => - { + (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => { + r.relate(al.ty(), bl.ty())?; + r.relate(ar.ty(), br.ty())?; Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?) } - (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) - if a_op == b_op && av.ty() == bv.ty() => - { + (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => { + r.relate(av.ty(), bv.ty())?; Expr::UnOp(a_op, r.consts(av, bv)?) } - (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) - if ak == bk && av.ty() == bv.ty() => - { + (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => { + r.relate(av.ty(), bv.ty())?; Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?) } (Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba)) - if aa.len() == ba.len() - && af.ty() == bf.ty() - && aa - .iter() - .zip(ba.iter()) - .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) => + if aa.len() == ba.len() => { + r.relate(af.ty(), bf.ty())?; let func = r.consts(af, bf)?; let mut related_args = Vec::with_capacity(aa.len()); for (a_arg, b_arg) in aa.iter().zip(ba.iter()) { related_args.push(r.consts(a_arg, b_arg)?); } - let related_args = tcx.mk_const_list(related_args.iter()); + let related_args = tcx.mk_const_list(&related_args); Expr::FunctionCall(func, related_args) } _ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))), @@ -741,7 +721,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> { _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))), } }); - tcx.mk_poly_existential_predicates(v) + tcx.mk_poly_existential_predicates_from_iter(v) } } |