docs← Back to article

Markdown for LLMs

LDC-E2115 — An undeclared name in an interval bound

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# LDC-E2115 — An undeclared name in an interval bound

## What it means

An interval bound is a value position: it must be a literal, a bound
rule variable, a declared constant, an enum member, or a parameter —
never a bare unknown name. A name with no binding in any of those
places is a free variable, and the compiler rejects it at the bound.

Binding the name with a rule variable plus a premise that yields it,
or replacing it with a literal floor date for a deliberately open
window, resolves it. Either way the bound ends up a genuine value.

## Example

```law
language "law.core" version "0.2";
package demo.diagnostics version "0.1.0";
namespace "urn:law:demo:diagnostics";

entity Person;
relation active(p: Person) kind empirical;
relation held(p: Person) kind institutional;
rule R strict {
  for p: Person;
  when active(p);
  then duty D {
    bearer p;
    goal maintenance {
      condition held(p);
      window [moment, infinity);
    }
  };
}
```

## Fix

```law
language "law.core" version "0.2";
package demo.diagnostics version "0.1.0";
namespace "urn:law:demo:diagnostics";

entity Person;
relation active(p: Person) kind empirical;
relation started(p: Person, since: Date) kind empirical;
relation held(p: Person) kind institutional;
rule R strict {
  for p: Person;
  for moment: Date;
  when active(p) and started(p, moment);
  then duty D {
    bearer p;
    goal maintenance {
      condition held(p);
      window [moment, infinity);
    }
  };
}
```

## Engine message

The engine reports this in its own wording:

```text
example.law:15:15: error LDC-E2115: name "moment" in a §20 interval bound is not declared: it is bound by neither a rule `for`, nor `let`, and is declared by neither `const` §54, nor a §38 enum member, nor an A3 §A3.2 parameter — it is a free variable (§188 unresolved name). An interval bound is a VALUE of an ordered scale (a position §135 window has `Date` or `Instant`), not a §52 identity, so a domain constant does not read the name here. Two legal resolutions. If the intended date is FROM THE CASE — bind the name with a rule body: `for moment: Date;` plus a premise yielding it. If the window is deliberately without an inscribed date — the corpus floor `[@0001-01-01, infinity)`, the technical floor «раньше всякой даты, которую пакет может назвать». The `[-infinity, infinity)` form does NOT work here: `check` accepts it, but lowering rejects it with LDC-E1305 — `lower_term` has an `infinity` branch and no `-infinity` branch
```

## Related

- [Time](/constructs/time/) — what interval bounds may hold.
- [Deadline calendar](/constructs/deadline-calendar/) — how position windows are dated.