Add expand_abstract_const
Adds the ability to directly expand a const to an expr without having to deal with intermediate steps.
This commit is contained in:
parent
f9750c1554
commit
5bb1a9febc
11 changed files with 124 additions and 174 deletions
|
@ -193,18 +193,6 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
ty::PredicateKind::ConstEvaluatable(a),
|
ty::PredicateKind::ConstEvaluatable(a),
|
||||||
ty::PredicateKind::ConstEvaluatable(b),
|
ty::PredicateKind::ConstEvaluatable(b),
|
||||||
) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
|
) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
|
||||||
/*
|
|
||||||
) => {
|
|
||||||
if let (Ok(Some(a)), Ok(Some(b))) = (
|
|
||||||
tcx.expand_bound_abstract_const(tcx.bound_abstract_const(a.def), a.substs),
|
|
||||||
tcx.expand_bound_abstract_const(tcx.bound_abstract_const(b.def), b.substs),
|
|
||||||
) && a.ty() == b.ty() {
|
|
||||||
return relator.relate(a, b).is_ok();
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
(
|
(
|
||||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
|
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
|
||||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
|
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
|
||||||
|
|
|
@ -1621,15 +1621,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
// variables
|
// variables
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
if substs.has_non_region_infer() {
|
if substs.has_non_region_infer() {
|
||||||
let substs_erased = tcx.erase_regions(unevaluated.substs);
|
let ac = tcx.expand_unevaluated_abstract_const(unevaluated.def, unevaluated.substs);
|
||||||
let ac = tcx.expand_bound_abstract_const(
|
|
||||||
tcx.bound_abstract_const(unevaluated.def),
|
|
||||||
substs_erased,
|
|
||||||
);
|
|
||||||
match ac {
|
match ac {
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
|
substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
|
||||||
param_env = self.tcx.param_env(unevaluated.def.did);
|
param_env = tcx.param_env(unevaluated.def.did);
|
||||||
}
|
}
|
||||||
Ok(Some(ct)) => {
|
Ok(Some(ct)) => {
|
||||||
if ct.has_non_region_infer() || ct.has_non_region_param() {
|
if ct.has_non_region_infer() || ct.has_non_region_param() {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
//! A subset of a mir body used for const evaluatability checking.
|
//! A subset of a mir body used for const evaluatability checking.
|
||||||
use crate::ty::{self, Const, EarlyBinder, FallibleTypeFolder, GenericArg, TyCtxt, TypeFoldable};
|
use crate::ty::{
|
||||||
|
self, subst::SubstsRef, Const, EarlyBinder, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable,
|
||||||
|
TypeSuperFoldable, TypeVisitable,
|
||||||
|
};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
|
||||||
|
@ -33,71 +36,79 @@ pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>,
|
||||||
|
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Returns a const with substs applied by
|
/// Returns a const with substs applied by
|
||||||
pub fn bound_abstract_const(
|
fn bound_abstract_const(self, uv: ty::WithOptConstParam<DefId>) -> BoundAbstractConst<'tcx> {
|
||||||
self,
|
let ac = if let Some((did, param_did)) = uv.as_const_arg() {
|
||||||
uv: ty::WithOptConstParam<DefId>,
|
|
||||||
) -> BoundAbstractConst<'tcx> {
|
|
||||||
self.thir_abstract_const_opt_const_arg(uv).map(|ac| ac.map(|ac| EarlyBinder(ac)))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn thir_abstract_const_opt_const_arg(
|
|
||||||
self,
|
|
||||||
def: ty::WithOptConstParam<DefId>,
|
|
||||||
) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
|
|
||||||
if let Some((did, param_did)) = def.as_const_arg() {
|
|
||||||
self.thir_abstract_const_of_const_arg((did, param_did))
|
self.thir_abstract_const_of_const_arg((did, param_did))
|
||||||
} else {
|
} else {
|
||||||
self.thir_abstract_const(def.did)
|
self.thir_abstract_const(uv.did)
|
||||||
}
|
};
|
||||||
|
Ok(ac?.map(|ac| EarlyBinder(ac)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_bound_abstract_const(
|
pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(
|
||||||
self,
|
self,
|
||||||
ct: BoundAbstractConst<'tcx>,
|
ac: T,
|
||||||
substs: &[GenericArg<'tcx>],
|
) -> Result<Option<T>, ErrorGuaranteed> {
|
||||||
) -> Result<Option<Const<'tcx>>, ErrorGuaranteed> {
|
self._expand_abstract_consts(ac, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand_unevaluated_abstract_const(
|
||||||
|
self,
|
||||||
|
did: ty::WithOptConstParam<DefId>,
|
||||||
|
substs: SubstsRef<'tcx>,
|
||||||
|
) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
|
||||||
|
let Some(ac) = self.bound_abstract_const(did)? else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
let substs = self.erase_regions(substs);
|
||||||
|
let ac = ac.subst(self, substs);
|
||||||
|
self._expand_abstract_consts(ac, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _expand_abstract_consts<T: TypeFoldable<'tcx>>(
|
||||||
|
self,
|
||||||
|
ac: T,
|
||||||
|
first: bool,
|
||||||
|
) -> Result<Option<T>, ErrorGuaranteed> {
|
||||||
struct Expander<'tcx> {
|
struct Expander<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
first: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> FallibleTypeFolder<'tcx> for Expander<'tcx> {
|
impl<'tcx> FallibleTypeFolder<'tcx> for Expander<'tcx> {
|
||||||
type Error = ErrorGuaranteed;
|
type Error = Option<ErrorGuaranteed>;
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, ErrorGuaranteed> {
|
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||||
use ty::ConstKind::*;
|
if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
|
||||||
let uv = match c.kind() {
|
ty.try_super_fold_with(self)
|
||||||
Unevaluated(uv) => uv,
|
} else {
|
||||||
Param(..) | Infer(..) | Bound(..) | Placeholder(..) | Value(..) | Error(..) => {
|
Ok(ty)
|
||||||
return Ok(c);
|
|
||||||
}
|
}
|
||||||
Expr(e) => {
|
|
||||||
let new_expr = match e {
|
|
||||||
ty::Expr::Binop(op, l, r) => {
|
|
||||||
ty::Expr::Binop(op, l.try_fold_with(self)?, r.try_fold_with(self)?)
|
|
||||||
}
|
}
|
||||||
ty::Expr::UnOp(op, v) => ty::Expr::UnOp(op, v.try_fold_with(self)?),
|
fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, Self::Error> {
|
||||||
ty::Expr::Cast(k, c, t) => {
|
let ct = match c.kind() {
|
||||||
ty::Expr::Cast(k, c.try_fold_with(self)?, t.try_fold_with(self)?)
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
|
if let Some(bac) = self.tcx.bound_abstract_const(uv.def)? {
|
||||||
|
let substs = self.tcx.erase_regions(uv.substs);
|
||||||
|
bac.subst(self.tcx, substs)
|
||||||
|
} else if self.first {
|
||||||
|
return Err(None);
|
||||||
|
} else {
|
||||||
|
c
|
||||||
}
|
}
|
||||||
ty::Expr::FunctionCall(func, args) => ty::Expr::FunctionCall(
|
}
|
||||||
func.try_fold_with(self)?,
|
_ => c,
|
||||||
args.try_fold_with(self)?,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
return Ok(self.tcx().mk_const(ty::ConstKind::Expr(new_expr), c.ty()));
|
self.first = false;
|
||||||
}
|
ct.try_super_fold_with(self)
|
||||||
};
|
|
||||||
let bac = self.tcx.bound_abstract_const(uv.def);
|
|
||||||
let ac = self.tcx.expand_bound_abstract_const(bac, uv.substs);
|
|
||||||
if let Ok(Some(ac)) = ac { ac.try_fold_with(self) } else { Ok(c) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match ac.try_fold_with(&mut Expander { tcx: self, first }) {
|
||||||
let Some(ac) = ct? else {
|
Ok(c) => Ok(Some(c)),
|
||||||
return Ok(None);
|
Err(None) => Ok(None),
|
||||||
};
|
Err(Some(e)) => Err(e),
|
||||||
let ac = ac.subst(self, substs);
|
}
|
||||||
Ok(Some(ac.try_fold_with(&mut Expander { tcx: self })?))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -626,7 +626,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
// an unnormalized (i.e. unevaluated) const in the param-env.
|
// an unnormalized (i.e. unevaluated) const in the param-env.
|
||||||
// FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants
|
// FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants
|
||||||
// these `eval` calls can be removed.
|
// these `eval` calls can be removed.
|
||||||
if !relation.tcx().features().generic_const_exprs {
|
if !tcx.features().generic_const_exprs {
|
||||||
a = a.eval(tcx, relation.param_env());
|
a = a.eval(tcx, relation.param_env());
|
||||||
b = b.eval(tcx, relation.param_env());
|
b = b.eval(tcx, relation.param_env());
|
||||||
}
|
}
|
||||||
|
@ -647,12 +647,12 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
||||||
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
|
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
|
||||||
|
|
||||||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
(ty::ConstKind::Unevaluated(_au), ty::ConstKind::Unevaluated(_bu))
|
||||||
if tcx.features().generic_const_exprs =>
|
if tcx.features().generic_const_exprs =>
|
||||||
{
|
{
|
||||||
if let (Ok(Some(a)), Ok(Some(b))) = (
|
if let (Ok(Some(a)), Ok(Some(b))) = (
|
||||||
tcx.expand_bound_abstract_const(tcx.bound_abstract_const(au.def), au.substs),
|
tcx.expand_abstract_consts(a),
|
||||||
tcx.expand_bound_abstract_const(tcx.bound_abstract_const(bu.def), bu.substs),
|
tcx.expand_abstract_consts(b),
|
||||||
) && a.ty() == b.ty() {
|
) && a.ty() == b.ty() {
|
||||||
return relation.consts(a, b);
|
return relation.consts(a, b);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -287,12 +287,8 @@ where
|
||||||
self.visit_ty(c.ty())?;
|
self.visit_ty(c.ty())?;
|
||||||
let tcx = self.def_id_visitor.tcx();
|
let tcx = self.def_id_visitor.tcx();
|
||||||
if let ty::ConstKind::Unevaluated(uv) = c.kind() &&
|
if let ty::ConstKind::Unevaluated(uv) = c.kind() &&
|
||||||
let Ok(Some(ct)) = tcx.expand_bound_abstract_const(tcx.bound_abstract_const(uv.def),
|
let Ok(Some(ct)) = tcx.expand_unevaluated_abstract_const(uv.def, uv.substs) {
|
||||||
uv.substs) {
|
ct.super_visit_with(self)?;
|
||||||
ct.visit_with(self)?;
|
|
||||||
}
|
|
||||||
if let ty::ConstKind::Expr(e) = c.kind() {
|
|
||||||
e.visit_with(self)?;
|
|
||||||
}
|
}
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,7 @@ pub fn is_const_evaluatable<'tcx>(
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let uv = match ct.kind() {
|
let uv = match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(uv) => uv,
|
ty::ConstKind::Unevaluated(uv) => uv,
|
||||||
// should be recursivee fixes.
|
ty::ConstKind::Expr(_) => bug!("unexpected expr in `is_const_evaluatable: {ct:?}"),
|
||||||
ty::ConstKind::Expr(..) => todo!(),
|
|
||||||
ty::ConstKind::Param(_)
|
ty::ConstKind::Param(_)
|
||||||
| ty::ConstKind::Bound(_, _)
|
| ty::ConstKind::Bound(_, _)
|
||||||
| ty::ConstKind::Placeholder(_)
|
| ty::ConstKind::Placeholder(_)
|
||||||
|
@ -40,10 +39,7 @@ pub fn is_const_evaluatable<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
if tcx.features().generic_const_exprs {
|
if tcx.features().generic_const_exprs {
|
||||||
let substs = tcx.erase_regions(uv.substs);
|
if let Some(ct) = tcx.expand_abstract_consts(ct)? {
|
||||||
if let Some(ct) =
|
|
||||||
tcx.expand_bound_abstract_const(tcx.bound_abstract_const(uv.def), substs)?
|
|
||||||
{
|
|
||||||
if satisfied_from_param_env(tcx, infcx, ct, param_env)? {
|
if satisfied_from_param_env(tcx, infcx, ct, param_env)? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -74,17 +70,13 @@ pub fn is_const_evaluatable<'tcx>(
|
||||||
//
|
//
|
||||||
// See #74595 for more details about this.
|
// See #74595 for more details about this.
|
||||||
let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
|
let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
|
||||||
|
|
||||||
let substs = tcx.erase_regions(uv.substs);
|
|
||||||
match concrete {
|
match concrete {
|
||||||
// If we're evaluating a foreign constant, under a nightly compiler without generic
|
// If we're evaluating a generic foreign constant, under a nightly compiler while
|
||||||
// const exprs, AND it would've passed if that expression had been evaluated with
|
// the current crate does not enable `feature(generic_const_exprs)`, abort
|
||||||
// generic const exprs, then suggest using generic const exprs.
|
// compilation with a useful error.
|
||||||
Err(_) if tcx.sess.is_nightly_build()
|
Err(_) if tcx.sess.is_nightly_build()
|
||||||
&& let Ok(Some(ct)) =
|
&& let Ok(Some(ac)) = tcx.expand_abstract_consts(ct)
|
||||||
tcx.expand_bound_abstract_const(tcx.bound_abstract_const(uv.def), substs)
|
&& let ty::ConstKind::Expr(_) = ac.kind() => {
|
||||||
&& let ty::ConstKind::Expr(_expr) = ct.kind()
|
|
||||||
&& satisfied_from_param_env(tcx, infcx, ct, param_env) == Ok(true) => {
|
|
||||||
tcx.sess
|
tcx.sess
|
||||||
.struct_span_fatal(
|
.struct_span_fatal(
|
||||||
// Slightly better span than just using `span` alone
|
// Slightly better span than just using `span` alone
|
||||||
|
@ -126,18 +118,6 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
ct: ty::Const<'tcx>,
|
ct: ty::Const<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Result<bool, NotConstEvaluatable> {
|
) -> Result<bool, NotConstEvaluatable> {
|
||||||
for pred in param_env.caller_bounds() {
|
|
||||||
match pred.kind().skip_binder() {
|
|
||||||
ty::PredicateKind::ConstEvaluatable(uv) => {
|
|
||||||
let ty::ConstKind::Unevaluated(uv) = uv.kind() else {
|
|
||||||
continue
|
|
||||||
};
|
|
||||||
let substs = tcx.erase_regions(uv.substs);
|
|
||||||
let Some(b_ct) =
|
|
||||||
tcx.expand_bound_abstract_const(tcx.bound_abstract_const(uv.def), substs)? else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Try to unify with each subtree in the AbstractConst to allow for
|
// Try to unify with each subtree in the AbstractConst to allow for
|
||||||
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
|
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
|
||||||
// predicate for `(N + 1) * 2`
|
// predicate for `(N + 1) * 2`
|
||||||
|
@ -156,7 +136,6 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
.at(&ObligationCause::dummy(), self.param_env)
|
.at(&ObligationCause::dummy(), self.param_env)
|
||||||
.eq(c, self.ct)
|
.eq(c, self.ct)
|
||||||
{
|
{
|
||||||
//let obligations = nested_obligations.into_obligations();
|
|
||||||
ControlFlow::BREAK
|
ControlFlow::BREAK
|
||||||
} else if let ty::ConstKind::Expr(e) = c.kind() {
|
} else if let ty::ConstKind::Expr(e) = c.kind() {
|
||||||
e.visit_with(self)
|
e.visit_with(self)
|
||||||
|
@ -166,6 +145,16 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for pred in param_env.caller_bounds() {
|
||||||
|
match pred.kind().skip_binder() {
|
||||||
|
ty::PredicateKind::ConstEvaluatable(ce) => {
|
||||||
|
let ty::ConstKind::Unevaluated(_) = ce.kind() else {
|
||||||
|
continue
|
||||||
|
};
|
||||||
|
let Some(b_ct) = tcx.expand_abstract_consts(ce)? else {
|
||||||
|
continue
|
||||||
|
};
|
||||||
|
|
||||||
let mut v = Visitor { ct, infcx, param_env };
|
let mut v = Visitor { ct, infcx, param_env };
|
||||||
let result = b_ct.visit_with(&mut v);
|
let result = b_ct.visit_with(&mut v);
|
||||||
|
|
||||||
|
|
|
@ -478,14 +478,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let (Ok(Some(a)), Ok(Some(b))) = (
|
if let (Ok(Some(a)), Ok(Some(b))) = (
|
||||||
tcx.expand_bound_abstract_const(
|
tcx.expand_abstract_consts(c1),
|
||||||
tcx.bound_abstract_const(a.def),
|
tcx.expand_abstract_consts(c2),
|
||||||
a.substs,
|
|
||||||
),
|
|
||||||
tcx.expand_bound_abstract_const(
|
|
||||||
tcx.bound_abstract_const(b.def),
|
|
||||||
b.substs,
|
|
||||||
),
|
|
||||||
) && a.ty() == b.ty() &&
|
) && a.ty() == b.ty() &&
|
||||||
let Ok(new_obligations) = infcx
|
let Ok(new_obligations) = infcx
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
|
@ -534,7 +528,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.eq(c1, c2)
|
.eq(c1, c2)
|
||||||
{
|
{
|
||||||
Ok(_) => ProcessResult::Changed(vec![]),
|
Ok(inf_ok) => {
|
||||||
|
ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
|
||||||
|
}
|
||||||
Err(err) => ProcessResult::Error(
|
Err(err) => ProcessResult::Error(
|
||||||
FulfillmentErrorCode::CodeConstEquateError(
|
FulfillmentErrorCode::CodeConstEquateError(
|
||||||
ExpectedFound::new(true, c1, c2),
|
ExpectedFound::new(true, c1, c2),
|
||||||
|
|
|
@ -849,11 +849,8 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
|
||||||
//
|
//
|
||||||
// This shouldn't really matter though as we can't really use any
|
// This shouldn't really matter though as we can't really use any
|
||||||
// constants which are not considered const evaluatable.
|
// constants which are not considered const evaluatable.
|
||||||
if let ty::ConstKind::Unevaluated(uv) = ct.kind() &&
|
if let ty::ConstKind::Unevaluated(_uv) = ct.kind() &&
|
||||||
let Ok(Some(ct)) = self
|
let Ok(Some(ct)) = self.tcx.expand_abstract_consts(ct){
|
||||||
.tcx
|
|
||||||
.expand_bound_abstract_const(self.tcx.bound_abstract_const(uv.def), uv.substs)
|
|
||||||
{
|
|
||||||
self.visit_const(ct)
|
self.visit_const(ct)
|
||||||
} else {
|
} else {
|
||||||
ct.super_visit_with(self)
|
ct.super_visit_with(self)
|
||||||
|
|
|
@ -668,18 +668,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// if the constants depend on generic parameters.
|
// if the constants depend on generic parameters.
|
||||||
//
|
//
|
||||||
// Let's just see where this breaks :shrug:
|
// Let's just see where this breaks :shrug:
|
||||||
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
|
if let (ty::ConstKind::Unevaluated(_), ty::ConstKind::Unevaluated(_)) =
|
||||||
(c1.kind(), c2.kind())
|
(c1.kind(), c2.kind())
|
||||||
{
|
{
|
||||||
if let (Ok(Some(a)), Ok(Some(b))) = (
|
if let (Ok(Some(a)), Ok(Some(b))) = (
|
||||||
tcx.expand_bound_abstract_const(
|
tcx.expand_abstract_consts(c1),
|
||||||
tcx.bound_abstract_const(a.def),
|
tcx.expand_abstract_consts(c2),
|
||||||
a.substs,
|
|
||||||
),
|
|
||||||
tcx.expand_bound_abstract_const(
|
|
||||||
tcx.bound_abstract_const(b.def),
|
|
||||||
b.substs,
|
|
||||||
),
|
|
||||||
) && a.ty() == b.ty() && let Ok(new_obligations) =
|
) && a.ty() == b.ty() && let Ok(new_obligations) =
|
||||||
self.infcx.at(&obligation.cause, obligation.param_env).eq(a, b)
|
self.infcx.at(&obligation.cause, obligation.param_env).eq(a, b)
|
||||||
{
|
{
|
||||||
|
@ -718,7 +712,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
.at(&obligation.cause, obligation.param_env)
|
.at(&obligation.cause, obligation.param_env)
|
||||||
.eq(c1, c2)
|
.eq(c1, c2)
|
||||||
{
|
{
|
||||||
Ok(_) => Ok(EvaluatedToOk),
|
Ok(inf_ok) => self.evaluate_predicates_recursively(
|
||||||
|
previous_stack,
|
||||||
|
inf_ok.into_obligations(),
|
||||||
|
),
|
||||||
Err(_) => Ok(EvaluatedToErr),
|
Err(_) => Ok(EvaluatedToErr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,8 +120,6 @@ fn main() {
|
||||||
let v = vec![1, 2, 3];
|
let v = vec![1, 2, 3];
|
||||||
let bv = v.lazy_updim([3, 4]);
|
let bv = v.lazy_updim([3, 4]);
|
||||||
let bbv = bv.bmap(|x| x * x);
|
let bbv = bv.bmap(|x| x * x);
|
||||||
//~^ ERROR mismatched types
|
|
||||||
|
|
||||||
println!("The size of v is {:?}", bbv.bget([0, 2]).expect("Out of bounds."));
|
println!("The size of v is {:?}", bbv.bget([0, 2]).expect("Out of bounds."));
|
||||||
//~^ ERROR mismatched types
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,25 +98,7 @@ LL | self.reference.bget(index).map(&self.closure)
|
||||||
= note: expected constant `Self::DIM`
|
= note: expected constant `Self::DIM`
|
||||||
found constant `DIM`
|
found constant `DIM`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to 10 previous errors
|
||||||
--> $DIR/issue-83765.rs:122:15
|
|
||||||
|
|
|
||||||
LL | let bbv = bv.bmap(|x| x * x);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^ expected `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`, found `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`
|
|
||||||
|
|
|
||||||
= note: expected constant `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`
|
|
||||||
found constant `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/issue-83765.rs:125:43
|
|
||||||
|
|
|
||||||
LL | println!("The size of v is {:?}", bbv.bget([0, 2]).expect("Out of bounds."));
|
|
||||||
| ^^^^ expected `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`, found `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`
|
|
||||||
|
|
|
||||||
= note: expected constant `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`
|
|
||||||
found constant `<LazyUpdim<'_, Vec<{integer}>, { Self::DIM }, 2> as TensorDimension>::DIM`
|
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0308.
|
Some errors have detailed explanations: E0277, E0308.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue