I'm not sure if this is because of changes to glue generation in the
last few days while I've been working on other things, or if it's a
side effect of the improvements I made to typechecking for anonymous
objects, or something else, but I guess I'll take it!
Closes issue #543.
Programs with constrained types now parse and typecheck, but
typestate doesn't check them specially, so the one relevant test
case so far is XFAILed.
Also rewrote all of the constraint-related data structures in the
process (again), for some reason. I got rid of a superfluous
data structure in the context that was mapping front-end constraints
to resolved constraints, instead handling constraints in the same
way in which everything else gets resolved.
This reverts commit 8c94d8fd54.
There's no mechanism to actually return the value from main, so all this does
is allow main -> int to compile. Per #688, the program returns non-zero on
failure, so it's not obvious that this change is appropriate at this time.
ret is similar to fail: if not followed by an expression, it
should be parsed as a ret without an argument. The old version would
fail if ret was followed by a close paren (for example). Fixed it.
Closes#676.
Capturing a type argument in the enclosing scope should be an error --
this commit implements that check in resolve, avoiding a potential
assertion failure in trans.
Closes#648.
Typestate was failing to check some code because if it saw an item,
it would quit immediately. This was to avoid checking nested items
in the same context as the lexically enclosing item, but it was
having the wrong effect: not checking the code after the item at all.
Fixed by switching to visit and skipping over items in a proper
nested fashion. Closes#668.
A check in trans didn't have a corresponding check in typeck, causing
some programs (to wit, compile-fail/chan-parameterized-args.rs - part of this
commit) to fail with an assertion failure in trans instead of a type error.
Fixed it. In short, arguments that are future thunk arguments (any spawn
arguments, and _ arguments in bind) need to either not contain type params
or type vars, or be by-reference.
Closes#665.
Currently it's only sequential, but it can do word frequency
counting. In an ideal world it would all be polymorphic, but that
pushes the limits of our type system right now. We can generalize it
later.
You can now say
expr_move(?dst, ?src) | expr_assign(?dst, ?src) { ... }
to match both expr_move and expr_assign. The names, types, and number
of bound names have to match in all the patterns.
Closes#449.
trans::trans_lval will now autobind if the given expression was the
name of a generic functions. Those callees (trans_call and trans_bind)
that are interested in the generics information call trans_lval_gen
now.
Previously, we were creating both a normal vtable entry and a
forwarding function for overriding methods, when they should have just
gotten a vtable entry. This patch fixes that.
This adds support for dropping cleanups for temporary values when they
are moved somewhere else. It then adds wraps most copy operations
(return, put in data structure, box, etc) in a way that will fall back
to a move when it is safe.
This saves a lot of taking/dropping, shaving over a megabyte off the
stage2/rustc binary size.
In some cases, most notably function returns, we could detect that the
returned value is a local variable, and can thus be safely moved even
though it is not a temporary. This will require putting some more
information in lvals.
I did not yet handle function arguments, since the logic for passing
them looked too convoluted to touch. I'll probably try that in the
near future, since it's bound to be a big win.
This will link to std and compile with the --test flag. Eventually the
run-pass/lib* tests will move here.
We could also put the std tests directly into the library and compile both a
library version and a test version, but I think this way will make for faster
builds.
Issue #428
(The old syntax is still supported as well, for now.)
It is now possible to leave out the parens around if, while, and
do/while conditions, and around alt expressions. Cases in an alt block
can now leave off the case keyword and parens around the pattern.
After the next snapshot, we can start migrating our code to use the
new alt syntax, probably with a pretty-printer pass. The paren-free
syntax will remain optional (you may always parenthesize expressions),
but the old case syntax will no longer be supported in the future.
If a closure inside a case alternative (for example, a for each loop)
referenced a pattern-bound variable, this would cause an assertion
failure in trans. Changed trans::collect_upvars to handle pattern-bound
vars correctly.
Incidentally, eliminated all direct uses of option::get in trans.
An expression like:
foo(1, fail, 2)
was failing to parse, because the parser was interpreting the comma
as the start of an expression that was an argument to fail, rather
than recognizing that the fail here has no arguments
Fixed this by using can_begin_expr to determine whether the next
token after a fail token suggests that this is a nullary fail or a
unary fail.
In addition, when translating calls, check before translating each
argument that the block still isn't terminated. This has the effect
that if an argument list includes fail, the back-end won't keep trying
to generate code for successive arguments and trip the !*terminated
assertion.
The code for translating a fail (for example) would call
Unreachable(), which terminates the block; if a fail appeared as an
argument, this would cause an LLVM assertion failure. Changed
trans_call to handle this situation correctly.
This is important since we are going to be making functions noncopyable
soon, which means we'll be seeing a lot of boxed functions.
(*f)(...) is really just too heavyweight.
Doing the autodereferencing was a very little bit tricky since
trans_call works with an *lval* of the function whereas existing
autoderef code was not for lvals.
Implement "claim" (issue #14), which is a version of "check" that
doesn't really do the check at runtime. It's an unsafe feature.
The new flag --check-claims turns claims into checks automatically --
but it's off by default, so by default, the assertion in a claim
doesn't execute at runtime.
The meta items within a crate's link attribute are used in linkage:
#[link(name = "std",
vers = "1.0",
custom = "whatever")];
Name and vers are treated specially, and everything else is hashed together
into the crate meta hash.
Issue #487
Resources are now defined like...
resource fd(int n) { close(n); }
Calling fd with an int will then produce a non-copyable value
that, when dropped, will call close on the given int.
Wrote some small test cases that use while loops and moves, to
make sure the poststate for the loop body gets propagated into the
new prestate and deinitialization gets reflected.
Along with that, rewrite the code for intersecting states. I still
find it dodgy, but I guess I'll continue trying to add more tests.
Also, I'll probably feel better about it once I start formalizing
the algorithm.
Includes assignment operations. Add regression tests for lots of less useful,
less used or unexpected combinations, as well as a selection of compile-fail
tests. Closes#500 (again!)
Modified typestate to throw away any constraints mentioning a
variable on the LHS of an assignment, recv, assign_op, or on
either side of a swap.
Some code cleanup as well.
If you use a function expecting an alias argument in a context that
expects a function expecting a value argument, or vice versa, the
previous error message complained that the number of arguments was
wrong. Fixed the error message to be accurate.
typestate now drops constraints correctly in the post-state of
a move expression or a declaration whose op is a move. It doesn't
yet drop constraints mentioning variables that get updated.
To do this, I had to change typestate to use trit-vectors instead
of bit-vectors, because for every constraint, there are three
possible values: known-to-be-false (e.g. after x <- y, init(y) is
known-to-be-false), known-to-be-true, and unknown. Before, we
conflated known-to-be-false with unknown. But move requires them
to be treated differently. Consider:
(program a)
(a1) x = 1;
(a2) y <- x;
(a3) log x;
(program b)
(b1) x = 1;
(b2) y <- z;
(b3) log x;
With only two values, the postcondition of statement a2 for
constraint init(x) is the same as that of b2: 0. But in (a2)'s
postcondition, init(x) *must* be false, but in (b2)'s condition,
it's just whatever it was in the postcondition of the preceding statement.
This code was causing a bounds check failure:
fn hd[U](&vec[U] v) -> U {
fn hd1(&vec[U] w) -> U {
ret w.(0);
}
ret hd1(v);
}
because in hd1, U was being treated as if it referred to a type
parameter of hd1, rather than referring to the lexically enclosing binding
for U that's part of hd.
I'm actually not sure whether this is a legit program or not. But I wanted
to get rid of the bounds check error, so I assumed that program shouldn't
compile and made it a proper error message.
This involved, in part, changing the ast::def type so that a def_fn
has a "purity" field. This lets the typechecker determine whether
functions defined in other crates are pure.
It also required updating some error messages in tests. As a test
for cross-crate constrained functions, I added a safe_slice function
to std::str (slice(), with one of the asserts replaced with a
function precondition) and some test cases (various versions of
fn-constraint.rs) that call it. Also, I changed "fn" to "pred" for
some of the boolean functions in std::uint.
I noticed that typestate was being lazier than it should be,
because it was only checking typestate for statements and
top-level expression (that is, the expression in a stmt_expr, but
not any subexpressions). So I rewrote the checks in tstate/ck.rs
to use walk, which exposed a few bugs in typestate that I fixed.
Also added some more test cases for if-check.
I don't currently know how to deal with syntax extensions that appear betweeen
an attribute and an item, so this test captures the error that occurs.
Issue #487
I added a "resolved" version of the ast::constr type -- ty::constr_def
-- that has a def_id field instead of an ann_field. This is more
consistent with other types and eliminates some checking.
Incidentally, I removed the def_map argument to the top-level function
in middle::alias, since the ty::ctxt already has a def_map field.
This is a somewhat odd place to put these checks, but the data tracked
by that pass, and the available functions, make it trivial to do such
a check there.
In code like "auto foo = fail", a type gets inferred for foo
depending on how it's used. However, fail still has type _|_ and
still should be treated that way: particularly, its value shouldn't
be copied. Fixed trans to reflect that.
Before, all aliases were implicitly mutable, and writing
&mutable was the same as writing &. Now, the two are
distinguished, and assignments to regular aliases are
no longer allowed.
Improve error message in the case where a use of a polymorphic tag has
insufficient type arguments given. Before, the typechecker was
just crashing with a bounds check error.