Skip to content

Commit 7c23ae8

Browse files
authored
Merge pull request #4116 from FStarLang/nik_4086
fix(typechecker): allow record syntax on non-record types when fields…
2 parents 7c9ca52 + 62c5a2b commit 7c23ae8

3 files changed

Lines changed: 40 additions & 12 deletions

File tree

src/typechecker/FStarC.TypeChecker.TcTerm.fst

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,11 +1188,17 @@ and tc_maybe_toplevel_term env (e:term) : term (* type-checked
11881188
in
11891189
let rdc : DsEnv.record_or_dc = rdc in //for type-based disambiguation of rdc projectors below
11901190
let open FStarC.Pprint in
1191-
if Some? (Env.expected_typ env) && not rdc.is_record then
1192-
raise_error top Errors.Error_CannotResolveRecord [
1193-
text "Expected an expression of type" ^/^ pp (fst (Some?.v (Env.expected_typ env)));
1194-
text "Type" ^/^ pp rdc.typename ^/^ text "is not a record type.";
1195-
];
1191+
(if Some? (Env.expected_typ env) && not rdc.is_record then
1192+
let rdc_field_names = List.map (fun (i, _) -> Ident.string_of_id i) rdc.fields in
1193+
let bad_field = List.tryFind (fun i -> not (List.existsb (fun f -> f = Ident.string_of_id (Ident.ident_of_lid i)) rdc_field_names)) uc.uc_fields in
1194+
match bad_field with
1195+
| Some f ->
1196+
raise_error top Errors.Error_CannotResolveRecord [
1197+
text "Expected an expression of type" ^/^ pp (fst (Some?.v (Env.expected_typ env)));
1198+
text "Type" ^/^ pp rdc.typename ^/^ text "is not declared as a record type;" ^/^
1199+
text "field" ^/^ pp f ^/^ text "is not valid for this type.";
1200+
]
1201+
| None -> ());
11961202
let constructor = S.fv_to_tm constructor in
11971203
let mk_field_projector i x =
11981204
let projname = mk_field_projector_name_from_ident constrname i in
@@ -3274,11 +3280,18 @@ and tc_pat env (pat_t:typ) (p0:pat) :
32743280
let rdc, _, constructor_fv = TcUtil.find_record_or_dc_from_head_fv env (TcUtil.head_fv_of_typ env t) uc p.p in
32753281
let f_sub_pats = List.zip uc.uc_fields sub_pats in
32763282
let open FStarC.Pprint in
3277-
if not rdc.is_record then
3278-
raise_error p Errors.Error_CannotResolveRecord [
3279-
text "Expected a pattern of type" ^/^ pp t;
3280-
text "Type" ^/^ pp rdc.typename ^/^ text "is not a record type.";
3281-
];
3283+
if not rdc.is_record then begin
3284+
let rdc_field_names = List.map (fun (i, _) -> Ident.string_of_id i) rdc.fields in
3285+
let bad_field = List.tryFind (fun i -> not (List.existsb (fun f -> f = Ident.string_of_id (Ident.ident_of_lid i)) rdc_field_names)) uc.uc_fields in
3286+
match bad_field with
3287+
| Some f ->
3288+
raise_error p Errors.Error_CannotResolveRecord [
3289+
text "Expected a pattern of type" ^/^ pp t;
3290+
text "Type" ^/^ pp rdc.typename ^/^ text "is not declared as a record type;" ^/^
3291+
text "field" ^/^ pp f ^/^ text "is not valid for this type.";
3292+
]
3293+
| None -> ()
3294+
end;
32823295
let sub_pats =
32833296
TcUtil.make_record_fields_in_order env uc (Some (Inl t)) rdc f_sub_pats
32843297
(fun _ ->

tests/bug-reports/closed/Bug3757.fst.output.expected

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
* Info at Bug3757.fst(8,4-8,13):
22
- Expected failure:
33
- Expected a pattern of type Prims.int & Prims.int
4-
- Type FStar.Pervasives.Native.tuple2 is not a record type.
4+
- Type
5+
FStar.Pervasives.Native.tuple2
6+
is not declared as a record type;
7+
field
8+
x
9+
is not valid for this type.
510

611
* Info at Bug3757.fst(12,28-12,31):
712
- Expected failure:
813
- Expected an expression of type Prims.int & Prims.bool
9-
- Type FStar.Pervasives.Native.tuple2 is not a record type.
14+
- Type
15+
FStar.Pervasives.Native.tuple2
16+
is not declared as a record type;
17+
field
18+
x
19+
is not valid for this type.
1020

1121
* Info at Bug3757.fst(15,15-15,17):
1222
- Expected failure:

tests/micro-benchmarks/RecordUpdate.fst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ module RecordUpdate
33
(* This should work, even if `t` is not declared as a record.*)
44
type t = | T : int -> t
55
let f (x:t) = {x with _0 = 1}
6+
7+
(* These should also work with type annotations and pattern matching *)
8+
let g (x:t) : t = {x with _0 = 1}
9+
let h () : t = { _0 = 1 }
10+
let i (x:t) = match x with | { _0 = n } -> n

0 commit comments

Comments
 (0)