Am Freitag, dem 14.03.2025 um 10:11 -0700 schrieb David Tarditi:
> Hi Martin,
> 
> The C design of VLAs misunderstood dependent typing.

They probably did not care about theory, but the design is
not inconsistent with theory.
> 
> For a program to  be validly typed when there are dependent types,
> you need to be able to write down the types of any values and
> variables at program points where they are in use.   This is
> problematic when there are assignments to variables involved
> in dependent types.  

In C, the types depend on the values of expressions evaluated
at certain points in time.

You could rewrite 

int len = 1;
char buf[len];

as 

int len = 1;
const int hidden_state = len;
char buf[hidden_state];


Deputy did this differently.

Martin

> The values that the dependent types used
> are “gone”, so the program is no longer validly typed using
> the source-level types.  The Deputy system handled this by introducing 
> temporary variables to hold values used in dependent types.  For C, that 
> corresponds to introducing hidden state, which is not done anywhere else in 
> the language.  It also doesn’t work when you have global variables involved 
> in dependent types, as you potentially need an unlimited number of copies.
> 
> In your example:
> 
> > int len = 1;
> > char buf[len]; // len is evaluated and the array has size 10
> > len = 10; // has no impact on the type of 'buf'
> 
> What is the dependent type of buf after you’ve assigned to len?  The compiler 
> can introduce a temporary, but the type is “gone” at the source level.   
> Claiming that buf has the type of “array of length len” is not correct:
> 
> > int len = 1;
> > char buf[len]; // len is evaluated and the array has size 10
> > len = 10; // has no impact on the type of ‘buf’.   *** The dependent type 
> > of buf in the source code (char [len]) is now wrong.***
>    
> There’s a misunderstanding of how type systems work.   There’s the static 
> typing of a program - what is declared in the source code and “type checked” 
> at compile time.  Then there is soundness: ensure that the program respects 
> the types at runtime.  A proof of soundness takes the static type checking 
> rules and combines them with the runtime semantics and shows that programs 
> “never go wrong”, i.e. access values at the wrong type.  To have soundness, 
> Deputy had to take the C source level programs and translate them to 
> dependently-typed programs with extra state and extra runtime checks.  It’s a 
> perfectly valid approach, but then one needs to understand that the 
> source-level types no longer correspond to the dependent types used in type 
> checking.   Deputy specifically restricted the dependent types of values 
> stored on the heap: a value with a dependent type had to be stored in a 
> member and the dependent type was specified in terms of other members in the 
> same object.
> 
> As for the rules around scoping, we only need to rules that differ because 
> the original design was flawed and missed common use cases.
> 
> David
> 
> 
> > On Mar 13, 2025, at 11:16 PM, Martin Uecker <uec...@tugraz.at> wrote:
> > 
> > 
> > Hi David,
> > 
> > Am Donnerstag, dem 13.03.2025 um 19:23 -0700 schrieb David Tarditi:
> > > 
> > > I skip your initiial part.  I think this was all discussed before
> > 
> > (also in WG14) and I still come to different conclusions.  Just
> > two comments:
> > 
> > ...
> > > 
> > > The VLA semantics are also problematic. User can side-effect
> > > variables used in a VLA declaration after the declaration, while
> > > the declaration is in scope.  It is not obvious how to implement
> > > bounds checking, because the bounds could be gone (invalid).
> > >  It is a design flaw that the declared bounds can become invalid
> > > while the declaration is in scope.
> > 
> > Variably modified types do not work like this C.  The size
> > expression is evaluated at the point of declaration.  If there
> > is a variable in it, it is never accessed later and changing it
> > does not affect the type anymore.
> > 
> > int len = 1;
> > char buf[len]; // len is evaluated and the array has size 10
> > len = 10; // has no impact on the type of 'buf'
> > 
> > In fact, one can also have more complicated expressions.
> > 
> > int len = 11;
> > char buf[len + 1]; // has size 11.
> > 
> > and those are also not re-evaluated later.
> > 
> > 
> > This is exactly how it works in other dependently types languages,
> > so I do not think one can make the case that C got these semantics 
> > wrong.
> > 
> > Bounds checking also works already today: https://godbolt.org/z/5P8so1reb
> > 
> > (although there are still missing pieces which would be important
> > but which compilers currently do not implement.  But for GCC I have
> > a local branch which adds most of those.)
> > 
> > 
> > > 
> > > Finally, when you get to nested pointers, the syntax (and typing)
> > > for VLAs becomes confusing. This isn’t VLAs fault. It is there in the
> > > original C design.  
> > 
> > Your comments about C's syntax certainly have some truth to them,
> > but I personally - as a C programmer and teacher - would find 
> > it much worse to add new inconsistent rules to the language
> > just to be able to write something in a more succinct way
> > in some specific cases.  A programmer would still have to
> > learn and nderstand the general C syntax and all the existing
> > rules name lookup rules.
> > 
> > I do not think adding new inconsistent rules would make the
> > language simpler and clearer in general, even it it may look
> > like this when only considering a narrow use case.
> > 
> > 
> > Martin
> > 
> > 
> 

Reply via email to