89 Commits

Author SHA1 Message Date
DAILLER Sylvain
f91bb58b89 Generalization of check_unused_vars to logic and program decl
Description:
- Choice was made to not add unused variables when there is no contract
  and no body (no pre/(x)post, and no body).
- For postcondition variable result, we only check variables that are not
  of unit type. And, we report a warning only if the variable is not present
  in all the ensures.
- For result variable, with several imbricated raise, it seems possible to
  have false positive with no location. Removing the no location case which
  seems unhelpful anyway
2019-08-20 15:48:44 +02:00
Sylvain Dailler
431ed6caf3 "at/old operator unused" is now a warning not an error.
The warning can be disabled by a debug flag.
The bench was changed so as to accept examples that **should** output
warning but not fail (this category did not exist, it does now) and
label_scope has been switched to it.
2018-10-11 10:56:04 +02:00
Guillaume Melquiond
250deb85bd Clean examples. 2018-09-12 08:05:47 +02:00
Andrei Paskevich
e3cc32aa71 Parser: emit a warning on redundant "import" 2018-06-15 17:08:09 +02:00
Andrei Paskevich
54f1786730 Typing: reject invalid or useless "at"/"old"
Also, comment out a seemingly useless invariant in
examples/topological_sorting.mlw detected by the new check.
2018-03-15 14:55:46 +01:00
Andrei Paskevich
f9ff4e02ad Expr: execute abstract blocks and whiteboxes with unfiltered effect
This commit also contains a fix for a curious exploit of our type
system which was made possible by a combination of local exceptions
and a special treatment of abstract blocks and whiteboxes.

Local exceptions allow us to exploit the type inference mechanism
and to force the same regions onto unrelated expressions. This is due
to the fact that local exceptions are region-monomorphic (this may be
relaxed in future). Of course, this was always possible via the API,
and the false aliases do not threaten the soundness of the system,
thanks to the following critical invariant:

  An allocation of a new mutable value always has an associated reset
  effect which invalidates the existing variables of the same type.

So, if two variables share a region, then exactly one of three
conditions must hold:

1. They are actually aliased, and modification of one must change
   the other in the VC.

2. They are not aliased, but the newer one invalidates the other:
   this is a case of false alias made benign by the reset effect.

3. The shared region is not actually reachable from the newer one:
        let x = if true then None else Some r
   this is another false alias, without an associated reset effect,
   yet still benign since the shared region is not reachable from x.

However, the type system and the VC generator must have the exact
same view on who's who's alias. If the VCgen encounters in the
same control flow two variables with a shared region in the type,
then the type system must have ensured one of the three conditions
above. Prior to this commit, there were two cases which violated
this:

- An exception raised in an abstract block that does not have
  an exceptional postcondition for it, escapes into the main
  control flow.

- A whitebox, by its nature, is fully handled inside the main
  control flow.

The violation came from the fact that abstract blocks and whiteboxes
are stored as cexps and so their effect is filtered by Ity.create_cty
in order to hide effects on variables allocated and collected inside
the block. This is a useful and necessary feature, except when the
VC of the block escapes into the main control flow and the forced
false aliases -- unchecked by the type system -- are seen by VCgen.
The implemented fix resolves the issue by restoring the hidden
effects for abstract blocks and whiteboxes.

Check bench/programs/bad-typing/false_alias*.mlw for two concrete
examples.
2017-06-13 17:59:28 +02:00
Jean-Christophe Filliatre
d8d5512577 bench: valid goals 2017-05-15 10:40:41 +02:00
Andrei Paskevich
78ee406451 rename cty_oldies for recursive calls
This prevents us from binding the same oldie variable twice,
see bench/programs/good/rec_oldies.mlw
2017-01-01 21:34:26 +01:00
Andrei Paskevich
a949118f7c Merge remote-tracking branch 'origin/master' into new_system
The only recent change in master currently ignored in
this merge is renaming mach.Array.Array63.array to array63.
If we decide to give array types in mach.Array specific names,
we should do it for every size, and not only for 63 bits.
2016-03-07 18:06:43 +01:00
Andrei Paskevich
def34e584b minor 2016-02-22 18:24:40 +01:00
Jean-Christophe Filliatre
02be08fa14 updated bench/ 2016-02-22 16:10:13 +01:00
Andrei Paskevich
eda92a0bae Mlw_expr: fix potentially unsound pattern matching in programs
split the ppat_ghost field in program patterns into two distinct
conditions:
- ppat_ghost, indicating that the pattern starts as ghost,
  meaning that all variables in it are ghost, too;
- ppat_fail, meaning that the pattern contains a refutable
  ghost subpattern, which makes the match in the extracted code
  impossible, which makes the whole match expression ghost.

Until now, the two conditions were disjunctively combined, making
admissible the invalid pattern matching in bench/p/b-d/ghost4.mlw.
2016-01-10 21:58:46 +01:00
Léon Gondelman
c13b1932cf converted standard library and drivers 2015-08-24 15:36:41 +02:00
Martin Clochard
f4a0b25e27 bad-typing: new counter-example for variants (follows from 101b1f5) 2015-07-03 10:35:46 +02:00
Andrei Paskevich
135853377f Mlw_ty: add a missing check to eff_full_inst
This fixes a soundness bug in WhyML typechecking.
See bench/programs/bad-typing/alias6.mlw for an example
of illegal alias that would go uncatched until now.
2014-09-11 16:42:03 +02:00
Andrei Paskevich
83858597ce WhyML: add "diverges", "reads {}", and "writes {}" effect clauses
- "diverges" states that the computation may not terminate (which
  does not mean that is always diverges: just as any other effect
  annotation, this clause states a possibility of a side effect).

- "reads {}" states that the computation does not access any variable
  except those that are listed elsewhere in the specification (or the
  proper function arguments, if "reads" is in a function spec).

- "writes {}" states that the computation does not modify any mutable
  value.

- If a function definition or an abstract computation may diverge,
  but there is no "diverges" clause in the specification, a warning
  is produced. If a function definition or an abstract computation
  always terminates, but there is a "diverges" clause in the spec,
  an error is produced.

- If there is a "reads" or a "writes" clause in a function definition
  or an abstract computation, then every modified value must be listed
  in "writes" and every accessed external variable not mentioned in
  the spec must be listed in "reads". (Notice that this is a stricter
  requirement than before, when the presence of a "writes" clause
  did not require to specify "reads".) However, one does not have to
  write "reads {}" or "writes {}" if the corresponding lists are empty.
2014-01-20 12:51:32 +01:00
Andrei Paskevich
bb743fab69 fix WhyML warnings about unused variables in examples 2014-01-19 23:35:04 +01:00
Andrei Paskevich
9c1eff2811 WhyML: switch Mlw_typing to the new Mlw_dexpr-based API 2013-11-20 01:42:36 +01:00
Guillaume Melquiond
3f1a2e2c88 Fix typos. 2013-04-28 10:20:23 +02:00
Andrei Paskevich
d58c722c2f whyml: check soundness of polymorphic recursion 2013-04-24 16:23:18 +02:00
Andrei Paskevich
66257bde3f one more test 2013-04-23 00:24:06 +02:00
Andrei Paskevich
3cd56b05c0 whyml: ensure the absence of alias in function types
One exception to this rule is the the result type in a non-recursive
function may contain regions coming the function's arguments (though
not from the context). It is sometimes useful to write a function
around a constructor or a projection: see function [create] in
verifythis_fm2012_LRS.mlw. For recursive functions we impose
the full non-alias discipline.
2013-04-22 23:31:38 +02:00
Andrei Paskevich
9fd9469c53 whyml: drop read effects
Now that ghost writes are checked via e_syms.syms_pv,
there is no use for read effects anymore.
2013-04-07 17:59:24 +02:00
Andrei Paskevich
30c225b418 whyml: reimplement verification of the ghost writes
This fixes one bug and several deficiencies in the previous
implementation, which was based on read effects. One caveat
about the current version is that we treat all type variables
in a polymorphic type as visible (= non-ghost) even if they
only occur in the ghost fields. For example, the following
code is rejected:

  type strange 'a = { ghost contents : 'a }

  let test () =
    let x = { contents = ref 0 } in
    x.contents := 42

Even though the field [contents] is ghost and cannot be reached
from the real-world code, the type of x is [strange (ref int)]
and the region of the reference is considered to be visible.
Thus the last assignment is seen as an illicit ghost write.

On the other hand,

  type strange 'a = { ghost contents : ref 'a }

and

  type strange 'a = { ghost mutable contents : 'a }

permit ghost writes into [contents] without problem.
Ghost writes into ghost variables are also okay.
2013-04-07 17:05:16 +02:00
Andrei Paskevich
dce120fab6 whyml: keep track of pvsymbols and psymbols in expressions
this commit changes the way of tracking occurrences of regions
and type variables for the purposes of generalization, effect
filtering, and effect checks. It restricts the previous
implementation in two aspects:

- a psymbol p can be monomorphic (= non-generalizable) in an effect
  only if p depends (= is defined via) a pvsymbol whose type contains
  the affected region. See bench/programs/bad-typing/recfun.mlw
  for an example. This restriction is required for soundness.

- an argument of a psymbol cannot contain a region shared with
  another argument or an external pvsymbol. However, we do not
  require (so far) that the argument's type doesn't contain the same
  region twice and we allow the result type to contain known regions.
  This restriction is not necessary for soundness, and is introduced
  only to avoid some unintentional user errors and reduce the gap
  between the types that can be implemented in a "let" and the types
  that can be declared in a "val".
2013-04-06 18:33:04 +02:00