Repro
```floe
type User = {
firebaseUid: Option.Option.Aaa,
foo: Literally.Anything.You.Want<int, string>,
}
```
No error. Hovers as a valid type. Codegen accepts it.
Root cause
`crates/floe-core/src/checker/type_resolve.rs:230-234`:
```rust
} else if self.registering_types
|| self.env.lookup_type(name).is_some()
|| name.contains('.') // <-- the hole
{
Type::Named(name.to_string())
}
```
The `.contains('.')` was added to allow TS-namespace types like `JSX.Element` (which Floe doesn't fully model). It's a wide-open escape hatch — any dotted name is accepted with no validation.
The CST parser at `cst/types.rs:67-72` already accepts arbitrary `A.B.C.D` chains, and the lowerer at `lower/types.rs:213` joins them into a single `Type::Named("A.B.C.D")`. The resolver is the only place this could be caught and currently isn't.
What "correct" looks like
The resolver should validate that the dotted name resolves to something — most likely either:
- An imported namespace (e.g. `React.JSX.Element` after `import React from "react"`), checked via `env.lookup` of the first segment
- An ambient namespace declared in lib files
If neither, emit E002 `unknown type ``` like every other unresolved name.
Tests
Add tests in `checker/tests.rs` (or wherever type-resolution tests live):
- `type_with_unknown_dotted_name_errors` — `Foo.Bar` → expect E002
- `type_with_jsx_namespace_resolves` — keep `JSX.Element` working when JSX hint is present (or the namespace's first segment is a recognized identifier)
- Bug-fix test reproducing `Option.Option.Aaa` → expect E002
Priority
P1. This is a silent correctness hole — typos produce no diagnostic.
Repro
```floe
type User = {
firebaseUid: Option.Option.Aaa,
foo: Literally.Anything.You.Want<int, string>,
}
```
No error. Hovers as a valid type. Codegen accepts it.
Root cause
`crates/floe-core/src/checker/type_resolve.rs:230-234`:
```rust
} else if self.registering_types
|| self.env.lookup_type(name).is_some()
|| name.contains('.') // <-- the hole
{
Type::Named(name.to_string())
}
```
The `.contains('.')` was added to allow TS-namespace types like `JSX.Element` (which Floe doesn't fully model). It's a wide-open escape hatch — any dotted name is accepted with no validation.
The CST parser at `cst/types.rs:67-72` already accepts arbitrary `A.B.C.D` chains, and the lowerer at `lower/types.rs:213` joins them into a single `Type::Named("A.B.C.D")`. The resolver is the only place this could be caught and currently isn't.
What "correct" looks like
The resolver should validate that the dotted name resolves to something — most likely either:
If neither, emit E002 `unknown type ``` like every other unresolved name.
Tests
Add tests in `checker/tests.rs` (or wherever type-resolution tests live):
Priority
P1. This is a silent correctness hole — typos produce no diagnostic.