-
Notifications
You must be signed in to change notification settings - Fork 256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add bounded polymorphism #5547
feat: Add bounded polymorphism #5547
Conversation
Fixes dafny-lang#5233 As a bonus, allow the optimization when there are no _compiled_ fields (previously, the optimization was disabled when _any_ fields were present).
# Conflicts: # Source/DafnyCore/Backends/JavaScript/JavaScriptCodeGenerator.cs # Source/IntegrationTests/TestFiles/LitTests/LitTest/git-issues/git-issue-5238.dfy # Source/IntegrationTests/TestFiles/LitTests/LitTest/git-issues/git-issue-5238.dfy.expect
# Conflicts: # Source/DafnyRuntime/DafnyRuntimeGo/dafny/dafnyFromDafny.go
Reporting some issues on behalf of @erniecohen:
Is there a missing constraint during type inference?
module Util {
function min(x:nat, y:nat):nat { if x < y then x else y }
function max(x:nat, y:nat):nat { if x < y then y else x }
}
trait Op<T> { function op(t:T):T }
trait BOp<S,T> { function op(s:S,t:T):T }
trait Dom<T(!new)> {
predicate has(t:T)
ghost predicate andPost(d:Dom<T>,r:Dom<T>) { forall t:T | has(t) && d.has(t) :: r.has(t) }
function and(d:Dom<T>):(r:Dom<T>) ensures andPost(d,r)
ghost predicate orPost(d:Dom<T>,r:Dom<T>) { forall t:T | has(t) || d.has(t) :: r.has(t) }
function or(d:Dom<T>):(r:Dom<T>) ensures andPost(d,r)
ghost static predicate topPost() { forall t:T :: top().has(t) }
static function top():Dom<T> ensures topPost()
}
newtype Reg = nat {
const v := this
const n := this as nat
function inc():Reg { v + 1 }
function plus(r:Reg):Reg { v + r.v }
}
datatype Ivl extends Dom<Reg> = Ivl(min:Reg,max:Reg) {
predicate has(t:Reg) { min <= t < max }
function and(d:Dom<Reg>):(r:Dom<Reg>) ensures andPost(d,r) && r is Ivl {
if (d is Ivl) then var d := d as Ivl;
var r := Ivl(Util.max(min.n,d.min.n) as Reg, Util.min(max.n,d.max.n) as Reg); r
else this
}
function or(d:Dom<Reg>):(r:Dom<Reg>) ensures orPost(d,r) {
if (d is Ivl) then var d := d as Ivl;
var r := Ivl(Util.min(min.n,d.min.n) as Reg, Util.max(max.n,d.max.n) as Reg); r
else top() // triggers internal error on verification
}
} returns
|
Thanks for the feedback and the example code. Regarding point 1: The only way I'm able to reproduce getting an "not assignable" type-checking error is if I use the old type system. To use However, even with |
# Conflicts: # Source/IntegrationTests/TestFiles/LitTests/LitTest/dafny4/Bug140.dfy.rs.check
Regarding point 2:
|
Regarding point 3: Thanks. Evidently, this was a problem with |
Thanks! Lastly, @ecohen is reporting that the following code...
...produces
Looks like the wrong token was assigned for the related location? |
So to review:
This all looks good to me, esp. since bounded polymorphism is (or should be, at least) a conservative extension to Dafny's type theory. |
# Conflicts: # Source/DafnyCore/Verifier/BoogieGenerator.ExpressionTranslator.cs
Description
This PR adds bounded polymorphism to the Dafny language. This feature allows any formal type parameter to be declared with a suffix of any number of
clauses, where
Type
is any trait or subset type thereof. At call sites, the actual type arguments are checked to be subtypes of the listed type bounds. Where the formal type parameters are in scope, an expression whose type is the type parameter can be converted to a supertype of any of the type bounds by an explicit type conversion (as
). In some cases, the type conversion is inferred automatically and can then be omitted from the program text.The feature requires
--type-system-refresh
for full functionality.Closes #5211
Example
For
test.dfy
being the programwe get:
Bonus
The PR also
A==B
which turns into bothA :> B
andB >: A
)By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.