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

How to idiomatically copy a slice?
Recursive types and arrays
Can I determine the zero value of generic types?
How to slice a large Vec<i32> as &[u8]?
How to parse i64 from a string? [duplicate]
Why is variable scope dependent on the definition order?
Warning on “unstable” directive
How can I pass a socket as an argument to a function being called within a thread?
error: cannot move out of borrowed content on &mut self
Why does a reference not live long enough in case of “as_slice”?
Getting the error “error: the trait `core::marker::Sized` is not implemented” when trying to return the value from a vector
Traits with associated type in templates
Error handling best-practices
How to call count on an iterator and still use the iterator's items?
Caught between a lifetime and an FFI place
How to swap elements of array?

Categories

HOME
hpoo
orientdb
macos-sierra
seedstack
android-fragments
softlayer
compilation
haproxy
hid
stacktrace.js
dafny
openlayers-3
ios-simulator
magento-2.0
impala
fedora
save
polymer-2.x
migrate
lapack
getopenfilename
bootstrap-switch
google-awareness
mailgun
supervisord
rpmbuild
angular2-highcharts
node-webkit
weex
fluent-migrator
mod-wsgi
tortoisemerge
sales
social-networking
dotcms
cordys-opentext
uivisualeffectview
export-to-pdf
icepdf
notesview
doctrine-extensions
realstudio
dredd
md5-file
entropy
visual-format-language
scala-collections
asp.net-web-api-routing
deedle
gmaps.js
mifos
bigdecimal
libharu
dmarc
carmen
facebook-ios-sdk
mathnet
gridbaglayout
univocity
textpattern
fanotify
cfwheels
jnlp
hmisc
search-form
android-handler
prism-4
mgwt
dc
visual-studio-6
lmax
angular-ui-select
squeezebox
code-complexity
forceclose
application-server
mp4parser
codahale-metrics
statechart
jsplitpane
smartfox
audiotoolbox
trialware
liveconnect
django-apps
server-variables
nsrangeexception
nosetests
digiflow
pyjamas
j2mepolish
zend-test
subtext
html-generation

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