@@ -63,10 +63,16 @@ func (val Value) String() string {
6363 return typ .String () + "<null>"
6464 }
6565
66- // TODO: print refinements
67-
6866 if ! val .IsKnown () {
69- return typ .String () + "<unknown>"
67+ var res strings.Builder
68+ res .WriteString (typ .String ())
69+ res .WriteString ("<unknown" )
70+ if len (val .refinements ) > 0 {
71+ res .WriteString (", " + val .Refinements ().String ())
72+ }
73+ res .WriteString (">" )
74+
75+ return res .String ()
7076 }
7177
7278 // everything else is built up
@@ -230,7 +236,13 @@ func (val Value) Equal(o Value) bool {
230236 return false
231237 }
232238
233- // TODO: compare refinements
239+ if len (val .refinements ) != len (o .refinements ) {
240+ return false
241+ }
242+
243+ if len (val .refinements ) > 0 && ! val .refinements .Equal (o .refinements ) {
244+ return false
245+ }
234246
235247 deepEqual , err := val .deepEqual (o )
236248 if err != nil {
@@ -242,9 +254,6 @@ func (val Value) Equal(o Value) bool {
242254// Copy returns a defensively-copied clone of Value that shares no underlying
243255// data structures with the original Value and can be mutated without
244256// accidentally mutating the original.
245- //
246- // TODO: Make sure this actually works for refinements. Consuming packages should not be able to mutate refinements of val
247- // TODO: Add docs referencing refinements
248257func (val Value ) Copy () Value {
249258 newVal := val .value
250259 switch v := val .value .(type ) {
@@ -263,7 +272,15 @@ func (val Value) Copy() Value {
263272 }
264273
265274 newTfValue := NewValue (val .Type (), newVal )
266- newTfValue .refinements = val .refinements
275+
276+ if len (val .refinements ) > 0 {
277+ newRefinements := make (refinement.Refinements , len (val .refinements ))
278+ for key , refnVal := range val .refinements {
279+ newRefinements [key ] = refnVal
280+ }
281+
282+ newTfValue .refinements = newRefinements
283+ }
267284
268285 return newTfValue
269286}
@@ -611,19 +628,28 @@ func unexpectedValueTypeError(p *AttributePath, expected, got interface{}, typ T
611628 return p .NewErrorf ("unexpected value type %T, %s values must be of type %T" , got , typ , expected )
612629}
613630
614- // TODO: do we need to return an error? Like if you attempt to refine a value improperly (like string prefix on a number)?
631+ // TODO: doc, mention returning value if not unknown
615632func (val Value ) Refine (refinements refinement.Refinements ) Value {
616633 newVal := val .Copy ()
617634
635+ // Refinements are only relevant for unknown values
636+ if val .IsKnown () {
637+ return newVal
638+ }
639+
618640 if len (refinements ) >= 0 {
619- newVal .refinements = refinements
641+ newRefinements := make (refinement.Refinements , len (refinements ))
642+ for key , refnVal := range refinements {
643+ newRefinements [key ] = refnVal
644+ }
645+ newVal .refinements = newRefinements
620646 }
621647
622648 return newVal
623649}
624650
651+ // TODO: doc, mention copy
625652func (val Value ) Refinements () refinement.Refinements {
626- // TODO: is this copy really needed?
627653 valCopy := val .Copy ()
628654
629655 return valCopy .refinements
0 commit comments