rust


unconstrained type parameter error


I'm trying to interface glium with cgmath. Following this answer, I have implemented a ToArray trait to convert instances of cgmath::Matrix4 into a format usable by glium:
pub trait ToArray {
type Output;
fn to_array(&self) -> Self::Output;
}
impl<S: cgmath::BaseNum> ToArray for cgmath::Matrix4<S> {
type Output = [[S; 4]; 4];
fn to_array(&self) -> Self::Output {
(*self).into()
}
}
Since I don't always use Matrix4 directly, I need a similar implementation for cgmath transform types. For example for cgmath::Decomposed:
impl<S: cgmath::BaseFloat, R: cgmath::Rotation3<S>> ToArray
for cgmath::Decomposed<cgmath::Vector3<S>, R> {
type Output = [[S; 4]; 4];
fn to_array(&self) -> Self::Output {
cgmath::Matrix4::<S>::from(*self).into()
}
}
This works, but I'd like to avoid duplicating the code for all transform types, so I thought I would define a generic implementation for anything that can be converted to a Matrix4:
impl<S: cgmath::BaseFloat, T: Into<cgmath::Matrix4<S>>> ToArray for T {
type Output = [[S; 4]; 4];
fn to_array(&self) -> Self::Output {
cgmath::Matrix4::<S>::from(*self).into()
}
}
Unfortunately, this doesn't work:
error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates
--> src/main.rs:23:6
|
23 | impl<S: cgmath::BaseFloat, T: Into<cgmath::Matrix4<S>>> ToArray for T {
| ^ unconstrained type parameter
I have two questions:
Why doesn't the above code work? From reading the rustc --explain output, I would expect the T: Into<cgmath::Matrix4<S>> to act as a valid constraint on S as well as T.
How can I write a generic implementation for anything that can be converted into a Matrix4?
Imagine I defined a type like this1:
struct PolymorphicMatrix;
impl Into<cgmath::Matrix4<f32>> for PolymorphicMatrix {
fn into(self) -> cgmath::Matrix4<f32> {
cgmath::Matrix4::new(
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0)
}
}
impl Into<cgmath::Matrix4<f64>> for PolymorphicMatrix {
fn into(self) -> cgmath::Matrix4<f64> {
cgmath::Matrix4::new(
2.0, 2.0, 2.0, 2.0,
2.0, 2.0, 2.0, 2.0,
2.0, 2.0, 2.0, 2.0,
2.0, 2.0, 2.0, 2.0)
}
}
Which of these impls will be used to implement ToArray? Both are applicable, but you can only implement ToArray once for PolymorphicMatrix, because ToArray has no type parameters. That's what the error means: it's not valid because it would cause issues in a situation like this.
Since you control neither Into nor cgmath::Matrix4, the only aspect you can change is ToArray. You can add a type parameter that is not used in the trait definition itself, and implementations can use that type parameter.
pub trait ToArray<S> {
type Output;
fn to_array(&self) -> Self::Output;
}
impl<S: cgmath::BaseFloat, T: Into<cgmath::Matrix4<S>>> ToArray<S> for T {
type Output = [[S; 4]; 4];
fn to_array(&self) -> Self::Output {
cgmath::Matrix4::<S>::from(*self).into()
}
}
Naturally, you can't enforce any kind of correlation between S and Output. Also, that type parameter might cause some ambiguities: since it's not used in the trait, the compiler might not be able to infer S from usage in some situations, so you may have to specify it explicitly. If that becomes a problem, you might want to explore using generic-array. It would let you lift the array dimensions to type parameters, so that you could get rid of the associated type and instead use the type parameters directly in the return type of to_array, which would help the compiler's inference.
1 Normally, one would implement From rather than Into. I'm using Into here to stay closer to the problem as stated.

Related Links

Changing key of HashMap from child method
Cannot build a delete function for a binary search tree in Rust because the borrowed value does not live long enough
Why does AtomicUsize not implement Send?
How can I define a list of functions to call? [duplicate]
How can I tell if a Rust library is deprecated?
error: non-scalar cast: `core::option::Option<i32>` as `usize`
Lifetime of variable in map/flat_map in Rust
Can associated constants be used to initialize fixed size arrays?
Why do Arc and Mutex allow me to change the value of an immutable variable?
Unable to download a package via cargo — timeout
“borrowed value does not live long enough” seems to blame the wrong thing
Is the destructor of Arc guaranteed to be called before upgrading a Weak reference will return None?
Can't find crate for `rayon`
How to write a function that returns Vec<Path>?
How to implement a long running process with progress in Rust, available via a Rest api?
Iterator that returns each Nth value

Categories

HOME
extjs
protocol-buffers
memory
macos-sierra
svn
yii
activemq
azure-mobile-services
ag-grid
firebase-dynamic-links
minecraft
wagtail
native-base
jpa-criteria
bellman-ford
elastic-load-balancer
match
amazon-emr
bootstrap-switch
fullcalendar-scheduler
smartgwt
mailgun
synthesis
mixpanel
scala-ide
pickle
boomi
nose
cmake-gui
fido-u2f
kamailio
stackexchange.redis
perfino
cell
pdf.js
opentext
unordered-multimap
fusetools
unrar
beego
ccavenue
serversocket
gnu-classpath
selenide
stat
fiware-wirecloud
gcal
liteide
viewmodel
nothing
uiautomatorviewer
head.js
nslayoutconstraint
degrees
google-shopping-api
yargs
cefpython
e
fuzzer
p6spy
ajaxmin
urbit
polymerfire
as3-api
flush
outlook.com
textpattern
bayesglm
apache-commons-digester
android-studio-import
auto-generate
blockquote
replicaset
artisan
tree-structure
gflags
mxe
tkx
jcheckbox
uno
dc
zend-mail
dmake
qt5.4
mobile-country-code
nachos
armv6
compiler-flags
mute
tnt4j
contextswitchdeadlock
red-system
wndproc
websphere-6.1
kolite
differentiation
qt-mobility
ognl
mygeneration
iphone-sdk-4.3
ppc
main-method
remote-working

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App