Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
a649815
Add DynType projector
7h3kk1d Aug 3, 2025
1a40403
Add shortcut for Dynamic Type with alt+d hotkey
7h3kk1d Aug 5, 2025
0216699
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 6, 2025
65d1851
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 12, 2025
3d15477
Add Typ.consistent_join for the dyntype projector
7h3kk1d Aug 12, 2025
36d615c
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 20, 2025
85c2b4d
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 20, 2025
7909c30
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 21, 2025
88e8d76
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 26, 2025
1e5f9ca
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 28, 2025
db3a420
Merge branch 'dev' into dyntype-proj
7h3kk1d Aug 29, 2025
3961c95
Merge branch 'dev' into dyntype-proj
7h3kk1d Sep 3, 2025
853e029
Merge remote-tracking branch 'origin/dev' into dyntype-proj
7h3kk1d Sep 12, 2025
be3aa4d
Merge branch 'dev' into dyntype-proj
7h3kk1d Sep 18, 2025
72e8101
Merge remote-tracking branch 'origin/dev' into dyntype-proj
7h3kk1d Sep 24, 2025
a82b64c
temp
7h3kk1d Sep 24, 2025
b7c2577
Merge branch '1966-no-probed-values' into dyntype-type-proj
7h3kk1d Sep 24, 2025
0dd5810
Type probe on types
7h3kk1d Sep 25, 2025
173a5f4
Remove projector parsing tests
7h3kk1d Sep 25, 2025
6e4de9c
Add type handling for Typ in probe
7h3kk1d Sep 25, 2025
353b0e2
Implement dynamic type handling in type projector
7h3kk1d Sep 29, 2025
4c6658c
Crude styling of dynamic types in type projector
7h3kk1d Sep 29, 2025
4d386e8
Mark unused patterns
7h3kk1d Sep 29, 2025
d8efcfd
Remove dynamic type projector
7h3kk1d Sep 29, 2025
9a8e9f6
Types can show their types
7h3kk1d Sep 29, 2025
9ab6e0c
Inefficient adding of dynamic types to cursor inspector
7h3kk1d Oct 2, 2025
ff67c1f
Merge remote-tracking branch 'origin/dev' into dyntype-proj
7h3kk1d Oct 6, 2025
2ea4c26
Merge remote-tracking branch 'origin/dyntype-proj' into dyntype-type-…
7h3kk1d Oct 6, 2025
930e42f
Fix transition_multiple call to include update_probe parameter
7h3kk1d Oct 10, 2025
e1539bc
Merge branch 'dev' into dyntype-proj
7h3kk1d Oct 17, 2025
75666d3
Merge remote-tracking branch 'origin/dev' into dyntype-type-proj
7h3kk1d Oct 17, 2025
2585f43
Address merge errors
7h3kk1d Oct 17, 2025
bbf9abf
Merge remote-tracking branch 'origin/dyntype-proj' into dyntype-type-…
7h3kk1d Oct 17, 2025
10a2850
Merge branch 'dev' into dyntype-proj
7h3kk1d Oct 21, 2025
bd8fd25
Merge branch 'dyntype-proj' into dyntype-type-proj
7h3kk1d Oct 21, 2025
d1e8ce3
Merge branch 'dev' into dyntype-proj
7h3kk1d Oct 23, 2025
c9d7cf2
Merge branch 'dev' into dyntype-proj
7h3kk1d Oct 30, 2025
b0b4285
Merge remote-tracking branch 'origin/dyntype-proj' into dyntype-type-…
7h3kk1d Oct 30, 2025
b08f6a1
Fix probe collection for types
7h3kk1d Nov 4, 2025
2e5350a
add WriterMonad
7h3kk1d Nov 4, 2025
941e249
Use writer monad in ascriptions transition
7h3kk1d Nov 4, 2025
d6c64e2
Only probe unknown expressions when dynamic_feedback is enabled
7h3kk1d Oct 16, 2025
e4a0034
Fix ascriptions transition hallucination by ai
7h3kk1d Nov 4, 2025
06902fc
Fix if statement ascription transition
7h3kk1d Nov 4, 2025
e08aa02
Remove debug print statement from ascriptions transition
7h3kk1d Nov 4, 2025
3c3eac3
Merge branch 'dev' into dyntype-proj
7h3kk1d Nov 10, 2025
bf5a0d2
Merge branch 'dyntype-proj' into dyntype-type-proj
7h3kk1d Nov 10, 2025
a3cf6dc
Remove debug print statement for dynamic ID check
7h3kk1d Nov 10, 2025
2dbf027
Stop doing ascription transition in labeled tuple entries unboxing
7h3kk1d Nov 10, 2025
df49af0
Revert Id show to full id
7h3kk1d Nov 10, 2025
8e2a70a
Revert IdTagged pp changes
7h3kk1d Nov 10, 2025
5b1c7d3
add Probe to Typ.cls
7h3kk1d Nov 10, 2025
5ff56a7
Remove comments
7h3kk1d Nov 10, 2025
7b34b49
Add documentation for probe_unknowns parameter in Elaborator
7h3kk1d Nov 10, 2025
c76a164
Disable type projector on types for now
7h3kk1d Nov 10, 2025
995b9af
Revert codeeditable and cursorinspector changes
7h3kk1d Nov 10, 2025
4ec5c6d
Fix syn display for typ proj
7h3kk1d Nov 10, 2025
30f5593
feat(typeproj): enhance toggle display logic for expected types
7h3kk1d Nov 10, 2025
698e981
Fix typ diff styling
7h3kk1d Nov 19, 2025
64d6aa6
Improve pad ids documentation
7h3kk1d Nov 19, 2025
c270918
add test for no difference between identical types
7h3kk1d Nov 19, 2025
e4e1a7c
feat(projectors): add Typ handling to type projector
7h3kk1d Nov 19, 2025
f1eea2e
refactor(elaborate): remove unused fix_typ_ids function and simplify …
7h3kk1d Nov 19, 2025
222abd1
fix(diff): clarify assumption about distinct initial ids in diff func…
7h3kk1d Nov 19, 2025
d5a0291
Fix typ.diff for recursive types and forall types
7h3kk1d Nov 19, 2025
9b1af01
Remove duplicate test
7h3kk1d Nov 19, 2025
ff5523b
Probes and dyntype probes on types (#1969)
7h3kk1d Nov 19, 2025
0f20fd1
refactor(diff): simplify testable function usage in diff tests
7h3kk1d Nov 19, 2025
c7d0ce2
refactor(Typ): abandon consistent_join
7h3kk1d Nov 19, 2025
52d2a2c
refactor(ProjectorCore): simplify name lookup using StringMap
7h3kk1d Nov 19, 2025
15a8df2
refactor(Test_Typ): remove redundant testable_typ variable
7h3kk1d Nov 19, 2025
c2b73ee
Fix assertion description
7h3kk1d Nov 20, 2025
1d1ff55
Fix typeproj dynamic type styling
7h3kk1d Nov 20, 2025
a324d73
Merge remote-tracking branch 'origin/dev' into dyntype-proj
7h3kk1d Nov 26, 2025
7e12fdd
Merge remote-tracking branch 'origin/dev' into dyntype-proj
7h3kk1d Nov 26, 2025
5c85788
Merge remote-tracking branch 'origin/dev' into dyntype-proj
7h3kk1d Feb 2, 2026
e4b95b2
More fixes
7h3kk1d Feb 2, 2026
10c26b3
Fix compilation
7h3kk1d Feb 3, 2026
79cf327
progress
7h3kk1d Feb 3, 2026
c733274
Add type probe recording for ascriptions and update test description
7h3kk1d Feb 3, 2026
aa26613
Record type samples during ascription transitions
7h3kk1d Feb 3, 2026
f6d3975
Fix type projector mode switching Failure(nth) exception
github-actions[bot] Feb 3, 2026
7f821c9
Use refractor id instead of projector in set model
7h3kk1d Feb 3, 2026
d8b16b2
Revert unnecessary changes
7h3kk1d Feb 3, 2026
4e6c1ae
Add type probe tests
7h3kk1d Feb 3, 2026
ee65e54
Preserve Parens ID during normalization for accurate type probes
7h3kk1d Feb 3, 2026
94ab61a
Type probe fixes
7h3kk1d Feb 3, 2026
14c1ed0
Merge branch 'dev' into dyntype-proj
7h3kk1d Feb 3, 2026
5c4fcb2
Rip out probes on types
7h3kk1d Feb 4, 2026
5d94433
Remove probe_unknowns from elaborator
7h3kk1d Feb 4, 2026
9ab851d
Revert extraneous changes
7h3kk1d Feb 4, 2026
457534b
Remove WriterMonad module
7h3kk1d Feb 4, 2026
e50c2c5
Update probes doc buffer to have a from_lvs example for dynamic type …
7h3kk1d Feb 4, 2026
c37c8e0
Merge remote-tracking branch 'origin/dev' into dyntype-proj
7h3kk1d Feb 6, 2026
23e38c3
Update context menu labels for type probe actions
7h3kk1d Feb 10, 2026
2620112
Merge branch 'dev' into dyntype-proj
7h3kk1d Feb 10, 2026
4ae0e2c
Add hover tooltip for type probe mode
7h3kk1d Feb 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/haz3lcore/pretty/ExpToSegment.re
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ let external_precedence_typ = (tp: Typ.t) =>
| Unknown(Internal)
| Unknown(SynSwitch)
| Unknown(Hole(EmptyHole))
| Unknown(Inconsistent)
| Var(_)
| Atom(_)
| Label(_)
Expand Down Expand Up @@ -467,6 +468,7 @@ and parenthesize_typ =
| Var(_)
| Unknown(Hole(Invalid(_)))
| Unknown(Internal)
| Unknown(Inconsistent)
| Unknown(SynSwitch)
| Unknown(Hole(EmptyHole))
| Atom(_) => typ
Expand Down Expand Up @@ -1239,6 +1241,7 @@ and typ_to_pretty = (~settings: Settings.t, typ: Typ.t): pretty => {
| Unknown(Hole(Invalid(s))) =>
text_to_pretty(typ |> Typ.rep_id, Sort.Typ, s)
| Unknown(Internal)
| Unknown(Inconsistent)
| Unknown(SynSwitch)
| Unknown(Hole(EmptyHole)) =>
if (settings.show_unknown_as_hole) {
Expand Down
7 changes: 6 additions & 1 deletion src/haz3lcore/projectors/ProjectorCore.re
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Kind = {
type t =
| Fold
| Info
| DynType
| Probe
| Checkbox
| Slider
Expand All @@ -37,7 +38,8 @@ module Kind = {
Livelit,
];

let projectors: list(t) = livelit_projectors @ [Fold, Info, Probe];
let projectors: list(t) =
livelit_projectors @ [Fold, Info, DynType, Probe];

/* A friendly name for each projector. This is used
* both for identifying a projector in the CSS and for
Expand All @@ -46,6 +48,7 @@ module Kind = {
switch (p) {
| Fold => "fold"
| Info => "type"
| DynType => "dyntype"
| Probe => "probe"
| Checkbox => "check"
| Slider => "slider"
Expand All @@ -59,9 +62,11 @@ module Kind = {
* name function in order to be able to select the
* projector in the projector panel menu */
let of_name = (p: string): t =>
// TODO Use a map built from above
switch (p) {
| "fold" => Fold
| "type" => Info
| "dyntype" => DynType
| "probe" => Probe
| "check" => Checkbox
| "slider" => Slider
Expand Down
1 change: 1 addition & 0 deletions src/haz3lcore/projectors/ProjectorInit.re
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ let to_module = (kind: ProjectorCore.Kind.t): (module Cooked) =>
switch (kind) {
| Fold => (module Cook(FoldProj.M))
| Info => (module Cook(TypeProj.M))
| DynType => (module Cook(DynTypeProj.M))
| Probe => (module Cook(ProbeProj.M))
| Slider => (module Cook(SliderProj.M))
| SliderF => (module Cook(SliderFProj.M))
Expand Down
114 changes: 114 additions & 0 deletions src/haz3lcore/projectors/implementations/DynTypeProj.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
open Virtual_dom.Vdom;
open Node;
open ProjectorBase;
open Language;

let self_ty = (info: option(Info.t)): option(Typ.t) =>
switch (info) {
| Some(InfoExp({self, _})) => Self.typ_of_exp(self)
| Some(InfoPat({self, _})) => Self.typ_of_pat(self)
| _ => None
};
module M: Projector = {
[@deriving (show({with_path: false}), sexp, yojson)]
type model =
| Expected
| Self;

[@deriving (show({with_path: false}), sexp, yojson)]
type action =
| ToggleDisplay;

let init = (any: Term.Any.t): option(model) => {
switch (any) {
| Exp(_)
| Pat(_) => Some(Expected)
| Any () => Some(Expected) /* Grout don't have sorts rn */
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

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

Grammar error in comment: "Grout don't have sorts" should be "Grouts don't have sorts" (plural subject requires plural verb form or singular "Grout doesn't have").

Suggested change
| Any () => Some(Expected) /* Grout don't have sorts rn */
| Any () => Some(Expected) /* Grout doesn't have sorts rn */

Copilot uses AI. Check for mistakes.
| _ => None
};
};

let dynamics = true;
let focusable = Focusable.non;

let typ_view = (info: info, utility, view_seg: View.seg) => {
let dynamic_typ =
info.dynamics
|> Option.bind(
_,
(d: Dynamics.Info.t) => {
let statics =
Statics.mk(CoreSettings.on, Builtins.ctx_init(Some(Int)));
let type_of = (c: Dynamics.Probe.Closure.t) => {
IdTagged.rep_id(c.value)
|> Id.Map.find_opt(_, statics(c.value))
|> Option.bind(
_,
fun
| InfoExp(e) => {
Some(e.ty);
}
| _ => None,
);
};
let types = List.map(type_of, d) |> Util.OptUtil.sequence;

Option.map(Typ.consistent_join(Ctx.empty), types);
},
)
|> Option.value(~default=Typ.fresh(Unknown(Internal)));
div(
~attrs=[Attr.classes(["dyntype-cell"])],
[Typ(dynamic_typ) |> utility.term_to_seg |> view_seg(Sort.Typ)],
);
};

let update = (model, _, a: action) =>
switch (a, model) {
| (ToggleDisplay, Expected) => Self
| (ToggleDisplay, Self) => Expected
};

let syntax_str = (info: info) => {
let max_len = 30;
let seg = Segment.unparenthesize(info.syntax);
let str = info.utility.seg_to_string(seg);
let str = Re.Str.global_replace(Re.Str.regexp("\n"), " ", str);
String.length(str) > max_len
? String.sub(str, 0, max_len) ++ "..." : str;
};

let placeholder = (_m, info) =>
ProjectorCore.Shape.inline(3 + String.length(syntax_str(info)));

let syntax_view = (info: info) => info |> syntax_str |> text;

let icon = div(~attrs=[Attr.classes(["icon"])], []);

let view =
(
_: model,
info: info,
~local: action => Ui_effect.t(unit),
~parent as _,
~view_seg,
) =>
View.{
inline:
div(
~attrs=[
Attr.classes(["main"]),
Attr.on_double_click(_ => local(ToggleDisplay)),
],
[syntax_view(info), icon],
),
offside:
Some(
div(
~attrs=[Attr.classes(["offside"])],
[typ_view(info, info.utility, view_seg)],
),
),
overlay: None,
};
};
2 changes: 2 additions & 0 deletions src/language/term/Grammar.re
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ and type_provenance('a) =
| SynSwitch
| Hole(type_hole('a))
| Internal
| Inconsistent
and filter('a) = {
pat: exp_t('a),
act: FilterAction.t,
Expand Down Expand Up @@ -416,6 +417,7 @@ and map_type_provenance_annotation:
| SynSwitch => SynSwitch
| Hole(h) => Hole(map_type_hole_annotation(f, h))
| Internal => Internal
| Inconsistent => Inconsistent
};
}
and map_type_hole_annotation:
Expand Down
1 change: 1 addition & 0 deletions src/language/term/TermBase.re
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ and Typ: {
| Unknown(Hole(Invalid(_)))
| Unknown(SynSwitch)
| Unknown(Internal)
| Unknown(Inconsistent)
| Atom(_)
| Label(_)
| Var(_) => term
Expand Down
59 changes: 46 additions & 13 deletions src/language/term/Typ.re
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type cls =
| MultiHole
| SynSwitch
| Internal
| Inconsistent
| Arrow
| Prod
| TupLabel
Expand Down Expand Up @@ -81,6 +82,7 @@ let cls_of_term: Grammar.typ_term('a) => cls =
| Unknown(Hole(MultiHole(_))) => MultiHole
| Unknown(SynSwitch) => SynSwitch
| Unknown(Internal) => Internal
| Unknown(Inconsistent) => Inconsistent
| Atom(c) => Atom(c)
| List(_) => List
| Arrow(_) => Arrow
Expand All @@ -99,6 +101,7 @@ let show_cls: cls => string =
| Invalid => "Invalid type"
| MultiHole => "Broken type"
| EmptyHole => "Type hole"
| Inconsistent => "Join of Inconsistent types"
| SynSwitch => "Synthetic type"
| Internal => "Internal type"
| Atom(_) => "Base type"
Expand Down Expand Up @@ -224,6 +227,8 @@ let join_type_provenance =
| (Internal, SynSwitch) => SynSwitch
| (Internal | Hole(_), _)
| (_, Hole(_)) => Internal
| (Inconsistent, _)
| (_, Inconsistent) => Inconsistent
| (SynSwitch, SynSwitch) => SynSwitch
};

Expand Down Expand Up @@ -430,13 +435,23 @@ let equal = (t1: t, t2: t): bool => fast_equal(t1, t2);
resolve parameter specifies whether, in the case of a type
variable and a succesful join, to return the resolved join type,
or to return the (first) type variable for readability */
let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => {
let join' = join(~resolve, ctx);
let rec join =
(
~inconsistent: option(t)=?,
~resolve=false,
ctx: Ctx.t,
ty1: t,
ty2: t,
)
: option(t) => {
let join' = join(~inconsistent?, ~resolve, ctx);
switch (term_of(ty1), term_of(ty2)) {
| (_, Parens(ty2)) => join'(ty1, ty2)
| (Parens(ty1), _) => join'(ty1, ty2)
| (Unknown(p1), Unknown(p2)) =>
Some(Unknown(join_type_provenance(p1, p2)) |> temp)
| (Unknown(Inconsistent), _) => Some(ty1)
| (_, Unknown(Inconsistent)) => Some(ty2)
| (Unknown(_), _) => Some(ty2)
| (_, Unknown(_)) => Some(ty1)
| (Var(n1), Var(n2)) =>
Expand Down Expand Up @@ -466,7 +481,7 @@ let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => {
};
let+ ty_body = join(~resolve, ctx, ty1', ty2);
Rec(tp1, ty_body) |> temp;
| (Rec(_), _) => None
| (Rec(_), _) => inconsistent
| (Forall(x1, ty1), Forall(x2, ty2)) =>
let ty1' =
switch (TPat.tyvar_of_utpat(x2)) {
Expand All @@ -482,25 +497,25 @@ let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => {
be exposed to the user. We preserve the variable name of the
second type to preserve synthesized type variable names, which
come from user annotations. */
| (Forall(_), _) => None
| (Forall(_), _) => inconsistent
| (Atom(c1), Atom(c2)) when c1 == c2 => Some(ty1)
| (Atom(_), _) => None
| (Atom(_), _) => inconsistent
| (Label(_), Label("")) => Some(ty1)
| (Label(""), Label(_)) => Some(ty2)
| (Label(name1), Label(name2))
when LabeledTuple.match_labels(name1, name2) =>
Some(ty1)
| (Label(_), _) => None
| (Label(_), _) => inconsistent
| (Arrow(ty1, ty2), Arrow(ty1', ty2')) =>
let* ty1 = join'(ty1, ty1');
let+ ty2 = join'(ty2, ty2');
Arrow(ty1, ty2) |> temp;
| (Arrow(_), _) => None
| (Arrow(_), _) => inconsistent
| (TupLabel(lab1, ty1'), TupLabel(lab2, ty2')) =>
let* lab = join'(lab1, lab2);
let+ ty = join'(ty1', ty2');
TupLabel(lab, ty) |> temp;
| (TupLabel(_), _) => None
| (TupLabel(_), _) => inconsistent
| (Prod(tys1), Prod(tys2)) =>
if (List.length(tys1) != List.length(tys2)) {
None;
Expand All @@ -509,15 +524,15 @@ let rec join = (~resolve=false, ctx: Ctx.t, ty1: t, ty2: t): option(t) => {
let+ tys = OptUtil.sequence(tys);
Prod(tys) |> temp;
}
| (Prod(_), _) => None
| (Prod(_), _) => inconsistent
| (Sum(sm1), Sum(sm2)) =>
let+ sm' = ConstructorMap.join(equal, join(~resolve, ctx), sm1, sm2);
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

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

Missing ~inconsistent? parameter: The recursive call to join on line 672 should pass the ~inconsistent? parameter like other recursive calls (e.g., line 584, 729), but it's missing. This means the Sum case won't properly propagate the inconsistent type marker. Should be join(~inconsistent?, ~resolve, ctx).

Suggested change
let+ sm' = ConstructorMap.join(equal, join(~resolve, ctx), sm1, sm2);
let+ sm' = ConstructorMap.join(equal, join(~inconsistent?, ~resolve, ctx), sm1, sm2);

Copilot uses AI. Check for mistakes.
Sum(sm') |> temp;
| (Sum(_), _) => None
| (Sum(_), _) => inconsistent
| (List(ty1), List(ty2)) =>
let+ ty = join'(ty1, ty2);
List(ty) |> temp;
| (List(_), _) => None
| (List(_), _) => inconsistent
| (Ap(_), _) => failwith("Type join of ap")
};
};
Expand Down Expand Up @@ -561,16 +576,34 @@ let rec match_synswitch = (t1: t, t2: t) => {
};
};

let join_all = (~empty: t, ctx: Ctx.t, ts: list(t)): option(t) =>
let join_all =
(~inconsistent=?, ~empty: t, ctx: Ctx.t, ts: list(t)): option(t) =>
List.fold_left(
(acc, ty) => OptUtil.and_then(join(ctx, ty), acc),
(acc, ty) => OptUtil.and_then(join(~inconsistent?, ctx, ty), acc),
Some(empty),
ts,
);

let is_consistent = (ctx: Ctx.t, ty1: t, ty2: t): bool =>
join(ctx, ty1, ty2) != None;

/*
Computes the most precise type that is consistent with all input types.
Like a multi-way join, but if any ground types are inconsistent, replaces
that position with an "unknown" type rather than failing.
This operation is NOT associative — applying it pairwise may yield
a different result than applying it to the whole list at once.
*/
let consistent_join = (ctx: Ctx.t, tys: list(t)): t => {
join_all(
~inconsistent=Unknown(Inconsistent) |> temp,
~empty=Unknown(SynSwitch) |> temp,
ctx,
tys,
)
|> Option.value(~default=Unknown(SynSwitch) |> temp);
};

/**
* Determines if one type (`ty1`) is more precise than another type (`ty2`) within a given context (`ctx`).
*
Expand Down
1 change: 1 addition & 0 deletions src/web/app/explainthis/ExplainThis.re
Original file line number Diff line number Diff line change
Expand Up @@ -2400,6 +2400,7 @@ let get_doc =
switch (bypass_parens_typ(term).term) {
| Unknown(SynSwitch)
| Unknown(Internal)
| Unknown(Inconsistent)
| Unknown(Hole(EmptyHole)) => get_message(HoleTyp.empty_hole)
| Unknown(Hole(MultiHole(_))) => get_message(HoleTyp.multi_hole)
| Atom(Int) => get_message(TerminalTyp.int)
Expand Down
7 changes: 7 additions & 0 deletions src/web/app/input/Shortcut.re
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ let shortcuts = (sys: Util.Key.sys): list(t) =>
"Type",
Globals(ActiveEditor(Project(SetIndicated(Specific(Info))))),
),
mk_shortcut(
~hotkey="alt+d",
~mdIcon="camera",
~section="Projection",
"Dynamic Type",
Globals(ActiveEditor(Project(SetIndicated(Specific(DynType))))),
),
mk_shortcut(
~hotkey="alt+l",
~mdIcon="camera",
Expand Down
1 change: 1 addition & 0 deletions src/web/www/style/projectors/proj-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@import "panel.css";
@import "proj-probe.css";
@import "proj-type.css";
@import "proj-dyntype.css";
@import "proj-cards.css";
@import "proj-text.css";
@import "proj-fold.css";
Expand Down
Loading