Skip to content

Instantly share code, notes, and snippets.

@ExpHP
Last active December 12, 2017 23:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ExpHP/141cbba9281385087d48220d808a1b6e to your computer and use it in GitHub Desktop.
Save ExpHP/141cbba9281385087d48220d808a1b6e to your computer and use it in GitHub Desktop.
use ::std::ops::{Add, Sub, Neg};
pub trait AddSub2<OtherP>
: Sized
+ Add<<Self as AddSub2<OtherP>>::Zero, Output=Self>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=Self>
+ Add<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::Add>
+ Add<Self>
+ Sub<Self, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Add, Output=<Self as AddSub2<OtherP>>::NOther>
+ Add<<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::Sub, Output=<Self as AddSub2<OtherP>>::Other>
+ Add<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::NSub, Output=<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::NAdd, Output=<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::NAdd>
{
type Zero
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::NOther>
+ Add<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::Other>
+ Add<Self, Output=Self>
+ Sub<Self, Output=<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::Add, Output=<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Add, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Add<<Self as AddSub2<OtherP>>::Sub, Output=<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::Sub, Output=<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::Neg, Output=Self>
+ Add<<Self as AddSub2<OtherP>>::NSub, Output=<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::NSub, Output=<Self as AddSub2<OtherP>>::Sub>
+ Add<OtherP, Output=<Self as AddSub2<OtherP>>::Other>
+ Sub<OtherP, Output=<Self as AddSub2<OtherP>>::NOther>
+ Add<<Self as AddSub2<OtherP>>::NAdd, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::NAdd, Output=<Self as AddSub2<OtherP>>::Add>
;
type Other
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Other>
+ Add<<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::NOther>
+ Add<Self, Output=<Self as AddSub2<OtherP>>::Add>
+ Sub<Self, Output=<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Add, Output=<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::Sub, Output=Self>
+ Sub<<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::Add>
+ Add<<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::NSub, Output=Self>
+ Add<<Self as AddSub2<OtherP>>::NAdd, Output=<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::NAdd>
;
type NOther
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::NOther>
+ Add<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::Other>
+ Add<<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<Self, Output=<Self as AddSub2<OtherP>>::Sub>
+ Sub<Self, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Add<<Self as AddSub2<OtherP>>::Add, Output=Self>
+ Sub<<Self as AddSub2<OtherP>>::Add>
+ Add<<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::Sub, Output=<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::NSub, Output=<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::NAdd, Output=Self>
;
type Add
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Add>
+ Add<<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::Other, Output=Self>
+ Add<<Self as AddSub2<OtherP>>::NOther, Output=Self>
+ Sub<<Self as AddSub2<OtherP>>::NOther>
+ Add<Self>
+ Sub<Self, Output=<Self as AddSub2<OtherP>>::Other>
+ Add<<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Add, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::NAdd, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::NAdd>
;
type Sub
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::Other, Output=Self>
+ Sub<<Self as AddSub2<OtherP>>::Other>
+ Add<<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::NOther, Output=Self>
+ Add<Self>
+ Sub<Self, Output=<Self as AddSub2<OtherP>>::NOther>
+ Add<<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Add>
+ Add<<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::Sub, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::NSub, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::NAdd>
;
type Neg
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Add<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::NSub>
+ Add<Self, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<Self>
+ Add<<Self as AddSub2<OtherP>>::Add, Output=<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::Add>
+ Add<<Self as AddSub2<OtherP>>::Sub, Output=<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::NSub, Output=<Self as AddSub2<OtherP>>::NOther>
+ Add<<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::NAdd, Output=<Self as AddSub2<OtherP>>::Other>
;
type NSub
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::Other>
+ Sub<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::Neg>
+ Add<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::NOther>
+ Add<Self, Output=<Self as AddSub2<OtherP>>::Other>
+ Sub<Self>
+ Add<<Self as AddSub2<OtherP>>::Add>
+ Sub<<Self as AddSub2<OtherP>>::Add>
+ Add<<Self as AddSub2<OtherP>>::Sub, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::Other>
+ Add<<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::NSub, Output=<Self as AddSub2<OtherP>>::Zero>
+ Add<<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::NAdd>
;
type NAdd
: Add<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::Zero, Output=<Self as AddSub2<OtherP>>::NAdd>
+ Add<<Self as AddSub2<OtherP>>::Other, Output=<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::Other>
+ Add<<Self as AddSub2<OtherP>>::NOther>
+ Sub<<Self as AddSub2<OtherP>>::NOther, Output=<Self as AddSub2<OtherP>>::Neg>
+ Add<Self, Output=<Self as AddSub2<OtherP>>::NOther>
+ Sub<Self>
+ Add<<Self as AddSub2<OtherP>>::Add, Output=<Self as AddSub2<OtherP>>::Zero>
+ Sub<<Self as AddSub2<OtherP>>::Add>
+ Add<<Self as AddSub2<OtherP>>::Sub>
+ Sub<<Self as AddSub2<OtherP>>::Sub>
+ Add<<Self as AddSub2<OtherP>>::Neg>
+ Sub<<Self as AddSub2<OtherP>>::Neg, Output=<Self as AddSub2<OtherP>>::NOther>
+ Add<<Self as AddSub2<OtherP>>::NSub>
+ Sub<<Self as AddSub2<OtherP>>::NSub>
+ Add<<Self as AddSub2<OtherP>>::NAdd>
+ Sub<<Self as AddSub2<OtherP>>::NAdd, Output=<Self as AddSub2<OtherP>>::Zero>
;
}
impl<ZeroP, OtherP, NOtherP, A, AddP, SubP, NegP, NSubP, NAddP> AddSub2<OtherP> for A
where
ZeroP
: Add<ZeroP, Output=ZeroP>
+ Sub<ZeroP, Output=ZeroP>
+ Add<OtherP, Output=OtherP>
+ Sub<OtherP, Output=NOtherP>
+ Add<NOtherP, Output=NOtherP>
+ Sub<NOtherP, Output=OtherP>
+ Add<A, Output=A>
+ Sub<A, Output=NegP>
+ Add<AddP, Output=AddP>
+ Sub<AddP, Output=NAddP>
+ Add<SubP, Output=SubP>
+ Sub<SubP, Output=NSubP>
+ Add<NegP, Output=NegP>
+ Sub<NegP, Output=A>
+ Add<NSubP, Output=NSubP>
+ Sub<NSubP, Output=SubP>
+ Add<NAddP, Output=NAddP>
+ Sub<NAddP, Output=AddP>
,
OtherP
: Add<ZeroP, Output=OtherP>
+ Sub<ZeroP, Output=OtherP>
+ Add<OtherP>
+ Sub<OtherP, Output=ZeroP>
+ Add<NOtherP, Output=ZeroP>
+ Sub<NOtherP>
+ Add<A, Output=AddP>
+ Sub<A, Output=NSubP>
+ Add<AddP>
+ Sub<AddP, Output=NegP>
+ Add<SubP, Output=A>
+ Sub<SubP>
+ Add<NegP, Output=NSubP>
+ Sub<NegP, Output=AddP>
+ Add<NSubP>
+ Sub<NSubP, Output=A>
+ Add<NAddP, Output=NegP>
+ Sub<NAddP>
,
NOtherP
: Add<ZeroP, Output=NOtherP>
+ Sub<ZeroP, Output=NOtherP>
+ Add<OtherP, Output=ZeroP>
+ Sub<OtherP>
+ Add<NOtherP>
+ Sub<NOtherP, Output=ZeroP>
+ Add<A, Output=SubP>
+ Sub<A, Output=NAddP>
+ Add<AddP, Output=A>
+ Sub<AddP>
+ Add<SubP>
+ Sub<SubP, Output=NegP>
+ Add<NegP, Output=NAddP>
+ Sub<NegP, Output=SubP>
+ Add<NSubP, Output=NegP>
+ Sub<NSubP>
+ Add<NAddP>
+ Sub<NAddP, Output=A>
,
A
: Sized
+ Add<ZeroP, Output=A>
+ Sub<ZeroP, Output=A>
+ Add<OtherP, Output=AddP>
+ Sub<OtherP, Output=SubP>
+ Add<NOtherP, Output=SubP>
+ Sub<NOtherP, Output=AddP>
+ Add<A>
+ Sub<A, Output=ZeroP>
+ Add<AddP>
+ Sub<AddP, Output=NOtherP>
+ Add<SubP>
+ Sub<SubP, Output=OtherP>
+ Add<NegP, Output=ZeroP>
+ Sub<NegP>
+ Add<NSubP, Output=OtherP>
+ Sub<NSubP>
+ Add<NAddP, Output=NOtherP>
+ Sub<NAddP>
,
AddP
: Add<ZeroP, Output=AddP>
+ Sub<ZeroP, Output=AddP>
+ Add<OtherP>
+ Sub<OtherP, Output=A>
+ Add<NOtherP, Output=A>
+ Sub<NOtherP>
+ Add<A>
+ Sub<A, Output=OtherP>
+ Add<AddP>
+ Sub<AddP, Output=ZeroP>
+ Add<SubP>
+ Sub<SubP>
+ Add<NegP, Output=OtherP>
+ Sub<NegP>
+ Add<NSubP>
+ Sub<NSubP>
+ Add<NAddP, Output=ZeroP>
+ Sub<NAddP>
,
SubP
: Add<ZeroP, Output=SubP>
+ Sub<ZeroP, Output=SubP>
+ Add<OtherP, Output=A>
+ Sub<OtherP>
+ Add<NOtherP>
+ Sub<NOtherP, Output=A>
+ Add<A>
+ Sub<A, Output=NOtherP>
+ Add<AddP>
+ Sub<AddP>
+ Add<SubP>
+ Sub<SubP, Output=ZeroP>
+ Add<NegP, Output=NOtherP>
+ Sub<NegP>
+ Add<NSubP, Output=ZeroP>
+ Sub<NSubP>
+ Add<NAddP>
+ Sub<NAddP>
,
NegP
: Add<ZeroP, Output=NegP>
+ Sub<ZeroP, Output=NegP>
+ Add<OtherP, Output=NSubP>
+ Sub<OtherP, Output=NAddP>
+ Add<NOtherP, Output=NAddP>
+ Sub<NOtherP, Output=NSubP>
+ Add<A, Output=ZeroP>
+ Sub<A>
+ Add<AddP, Output=OtherP>
+ Sub<AddP>
+ Add<SubP, Output=NOtherP>
+ Sub<SubP>
+ Add<NegP>
+ Sub<NegP, Output=ZeroP>
+ Add<NSubP>
+ Sub<NSubP, Output=NOtherP>
+ Add<NAddP>
+ Sub<NAddP, Output=OtherP>
,
NSubP
: Add<ZeroP, Output=NSubP>
+ Sub<ZeroP, Output=NSubP>
+ Add<OtherP>
+ Sub<OtherP, Output=NegP>
+ Add<NOtherP, Output=NegP>
+ Sub<NOtherP>
+ Add<A, Output=OtherP>
+ Sub<A>
+ Add<AddP>
+ Sub<AddP>
+ Add<SubP, Output=ZeroP>
+ Sub<SubP>
+ Add<NegP>
+ Sub<NegP, Output=OtherP>
+ Add<NSubP>
+ Sub<NSubP, Output=ZeroP>
+ Add<NAddP>
+ Sub<NAddP>
,
NAddP
: Add<ZeroP, Output=NAddP>
+ Sub<ZeroP, Output=NAddP>
+ Add<OtherP, Output=NegP>
+ Sub<OtherP>
+ Add<NOtherP>
+ Sub<NOtherP, Output=NegP>
+ Add<A, Output=NOtherP>
+ Sub<A>
+ Add<AddP, Output=ZeroP>
+ Sub<AddP>
+ Add<SubP>
+ Sub<SubP>
+ Add<NegP>
+ Sub<NegP, Output=NOtherP>
+ Add<NSubP>
+ Sub<NSubP>
+ Add<NAddP>
+ Sub<NAddP, Output=ZeroP>
,
{
type Zero = ZeroP;
type Other = OtherP;
type NOther = NOtherP;
type Add = AddP;
type Sub = SubP;
type Neg = NegP;
type NSub = NSubP;
type NAdd = NAddP;
}
fn foo<A: AddSub2<B>, B>(a: A, b: B) {
// This only works if
// + Add<OtherP, Output=<Self as AddSub2<OtherP>>::Other>
// is the very last "Add" bound in the list of bounds on AddSub2::Zero.
a - a + b;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment