aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/test/opaque_SUITE_data/src/simple/exact_api.erl
blob: c19330eb30dd6a2cd1f952942db21ce9e121d526 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
-module(exact_api).

-export([new/0, exact_api_test/1, exact_api_new/1,
         exact_adt_test/1, exact_adt_new/1]).

-export_type([exact_api/0]).

-record(digraph, {vtab = notable :: ets:tab(),
		  etab = notable :: ets:tab(),
		  ntab = notable :: ets:tab(),
	          cyclic = true  :: boolean()}).

-spec new() -> digraph:graph().

new() ->
    A = #digraph{},
    set_type(A), % does not have an opaque term as 1st argument
    A.

-spec set_type(digraph:graph()) -> true.

set_type(G) ->
    digraph:delete(G).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%% The derived spec of exact_api_new() is
%%% -spec exact_api_new(exact_api:exact_api()) -> exact_api:exact_api().
%%% This won't happen unless dialyzer_typesig uses
%%% t_is_exactly_equal() rather than t_is_equal().
%%% [As of R17B the latter considers two types equal if nothing but
%%%  their ?opaque tags differ.]

-record(exact_api, {}).

-opaque exact_api() :: #exact_api{}.

exact_api_test(X) ->
    #exact_api{} = exact_api_set_type(X). % OK

exact_api_new(A) ->
    A = #exact_api{},
    _ = exact_api_set_type(A), % OK (the opaque type is local)
    A.

-spec exact_api_set_type(exact_api()) -> exact_api().

exact_api_set_type(#exact_api{}=E) -> E.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-record(exact_adt, {}).

exact_adt_test(X) ->
    #exact_adt{} = exact_adt:exact_adt_set_type(X). % breaks the opaqueness

exact_adt_new(A) ->
    A = #exact_adt{},
    _ = exact_adt:exact_adt_set_type2(A), % does not have an opaque term as 1st argument
    A.