@@ -804,9 +804,14 @@ end) = struct
804804  let  lookup_from_type  env  tpath  (lid  : Longident.t loc ) : Name.t  = 
805805    let  descrs =  get_descrs (Env. find_type_descrs tpath env) in 
806806    Env. mark_type_used env (Path. last tpath) (Env. find_type tpath env);
807-     (*  TODO(dict-pattern-matching): also lookup the actual definition and check for @res.dict? *) 
808807    let  is_dict =  Path. same tpath Predef. path_dict in 
809808    if  is_dict then  (
809+       (*  [dict] Dicts are implented as a record with a single "magic" field. This magic field is 
810+          used to track the dict value type, and any label lookup on the dict record type  
811+          will give that single value type back. This is how we can piggy back on the record  
812+          pattern matching mechanism. 
813+          
814+         The code below handles directing any label lookup to the magic field. *)  
810815      match  lid.txt with 
811816        Longident. Lident  s_  -> begin 
812817          let  s =  
@@ -908,7 +913,11 @@ module Label = NameChoice (struct
908913  type  t  = label_description 
909914  let  type_kind =  " record" 
910915  let  get_name  lbl  =  lbl.lbl_name
916+   
911917  let  add_with_name  lbl  name  = 
918+     (*  [dict] This is used in dicts and shouldn't be used anywhere else. 
919+        It adds a new field to an existing record type, to "fool" the pattern 
920+        matching into thinking the label exists. *)  
912921    let  l =  
913922      {lbl with 
914923        lbl_name =  name;
@@ -1387,9 +1396,10 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
13871396      let  has_dict_pattern_attr =  Dict_type_helpers. has_dict_pattern_attribute sp.ppat_attributes in 
13881397      let  opath, record_ty =  (
13891398      if  has_dict_pattern_attr then  (
1390-         (*  When this is a dict pattern and we don't have an actual expected type yet, 
1391-          infer the type as a dict with a new type variable. This let us hook into the  
1392-          existing inference mechanism for records in dict pattern matching too. *)  
1399+         (*  [dict] If this is a dict pattern match we know we should force the record type
1400+             as the dict record type with a fresh type variable. This fixes so that dicts 
1401+             can still be inferred properly from just pattern usage. Without this little  
1402+             tweak, the inference would not work properly. *)  
13931403        (Some  (Predef. path_dict, Predef. path_dict), newgenty (Tconstr  (Predef. path_dict, [newvar () ], ref  Mnil )))
13941404      ) else 
13951405        try 
@@ -3029,10 +3039,10 @@ and type_label_access env srecord lid =
30293039      match  extract_concrete_typedecl env ty_exp with 
30303040      |  (p0, _, {type_attributes}) 
30313041        when  Path. same p0 Predef. path_dict &&  Dict_type_helpers. has_dict_attribute type_attributes -> 
3032-           (*  Cover the case when trying to direct field access on a dict, e.g. `someDict.name`.
3042+           (*  [dict]  Cover the case when trying to direct field access on a dict, e.g. `someDict.name`.
30333043            We need to disallow this because the fact that a dict is represented as a single field 
30343044            record internally is just an implementation detail, and not intended to be exposed to 
3035-             the user.*)  
3045+             the user.  *)  
30363046          raise(Error (lid.loc, env, Field_access_on_dict_type ))
30373047      |  (p0 , p , {type_kind =Type_record  _ } ) -> Some (p0, p)
30383048      |  _  -> None 
0 commit comments