diff options
| author | b-naber <bn263@gmx.de> | 2022-03-22 10:38:46 +0100 |
|---|---|---|
| committer | b-naber <bn263@gmx.de> | 2022-03-22 11:35:59 +0100 |
| commit | 8ff1edbe5e38cede450d926d2761191f07bb0af1 (patch) | |
| tree | cb401f40ca781065e809e7ae004ed1e83b9f82ff | |
| parent | 6cf3409e16845bf52e72f4ffdac9db139a24a8d3 (diff) | |
| download | rust-8ff1edbe5e38cede450d926d2761191f07bb0af1.tar.gz rust-8ff1edbe5e38cede450d926d2761191f07bb0af1.zip | |
fix previous failures and address review
| -rw-r--r-- | compiler/rustc_infer/src/infer/mod.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/queries.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 208 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/fulfill.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/mod.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/dropck.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/const-generics/issues/issue-83765.rs | 118 | ||||
| -rw-r--r-- | src/test/ui/const-generics/issues/issue-83765.stderr | 10 |
9 files changed, 204 insertions, 166 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e7fd7d2928e..45502c720ae 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -20,8 +20,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; -use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::mir::interpret::EvalToConstValueResult; +use rustc_middle::mir::interpret::{ErrorHandled, EvalToConstValueResult}; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; @@ -695,9 +694,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> bool { // Reject any attempt to unify two unevaluated constants that contain inference - // variables. - // FIXME `TyCtxt::const_eval_resolve` already rejects the resolution of those - // constants early, but the canonicalization below messes with that mechanism. + // variables, since inference variables in queries lead to ICEs. if a.substs.has_infer_types_or_consts() || b.substs.has_infer_types_or_consts() { debug!("a or b contain infer vars in its substs -> cannot unify"); return false; @@ -1621,8 +1618,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Postpone the evaluation of constants whose substs depend on inference // variables if substs.has_infer_types_or_consts() { - debug!("has infer types or consts"); - return Err(ErrorHandled::TooGeneric); + debug!("substs have infer types or consts: {:?}", substs); + if substs.has_infer_types_or_consts() { + return Err(ErrorHandled::TooGeneric); + } } let param_env_erased = self.tcx.erase_regions(param_env); diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 155ee210ebe..639a9bc600a 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -43,7 +43,7 @@ impl<'tcx> TyCtxt<'tcx> { // variables. We reject those here since `resolve_opt_const_arg` // would fail otherwise if ct.substs.has_infer_types_or_consts() { - return Err(ErrorHandled::TooGeneric); + bug!("did not expect inference variables here"); } match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 0c33ea858fd..c44e9613630 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -569,6 +569,18 @@ pub(super) fn thir_abstract_const<'tcx>( } } +/// Tries to unify two abstract constants using structural equality. +#[instrument(skip(tcx), level = "debug")] +pub(super) fn try_unify<'tcx>( + tcx: TyCtxt<'tcx>, + a: AbstractConst<'tcx>, + b: AbstractConst<'tcx>, + param_env: ty::ParamEnv<'tcx>, +) -> bool { + let const_unify_ctxt = ConstUnifyCtxt::new(tcx, param_env); + const_unify_ctxt.try_unify_inner(a, b) +} + pub(super) fn try_unify_abstract_consts<'tcx>( tcx: TyCtxt<'tcx>, (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>), @@ -622,115 +634,119 @@ where recurse(tcx, ct, &mut f) } -// Substitutes generics repeatedly to allow AbstractConsts to unify where a -// ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g. -// Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])] -#[inline] -#[instrument(skip(tcx), level = "debug")] -fn try_replace_substs_in_root<'tcx>( +pub(super) struct ConstUnifyCtxt<'tcx> { tcx: TyCtxt<'tcx>, - mut abstr_const: AbstractConst<'tcx>, -) -> Option<AbstractConst<'tcx>> { - while let Node::Leaf(ct) = abstr_const.root(tcx) { - match AbstractConst::from_const(tcx, ct) { - Ok(Some(act)) => abstr_const = act, - Ok(None) => break, - Err(_) => return None, - } - } - - Some(abstr_const) + param_env: ty::ParamEnv<'tcx>, } -/// Tries to unify two abstract constants using structural equality. -#[instrument(skip(tcx), level = "debug")] -pub(super) fn try_unify<'tcx>( - tcx: TyCtxt<'tcx>, - a: AbstractConst<'tcx>, - b: AbstractConst<'tcx>, - param_env: ty::ParamEnv<'tcx>, -) -> bool { - let a = match try_replace_substs_in_root(tcx, a) { - Some(a) => a, - None => { - return true; +impl<'tcx> ConstUnifyCtxt<'tcx> { + pub(super) fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { + ConstUnifyCtxt { tcx, param_env } + } + + // Substitutes generics repeatedly to allow AbstractConsts to unify where a + // ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g. + // Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])] + #[inline] + #[instrument(skip(self), level = "debug")] + pub(super) fn try_replace_substs_in_root( + &self, + mut abstr_const: AbstractConst<'tcx>, + ) -> Option<AbstractConst<'tcx>> { + while let Node::Leaf(ct) = abstr_const.root(self.tcx) { + match AbstractConst::from_const(self.tcx, ct) { + Ok(Some(act)) => abstr_const = act, + Ok(None) => break, + Err(_) => return None, + } } - }; - let b = match try_replace_substs_in_root(tcx, b) { - Some(b) => b, - None => { + Some(abstr_const) + } + + /// Tries to unify two abstract constants using structural equality. + #[instrument(skip(self), level = "debug")] + fn try_unify_inner(&self, a: AbstractConst<'tcx>, b: AbstractConst<'tcx>) -> bool { + let a = if let Some(a) = self.try_replace_substs_in_root(a) { + a + } else { return true; - } - }; + }; - let a_root = a.root(tcx); - let b_root = b.root(tcx); - debug!(?a_root, ?b_root); + let b = if let Some(b) = self.try_replace_substs_in_root(b) { + b + } else { + return true; + }; - match (a_root, b_root) { - (Node::Leaf(a_ct), Node::Leaf(b_ct)) => { - let a_ct = a_ct.eval(tcx, param_env); - debug!("a_ct evaluated: {:?}", a_ct); - let b_ct = b_ct.eval(tcx, param_env); - debug!("b_ct evaluated: {:?}", b_ct); + let a_root = a.root(self.tcx); + let b_root = b.root(self.tcx); + debug!(?a_root, ?b_root); - if a_ct.ty() != b_ct.ty() { - return false; - } + match (a_root, b_root) { + (Node::Leaf(a_ct), Node::Leaf(b_ct)) => { + let a_ct = a_ct.eval(self.tcx, self.param_env); + debug!("a_ct evaluated: {:?}", a_ct); + let b_ct = b_ct.eval(self.tcx, self.param_env); + debug!("b_ct evaluated: {:?}", b_ct); - match (a_ct.val(), b_ct.val()) { - // We can just unify errors with everything to reduce the amount of - // emitted errors here. - (ty::ConstKind::Error(_), _) | (_, ty::ConstKind::Error(_)) => true, - (ty::ConstKind::Param(a_param), ty::ConstKind::Param(b_param)) => { - a_param == b_param + if a_ct.ty() != b_ct.ty() { + return false; } - (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val, - // If we have `fn a<const N: usize>() -> [u8; N + 1]` and `fn b<const M: usize>() -> [u8; 1 + M]` - // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This - // means that we only allow inference variables if they are equal. - (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val, - // We expand generic anonymous constants at the start of this function, so this - // branch should only be taking when dealing with associated constants, at - // which point directly comparing them seems like the desired behavior. - // - // FIXME(generic_const_exprs): This isn't actually the case. - // We also take this branch for concrete anonymous constants and - // expand generic anonymous constants with concrete substs. - (ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => { - a_uv == b_uv + + match (a_ct.val(), b_ct.val()) { + // We can just unify errors with everything to reduce the amount of + // emitted errors here. + (ty::ConstKind::Error(_), _) | (_, ty::ConstKind::Error(_)) => true, + (ty::ConstKind::Param(a_param), ty::ConstKind::Param(b_param)) => { + a_param == b_param + } + (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val, + // If we have `fn a<const N: usize>() -> [u8; N + 1]` and `fn b<const M: usize>() -> [u8; 1 + M]` + // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This + // means that we only allow inference variables if they are equal. + (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val, + // We expand generic anonymous constants at the start of this function, so this + // branch should only be taking when dealing with associated constants, at + // which point directly comparing them seems like the desired behavior. + // + // FIXME(generic_const_exprs): This isn't actually the case. + // We also take this branch for concrete anonymous constants and + // expand generic anonymous constants with concrete substs. + (ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => { + a_uv == b_uv + } + // FIXME(generic_const_exprs): We may want to either actually try + // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like + // this, for now we just return false here. + _ => false, } - // FIXME(generic_const_exprs): We may want to either actually try - // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like - // this, for now we just return false here. - _ => false, } + (Node::Binop(a_op, al, ar), Node::Binop(b_op, bl, br)) if a_op == b_op => { + self.try_unify_inner(a.subtree(al), b.subtree(bl)) + && self.try_unify_inner(a.subtree(ar), b.subtree(br)) + } + (Node::UnaryOp(a_op, av), Node::UnaryOp(b_op, bv)) if a_op == b_op => { + self.try_unify_inner(a.subtree(av), b.subtree(bv)) + } + (Node::FunctionCall(a_f, a_args), Node::FunctionCall(b_f, b_args)) + if a_args.len() == b_args.len() => + { + self.try_unify_inner(a.subtree(a_f), b.subtree(b_f)) + && iter::zip(a_args, b_args) + .all(|(&an, &bn)| self.try_unify_inner(a.subtree(an), b.subtree(bn))) + } + (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty)) + if (a_ty == b_ty) && (a_kind == b_kind) => + { + self.try_unify_inner(a.subtree(a_operand), b.subtree(b_operand)) + } + // use this over `_ => false` to make adding variants to `Node` less error prone + (Node::Cast(..), _) + | (Node::FunctionCall(..), _) + | (Node::UnaryOp(..), _) + | (Node::Binop(..), _) + | (Node::Leaf(..), _) => false, } - (Node::Binop(a_op, al, ar), Node::Binop(b_op, bl, br)) if a_op == b_op => { - try_unify(tcx, a.subtree(al), b.subtree(bl), param_env) - && try_unify(tcx, a.subtree(ar), b.subtree(br), param_env) - } - (Node::UnaryOp(a_op, av), Node::UnaryOp(b_op, bv)) if a_op == b_op => { - try_unify(tcx, a.subtree(av), b.subtree(bv), param_env) - } - (Node::FunctionCall(a_f, a_args), Node::FunctionCall(b_f, b_args)) - if a_args.len() == b_args.len() => - { - try_unify(tcx, a.subtree(a_f), b.subtree(b_f), param_env) - && iter::zip(a_args, b_args) - .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn), param_env)) - } - (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty)) - if (a_ty == b_ty) && (a_kind == b_kind) => - { - try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand), param_env) - } - // use this over `_ => false` to make adding variants to `Node` less error prone - (Node::Cast(..), _) - | (Node::FunctionCall(..), _) - | (Node::UnaryOp(..), _) - | (Node::Binop(..), _) - | (Node::Leaf(..), _) => false, } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 62c6c845479..df1e8cdcde0 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -581,7 +581,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val(), c2.val()) { - if infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) { + if infcx.try_unify_abstract_consts( + a.shrink(), + b.shrink(), + obligation.param_env, + ) { return ProcessResult::Changed(vec![]); } } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index bf94c61e6c2..e06ecc528aa 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -860,7 +860,10 @@ pub fn provide(providers: &mut ty::query::Providers) { ty::WithOptConstParam { did, const_param_did: Some(param_did) }, ) }, - try_unify_abstract_consts: const_evaluatable::try_unify_abstract_consts, + try_unify_abstract_consts: |tcx, param_env_and| { + let (param_env, (a, b)) = param_env_and.into_parts(); + const_evaluatable::try_unify_abstract_consts(tcx, (a, b), param_env) + }, ..*providers }; } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 8af4606db85..fe369ca5c46 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -643,7 +643,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val(), c2.val()) { - if self.infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) { + if self.infcx.try_unify_abstract_consts( + a.shrink(), + b.shrink(), + obligation.param_env, + ) { return Ok(EvaluatedToOk); } } diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 1849ece9f76..57b642dc38f 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -243,7 +243,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( ( ty::PredicateKind::ConstEvaluatable(a), ty::PredicateKind::ConstEvaluatable(b), - ) => tcx.try_unify_abstract_consts((a, b)), + ) => tcx.try_unify_abstract_consts(self_param_env.and((a, b))), ( ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)), ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)), diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs index 67d813819e7..71c164ab0a5 100644 --- a/src/test/ui/const-generics/issues/issue-83765.rs +++ b/src/test/ui/const-generics/issues/issue-83765.rs @@ -2,103 +2,115 @@ #![allow(incomplete_features)] trait TensorDimension { - const DIM : usize; - //~^ ERROR cycle detected when resolving instance `<LazyUpdim<T, {T::DIM}, DIM> - const ISSCALAR : bool = Self::DIM == 0; - fn is_scalar(&self) -> bool {Self::ISSCALAR} + const DIM: usize; + //~^ ERROR cycle detected when resolving instance + // FIXME Given the current state of the compiler its expected that we cycle here, + // but the cycle is still wrong. + const ISSCALAR: bool = Self::DIM == 0; + fn is_scalar(&self) -> bool { + Self::ISSCALAR + } } -trait TensorSize : TensorDimension { - fn size(&self) -> [usize;Self::DIM]; - fn inbounds(&self,index : [usize;Self::DIM]) -> bool { - index.iter().zip(self.size().iter()).all(|(i,s)| i < s) +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; + fn inbounds(&self, index: [usize; Self::DIM]) -> bool { + index.iter().zip(self.size().iter()).all(|(i, s)| i < s) } } - trait Broadcastable: TensorSize + Sized { type Element; - fn bget(&self, index:[usize;Self::DIM]) -> Option<Self::Element>; - fn lazy_updim<const NEWDIM : usize>(&self, size : [usize;NEWDIM] ) -> - LazyUpdim<Self,{Self::DIM},NEWDIM> - { - assert!(NEWDIM >= Self::DIM, - "Updimmed tensor cannot have fewer indices than the initial one."); - LazyUpdim {size,reference:&self} + fn bget(&self, index: [usize; Self::DIM]) -> Option<Self::Element>; + fn lazy_updim<const NEWDIM: usize>( + &self, + size: [usize; NEWDIM], + ) -> LazyUpdim<Self, { Self::DIM }, NEWDIM> { + assert!( + NEWDIM >= Self::DIM, + "Updimmed tensor cannot have fewer indices than the initial one." + ); + LazyUpdim { size, reference: &self } } - fn bmap<T,F :Fn(Self::Element) -> T>(&self,foo : F) -> BMap<T,Self,F,{Self::DIM}>{ - BMap {reference:self,closure : foo} + fn bmap<T, F: Fn(Self::Element) -> T>(&self, foo: F) -> BMap<T, Self, F, { Self::DIM }> { + BMap { reference: self, closure: foo } } } - -struct LazyUpdim<'a,T : Broadcastable,const OLDDIM : usize, const DIM : usize> { - size : [usize;DIM], - reference : &'a T +struct LazyUpdim<'a, T: Broadcastable, const OLDDIM: usize, const DIM: usize> { + size: [usize; DIM], + reference: &'a T, } -impl<'a,T : Broadcastable,const DIM : usize> TensorDimension for LazyUpdim<'a,T,{T::DIM},DIM> { - const DIM : usize = DIM; +impl<'a, T: Broadcastable, const DIM: usize> TensorDimension for LazyUpdim<'a, T, { T::DIM }, DIM> { + const DIM: usize = DIM; } -impl<'a,T : Broadcastable,const DIM : usize> TensorSize for LazyUpdim<'a,T,{T::DIM},DIM> { - fn size(&self) -> [usize;DIM] {self.size} +impl<'a, T: Broadcastable, const DIM: usize> TensorSize for LazyUpdim<'a, T, { T::DIM }, DIM> { + fn size(&self) -> [usize; DIM] { + self.size + } } -impl<'a,T : Broadcastable,const DIM : usize> Broadcastable for LazyUpdim<'a,T,{T::DIM},DIM> -{ +impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> { type Element = T::Element; - fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> { + fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> { assert!(DIM >= T::DIM); - if !self.inbounds(index) {return None} + if !self.inbounds(index) { + return None; + } let size = self.size(); - let newindex : [usize;T::DIM] = Default::default(); + let newindex: [usize; T::DIM] = Default::default(); self.reference.bget(newindex) } } -struct BMap<'a,R, T : Broadcastable, F : Fn(T::Element) -> R , const DIM: usize> { - reference : &'a T, - closure : F +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, } -impl<'a,R, T : Broadcastable, F : Fn(T::Element) -> R, - const DIM: usize> TensorDimension for BMap<'a,R,T,F,DIM> { - - const DIM : usize = DIM; +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; } -impl<'a,R, T : Broadcastable, F : Fn(T::Element) -> R , - const DIM: usize> TensorSize for BMap<'a,R,T,F,DIM> { - - fn size(&self) -> [usize;DIM] {self.reference.size()} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + self.reference.size() + } } -impl<'a,R, T : Broadcastable, F : Fn(T::Element) -> R , - const DIM: usize> Broadcastable for BMap<'a,R,T,F,DIM> { - +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> Broadcastable + for BMap<'a, R, T, F, DIM> +{ type Element = R; - fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> { + fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> { self.reference.bget(index).map(&self.closure) } } impl<T> TensorDimension for Vec<T> { - const DIM : usize = 1; + const DIM: usize = 1; } impl<T> TensorSize for Vec<T> { - fn size(&self) -> [usize;1] {[self.len()]} + fn size(&self) -> [usize; 1] { + [self.len()] + } } impl<T: Clone> Broadcastable for Vec<T> { type Element = T; - fn bget(& self,index : [usize;1]) -> Option<T> { + fn bget(&self, index: [usize; 1]) -> Option<T> { self.get(index[0]).cloned() } } fn main() { - let v = vec![1,2,3]; - let bv = v.lazy_updim([3,4]); - let bbv = bv.bmap(|x| x*x); + let v = vec![1, 2, 3]; + let bv = v.lazy_updim([3, 4]); + let bbv = bv.bmap(|x| x * x); - 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.")); } diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr index 0003969f7ac..8705a39fa4b 100644 --- a/src/test/ui/const-generics/issues/issue-83765.stderr +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -1,16 +1,16 @@ -error[E0391]: cycle detected when resolving instance `<LazyUpdim<T, {T::DIM}, DIM> as TensorDimension>::DIM` +error[E0391]: cycle detected when resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM` --> $DIR/issue-83765.rs:5:5 | -LL | const DIM : usize; - | ^^^^^^^^^^^^^^^^^^ +LL | const DIM: usize; + | ^^^^^^^^^^^^^^^^^ | note: ...which requires checking if `TensorDimension` fulfills its obligations... --> $DIR/issue-83765.rs:4:1 | LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires resolving instance `<LazyUpdim<T, {T::DIM}, DIM> as TensorDimension>::DIM`, completing the cycle - = note: cycle used when normalizing `<LazyUpdim<T, {T::DIM}, DIM> as TensorDimension>::DIM` + = note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle + = note: cycle used when normalizing `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM` error: aborting due to previous error |
