Skip to content

Add optional tz parameter to datetime_now and reject extra positional args#725

Merged
tautschnig merged 17 commits intomainfrom
tautschnig/extra-positional-args
Apr 6, 2026
Merged

Add optional tz parameter to datetime_now and reject extra positional args#725
tautschnig merged 17 commits intomainfrom
tautschnig/extra-positional-args

Conversation

@tautschnig
Copy link
Copy Markdown
Contributor

@tautschnig tautschnig commented Apr 1, 2026

Problem

datetime.now(timezone.utc) caused an arity mismatch because the prelude's datetime_now declared 0 parameters while the Python call passed 1 argument. This surfaced as a "call [end_time] := datetime_now($hole_12($heap_in))" error in check_storage_costs.

Approach

Rather than silently dropping extra positional arguments (which could mask real bugs), we model the missing optional parameter in the prelude and add an arity check that rejects extra positional arguments for all functions.

Prelude changes:

  • Add tz: Any parameter to datetime_now in the Laurel prelude
  • Add tz: AnyOrNone parameter to datetime_now in the Core prelude and FunctionSignatures

Arity checking:
combinePositionalAndKeywordArgs now raises a user error when a call passes more positional arguments than the function signature declares, for both user-defined and prelude functions alike

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

When a Python function call passes more positional arguments than the
Laurel prelude signature declares (e.g., datetime.now(timezone.utc)
where datetime_now has 0 params), truncate the argument list to the
signature length instead of passing the extra args through.

This fixes an arity mismatch that caused check_storage_costs to fail
with "call [end_time] := datetime_now($hole_12($heap_in))" — the
timezone.utc argument was being passed to a 0-parameter procedure.

The fix is general: any prelude function that models fewer parameters
than the Python signature will silently drop the unmodeled trailing
arguments, which is correct for verification since those parameters
do not affect the modeled behavior.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig self-assigned this Apr 1, 2026
@tautschnig tautschnig requested review from a team and Copilot April 1, 2026 09:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts the Python→Laurel translator to avoid arity mismatches when Python call sites pass more positional arguments than a modeled/prelude Laurel signature declares (e.g., datetime.now(timezone.utc) when the model declares 0 params), and adds a regression test for that scenario.

Changes:

  • Truncate positional arguments to the modeled signature length during argument combination in PythonToLaurel.
  • Add a new Python pipeline test covering datetime.now(timezone.utc) and basic datetime arithmetic.
  • Register the new test in the Python CBMC expected-outcomes list as PASS.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
Strata/Languages/Python/PythonToLaurel.lean Truncates extra positional args during call argument processing to prevent Laurel arity mismatch.
StrataTest/Languages/Python/tests/test_datetime_now_tz.py Adds regression test exercising datetime.now(timezone.utc) and timedelta arithmetic.
StrataTest/Languages/Python/tests/cbmc_expected.txt Marks the new test as expected PASS in the CBMC pipeline runner.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Strata/Languages/Python/PythonToLaurel.lean Outdated
tautschnig and others added 3 commits April 1, 2026 10:01
The previous truncation of extra positional arguments applied to all
calls with a known funcDecl, including user-defined functions. This
could silently hide real Python arity errors, making verification
unsound.

Now only prelude/external functions (where we intentionally under-model
parameters) have extra trailing args silently dropped. User-defined
functions raise an error when called with too many positional arguments,
matching Python's TypeError semantics.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Exercise the datetime.now(timezone.utc) scenario through the full
Python → Laurel → Core → SMT pipeline in VerifyPythonTest, so the
fix is tested by 'lake test' and not only via the CBMC pipeline.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig enabled auto-merge April 1, 2026 10:39
@tautschnig tautschnig removed their assignment Apr 1, 2026
Copy link
Copy Markdown
Contributor

@olivier-aws olivier-aws left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised this is sound in general. Another solution would be to modify our Prelude functions to have the optional argument, and add "holes" when one argument is missing. Any reason why we shouldn't use this approach?

Comment thread Strata/Languages/Python/PythonToLaurel.lean Outdated
tautschnig and others added 5 commits April 2, 2026 18:22
…tions

Verify that calling a user-defined function with extra positional
arguments produces the expected error through the full pipeline,
exercised by 'lake test'.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
…al args

Instead of silently truncating extra positional arguments for prelude
functions, add the missing optional parameter to the prelude signature.
This is cleaner: the prelude accurately models Python's datetime.now(tz)
signature, and extra positional args are now an error for all functions
(user-defined and prelude alike).

Changes:
- Add tz:Any parameter to datetime_now in Laurel prelude
- Add tz:AnyOrNone parameter to datetime_now in Core prelude
- Add tz:AnyOrNone to datetime_now in FunctionSignatures
- Remove arg-truncation and userFunctions distinction from
  combinePositionalAndKeywordArgs; extra args are always an error
- Update PreludeVerifyTest assertion IDs (prelude size changed)

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig
Copy link
Copy Markdown
Contributor Author

I'm surprised this is sound in general. Another solution would be to modify our Prelude functions to have the optional argument, and add "holes" when one argument is missing. Any reason why we shouldn't use this approach?

That's a great point that we are using a different approach elsewhere. I have now adopted that approach here as well.

tautschnig and others added 2 commits April 3, 2026 19:17
timezone.utc is not modeled in the prelude, causing resolution errors
in CI where strata.gen is available. Use None to test the optional tz
parameter instead.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig changed the title Drop extra positional args beyond function signature in Python-to-Laurel Add optional tz parameter to datetime_now and reject extra positional args Apr 3, 2026
…tional-args

Resolve PreludeVerifyTest assertion ID conflict: adjust IDs for both
upstream changes and the tz parameter addition.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Comment thread StrataTest/Languages/Python/VerifyPythonTest.lean Outdated
Comment thread Strata/Languages/Python/PythonToLaurel.lean
tautschnig and others added 3 commits April 3, 2026 20:54
Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
The isVarKwargs path (** dict expansion) bypassed
combinePositionalAndKeywordArgs entirely, so extra positional args
before the **dict were not caught. Add the same arity check.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Exercises the arity check in the isVarKwargs call path.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
MikaelMayer
MikaelMayer previously approved these changes Apr 3, 2026
…tional-args

# Conflicts:
#	StrataTest/Languages/Python/VerifyPythonTest.lean
#	StrataTest/Languages/Python/tests/cbmc_expected.txt
…tional-args

# Conflicts:
#	StrataTest/Languages/Python/VerifyPythonTest.lean
#	StrataTest/Languages/Python/tests/cbmc_expected.txt
@tautschnig tautschnig added this pull request to the merge queue Apr 6, 2026
Merged via the queue into main with commit 5cd6ef4 Apr 6, 2026
15 checks passed
@tautschnig tautschnig deleted the tautschnig/extra-positional-args branch April 6, 2026 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants