22
22
//! into sets, use the `Value` type of `()`.
23
23
//!
24
24
//! When you have keys with non-trivial values, you must also define
25
- //! how those values can be merged. If this merging is infallible, you
26
- //! should implement the `InfallibleUnifyValue` trait, which unlocks
27
- //! various more ergonomic methods (e.g., `union()` in place of
28
- //! `unify_var_var()`).
25
+ //! how those values can be merged. As part of doing this, you can
26
+ //! define the "error" type to return on error; if errors are not
27
+ //! possible, use `NoError` (an uninstantiable struct). Using this
28
+ //! type also unlocks various more ergonomic methods (e.g., `union()`
29
+ //! in place of `unify_var_var()`).
29
30
30
31
use std:: marker;
31
32
use std:: fmt:: Debug ;
@@ -76,14 +77,63 @@ pub trait UnifyKey : Copy + Clone + Debug + PartialEq {
76
77
}
77
78
}
78
79
80
+ /// Trait implemented for **values** associated with a unification
81
+ /// key. This trait defines how to merge the values from two keys that
82
+ /// are unioned together. This merging can be fallible. If you attempt
83
+ /// to union two keys whose values cannot be merged, then the error is
84
+ /// propagated up and the two keys are not unioned.
85
+ ///
86
+ /// This crate provides implementations of `UnifyValue` for `()`
87
+ /// (which is infallible) and `Option<T>` (where `T: UnifyValue`). The
88
+ /// option implementation merges two sum-values using the `UnifyValue`
89
+ /// implementation of `T`.
90
+ ///
91
+ /// See also `EqUnifyValue`, which is a convenience trait for cases
92
+ /// where the "merge" operation succeeds only if the two values are
93
+ /// equal.
79
94
pub trait UnifyValue : Clone + Debug {
95
+ /// Defines the type to return when merging of two values fails.
96
+ /// If merging is infallible, use the special struct `NoError`
97
+ /// found in this crate, which unlocks various more convenient
98
+ /// methods on the unification table.
99
+ type Error ;
100
+
80
101
/// Given two values, produce a new value that combines them.
81
102
/// If that is not possible, produce an error.
82
- fn unify_values ( value1 : & Self , value2 : & Self ) -> Result < Self , ( Self , Self ) > ;
103
+ fn unify_values ( value1 : & Self , value2 : & Self ) -> Result < Self , Self :: Error > ;
104
+ }
105
+
106
+ /// A convenient helper for unification values which must be equal or
107
+ /// else an error occurs. For example, if you are unifying types in a
108
+ /// simple functional language, this may be appropriate, since (e.g.)
109
+ /// you can't unify a type variable bound to `int` with one bound to
110
+ /// `float` (but you can unify two type variables both bound to
111
+ /// `int`).
112
+ ///
113
+ /// Any type which implements `EqUnifyValue` automatially implements
114
+ /// `UnifyValue`; if the two values are equal, merging is permitted.
115
+ /// Otherwise, the error `(v1, v2)` is returned, where `v1` and `v2`
116
+ /// are the two unequal values.
117
+ pub trait EqUnifyValue : Eq + Clone + Debug {
118
+ }
119
+
120
+ impl < T : EqUnifyValue > UnifyValue for T {
121
+ type Error = ( T , T ) ;
122
+
123
+ fn unify_values ( value1 : & Self , value2 : & Self ) -> Result < Self , Self :: Error > {
124
+ if value1 == value2 {
125
+ Ok ( value1. clone ( ) )
126
+ } else {
127
+ Err ( ( value1. clone ( ) , value2. clone ( ) ) )
128
+ }
129
+ }
83
130
}
84
131
85
- /// Marker trait which indicates that `UnifyValues::unify_values` will never return `Err`.
86
- pub trait InfallibleUnifyValue : UnifyValue {
132
+ /// A struct which can never be instantiated. Used
133
+ /// for the error type for infallible cases.
134
+ #[ derive( Debug ) ]
135
+ pub struct NoError {
136
+ _dummy : ( )
87
137
}
88
138
89
139
/// Value of a unification key. We implement Tarjan's union-find
@@ -393,7 +443,7 @@ impl<'tcx, K, V> UnificationTable<K>
393
443
/// Unions two keys without the possibility of failure; only
394
444
/// applicable to InfallibleUnifyValue.
395
445
pub fn union ( & mut self , a_id : K , b_id : K )
396
- where V : InfallibleUnifyValue
446
+ where V : UnifyValue < Error = NoError >
397
447
{
398
448
self . unify_var_var ( a_id, b_id) . unwrap ( ) ;
399
449
}
@@ -408,7 +458,7 @@ impl<'tcx, K, V> UnificationTable<K>
408
458
self . get_root_key ( id)
409
459
}
410
460
411
- pub fn unify_var_var ( & mut self , a_id : K , b_id : K ) -> Result < ( ) , ( V , V ) > {
461
+ pub fn unify_var_var ( & mut self , a_id : K , b_id : K ) -> Result < ( ) , V :: Error > {
412
462
let root_a = self . get_root_key ( a_id) ;
413
463
let root_b = self . get_root_key ( b_id) ;
414
464
@@ -423,7 +473,7 @@ impl<'tcx, K, V> UnificationTable<K>
423
473
424
474
/// Sets the value of the key `a_id` to `b`, attempting to merge
425
475
/// with the previous value.
426
- pub fn unify_var_value ( & mut self , a_id : K , b : V ) -> Result < ( ) , ( V , V ) > {
476
+ pub fn unify_var_value ( & mut self , a_id : K , b : V ) -> Result < ( ) , V :: Error > {
427
477
let root_a = self . get_root_key ( a_id) ;
428
478
let value = try!( V :: unify_values ( & self . value ( root_a) . value , & b) ) ;
429
479
self . update_value ( root_a, |node| node. value = value) ;
@@ -440,28 +490,26 @@ impl<'tcx, K, V> UnificationTable<K>
440
490
///////////////////////////////////////////////////////////////////////////
441
491
442
492
impl UnifyValue for ( ) {
443
- fn unify_values ( _: & ( ) , _: & ( ) ) -> Result < ( ) , ( ( ) , ( ) ) > {
493
+ type Error = NoError ;
494
+
495
+ fn unify_values ( _: & ( ) , _: & ( ) ) -> Result < ( ) , NoError > {
444
496
Ok ( ( ) )
445
497
}
446
498
}
447
499
448
- impl InfallibleUnifyValue for ( ) {
449
- }
450
-
451
500
impl < V : UnifyValue > UnifyValue for Option < V > {
452
- fn unify_values ( a : & Option < V > , b : & Option < V > ) -> Result < Self , ( Self , Self ) > {
501
+ type Error = V :: Error ;
502
+
503
+ fn unify_values ( a : & Option < V > , b : & Option < V > ) -> Result < Self , V :: Error > {
453
504
match ( a, b) {
454
505
( & None , & None ) => Ok ( None ) ,
455
506
( & Some ( ref v) , & None ) | ( & None , & Some ( ref v) ) => Ok ( Some ( v. clone ( ) ) ) ,
456
507
( & Some ( ref a) , & Some ( ref b) ) => {
457
508
match V :: unify_values ( a, b) {
458
509
Ok ( v) => Ok ( Some ( v) ) ,
459
- Err ( ( a , b ) ) => Err ( ( Some ( a ) , Some ( b ) ) ) ,
510
+ Err ( err ) => Err ( err ) ,
460
511
}
461
512
}
462
513
}
463
514
}
464
515
}
465
-
466
- impl < V : InfallibleUnifyValue > InfallibleUnifyValue for Option < V > {
467
- }
0 commit comments