Skip to content

Commit 92815dd

Browse files
committed
asyncpi/types: Refine errors.
Wrap all errors in exported functions.
1 parent d4a6167 commit 92815dd

File tree

3 files changed

+48
-20
lines changed

3 files changed

+48
-20
lines changed

internal/errors/errors.go

+5
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,8 @@ func Wrap(err error, msg string) error {
5858
msg: msg,
5959
}
6060
}
61+
62+
// Causer returns the cause of the error.
63+
type Causer interface {
64+
Cause() error
65+
}

types/infer.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ func processInferType(p asyncpi.Process) error {
159159
return nil
160160
}
161161

162+
func errUnify(err error) error {
163+
return errors.Wrap(err, "cannot unify types")
164+
}
165+
162166
// Unify combines the constraints of sending and receiving channels
163167
// with best effort.
164168
//
@@ -177,7 +181,7 @@ func Unify(p asyncpi.Process) error {
177181
case *asyncpi.Recv:
178182
ch, isTyped := p.Chan.(TypedName)
179183
if !isTyped {
180-
return InferUntypedError{Name: p.Chan.Ident()}
184+
return errUnify(InferUntypedError{Name: p.Chan.Ident()})
181185
}
182186
// chType is either
183187
// - a compType with refType fields (including struct{})
@@ -187,7 +191,7 @@ func Unify(p asyncpi.Process) error {
187191
for _, v := range p.Vars {
188192
tv, isTyped := v.(TypedName)
189193
if !isTyped {
190-
return InferUntypedError{Name: v.Ident()}
194+
return errUnify(InferUntypedError{Name: v.Ident()})
191195
}
192196
tns = append(tns, tv)
193197
}
@@ -209,27 +213,27 @@ func Unify(p asyncpi.Process) error {
209213
} else if IsEqual(varType, tns[0].Type()) {
210214
// Type is both set but equal
211215
} else {
212-
return &TypeError{
216+
return errUnify(&TypeError{
213217
T: varType,
214218
U: tns[0].Type(),
215219
Msg: fmt.Sprintf("Types inferred from channel %s are in conflict", p.Chan.Ident()),
216-
}
220+
})
217221
}
218222
}
219223
default:
220224
compT, isComp := varType.(*Composite)
221225
if !isComp {
222-
return &TypeArityError{
226+
return errUnify(&TypeArityError{
223227
Got: 1,
224228
Expected: len(p.Vars),
225229
Msg: fmt.Sprintf("Types from channel %s and vars have different arity", p.Chan.Ident()),
226-
}
230+
})
227231
} else if len(tns) != len(compT.Elems()) {
228-
return &TypeArityError{
232+
return errUnify(&TypeArityError{
229233
Got: len(compT.Elems()),
230234
Expected: len(p.Vars),
231235
Msg: fmt.Sprintf("Types from channel %s and vars have different arity", p.Chan.Ident()),
232-
}
236+
})
233237
}
234238
for i := range tns {
235239
if _, ok := tns[i].Type().(*anyType); ok {
@@ -239,11 +243,11 @@ func Unify(p asyncpi.Process) error {
239243
} else if IsEqual(compT.elems[i], tns[i].Type()) {
240244
// Type is both set but equal
241245
} else {
242-
return &TypeError{
246+
return errUnify(&TypeError{
243247
T: varType,
244248
U: tns[i].Type(),
245249
Msg: fmt.Sprintf("Types inferred from channel %s are in conflict", p.Chan.Ident()),
246-
}
250+
})
247251
}
248252
}
249253
}
@@ -252,6 +256,8 @@ func Unify(p asyncpi.Process) error {
252256
return Unify(p.Proc)
253257
case *asyncpi.Restrict:
254258
return Unify(p.Proc)
259+
default:
260+
return errUnify(asyncpi.UnknownProcessError{Proc: p})
255261
}
256262
return nil
257263
}

types/type_test.go

+27-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"go.nickng.io/asyncpi"
8+
"go.nickng.io/asyncpi/internal/errors"
89
)
910

1011
// Tests type inference only.
@@ -381,8 +382,12 @@ func TestInferUnifyNested(t *testing.T) {
381382
t.Errorf("Infer: Type of `a` is not %s\n got: %s",
382383
atype, resa.Name.(TypedName).Type())
383384
}
384-
Infer(proc)
385-
Unify(proc)
385+
if err := Infer(proc); err != nil {
386+
t.Fatal(err)
387+
}
388+
if err := Unify(proc); err != nil {
389+
t.Fatal(err)
390+
}
386391
inferredResa, ok := proc.(*asyncpi.Restrict)
387392
if !ok {
388393
t.Errorf("Parse: `%s` does not begin with restriction", nested)
@@ -421,10 +426,12 @@ func TestInferUnifyNamePassing(t *testing.T) {
421426
if !ok {
422427
t.Errorf("Parse: `%s` does not begin with restriction", namePassing)
423428
}
429+
if err := Infer(proc); err != nil {
430+
t.Fatal(err)
431+
}
432+
if err := Unify(proc); err != nil {
424433
t.Fatal(err)
425434
}
426-
Infer(proc)
427-
Unify(proc)
428435
inferredResa, ok := proc.(*asyncpi.Restrict)
429436
if !ok {
430437
t.Errorf("Parse: `%s` does not begin with restriction", namePassing)
@@ -467,8 +474,12 @@ func TestInferNested(t *testing.T) {
467474
t.Errorf("Infer: Type of `a` is not %s\n got: %s",
468475
atype, resa.Name.(TypedName).Type())
469476
}
470-
Infer(proc)
471-
Unify(proc)
477+
if err := Infer(proc); err != nil {
478+
t.Fatal(err)
479+
}
480+
if err := Unify(proc); err != nil {
481+
t.Fatal(err)
482+
}
472483
inferredResa, ok := proc.(*asyncpi.Restrict)
473484
if !ok {
474485
t.Errorf("Parse: `%s` does not begin with restriction", nested)
@@ -497,10 +508,14 @@ func TestMismatchCompType(t *testing.T) {
497508
if err != nil {
498509
t.Fatal(err)
499510
}
500-
Infer(proc)
511+
if err := Infer(proc); err != nil {
512+
t.Fatal(err)
513+
}
501514
err = Unify(proc)
502-
if _, ok := err.(*TypeArityError); !ok {
503-
t.Fatalf("Unify: Expecting type error (mismatched args in a) but got %v", err)
515+
if err, ok := err.(errors.Causer); ok {
516+
if _, ok := err.Cause().(*TypeArityError); !ok {
517+
t.Fatalf("Unify: Expecting type error (mismatched args in a) but got %v", err)
518+
}
504519
}
505520
}
506521

@@ -511,7 +526,9 @@ func TestMultipleSender(t *testing.T) {
511526
if err != nil {
512527
t.Fatal(err)
513528
}
514-
Infer(proc)
529+
if err := Infer(proc); err != nil {
530+
t.Fatal(err)
531+
}
515532
if err := Unify(proc); err != nil {
516533
t.Fatal(err)
517534
}

0 commit comments

Comments
 (0)