@@ -2617,6 +2617,8 @@ module EstablishTypeDefinitionCores =
26172617 let m = tycon.Range
26182618 let env = AddDeclaredTypars CheckForDuplicateTypars ( tycon.Typars m) env
26192619 let env = MakeInnerEnvForTyconRef env thisTyconRef false
2620+ let ad = env.AccessRights
2621+ let spreadSrcTys = ResizeArray ()
26202622 [ match synTyconRepr with
26212623 | SynTypeDefnSimpleRepr.None _ -> ()
26222624 | SynTypeDefnSimpleRepr.Union (_, unionCases, _) ->
@@ -2660,13 +2662,62 @@ module EstablishTypeDefinitionCores =
26602662 errorR( Error( FSComp.SR.tcStructsMustDeclareTypesOfImplicitCtorArgsExplicitly(), m))
26612663 yield ( ty, m)
26622664
2663- | SynTypeDefnSimpleRepr.Record (_, SynFields fields, _) ->
2664- for SynField( fieldType = ty; range = m) in fields do
2665- let tyR , _ = TcTypeAndRecover cenv NoNewTypars NoCheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes env tpenv ty
2666- yield ( tyR, m)
2665+ | SynTypeDefnSimpleRepr.Record (_, fieldsAndSpreads, _) ->
2666+ let (| LeftwardExplicit | NoLeftwardExplicit |) hasLeftwardExplicit = if hasLeftwardExplicit then LeftwardExplicit else NoLeftwardExplicit
2667+ let LeftwardExplicit = true
2668+ let NoLeftwardExplicit = false
2669+
2670+ // We must apply the spread shadowing logic here to get
2671+ // the correct set of field types.
2672+ let rec collectTys tys fieldsAndSpreads =
2673+ match fieldsAndSpreads with
2674+ | [] ->
2675+ tys
2676+ |> Map.toList
2677+ |> List.collect ( fun ( _ , ( _ , dupes )) -> dupes)
2678+
2679+ | SynFieldOrSpread.Field ( SynField ( idOpt = None)) :: fieldsAndSpreads ->
2680+ collectTys tys fieldsAndSpreads
2681+
2682+ | SynFieldOrSpread.Field ( SynField ( idOpt = Some fieldId; fieldType = ty; range = m)) :: fieldsAndSpreads ->
2683+ let tyR , _ = TcTypeAndRecover cenv NoNewTypars NoCheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes env tpenv ty
2684+ let tys =
2685+ tys |> Map.change fieldId.idText ( function
2686+ | None -> Some ( LeftwardExplicit, [ tyR, m])
2687+ | Some ( LeftwardExplicit, dupes) -> Some ( LeftwardExplicit, ( tyR, m) :: dupes)
2688+ | Some ( NoLeftwardExplicit, _ dupes) -> Some ( LeftwardExplicit, [ tyR, m]))
2689+
2690+ collectTys tys fieldsAndSpreads
2691+
2692+ | SynFieldOrSpread.Spread ( SynTypeSpread ( ty = ty; range = m)) :: fieldsAndSpreads ->
2693+ let spreadSrcTy , _ = TcTypeAndRecover cenv NoNewTypars NoCheckCxs ItemOccurrence.UseInType WarnOnIWSAM.Yes env tpenv ty
2694+
2695+ let fieldsFromSpread =
2696+ if isRecdTy g spreadSrcTy then
2697+ spreadSrcTys.Add spreadSrcTy
2698+ ResolveRecordOrClassFieldsOfType cenv.nameResolver m ad spreadSrcTy false
2699+ |> List.choose ( function
2700+ | Item.RecdField field -> Some ( field.RecdField.Id.idText, ( FreshenRecdFieldRef cenv.nameResolver m field.RecdFieldRef) .FieldType, m)
2701+ | _ -> None)
2702+ else
2703+ match tryDestAnonRecdTy g spreadSrcTy with
2704+ | ValueSome ( anonInfo, tys) -> tys |> List.mapi ( fun i ty -> anonInfo.SortedNames[ i], ty, m)
2705+ | ValueNone -> []
2706+
2707+ let tys =
2708+ ( tys, fieldsFromSpread)
2709+ ||> List.fold ( fun tys ( fieldId , ty , m ) ->
2710+ tys |> Map.change fieldId ( function
2711+ | None -> Some ( NoLeftwardExplicit, [ ty, m])
2712+ | Some ( LeftwardExplicit, _ dupes) -> Some ( LeftwardExplicit, [ ty, m])
2713+ | Some ( NoLeftwardExplicit, _ dupes) -> Some ( NoLeftwardExplicit, [ ty, m])))
2714+
2715+ collectTys tys fieldsAndSpreads
2716+
2717+ yield ! collectTys Map.empty fieldsAndSpreads
26672718
26682719 | _ ->
2669- () ]
2720+ () ], spreadSrcTys
26702721
26712722 let ComputeModuleOrNamespaceKind g isModule typeNames attribs nm =
26722723 if not isModule then ( Namespace true )
@@ -4317,14 +4368,43 @@ module EstablishTypeDefinitionCores =
43174368 // be satisfied, so we have to do this prior to checking any constraints.
43184369 //
43194370 // First find all the field types in all the structural types
4320- let tyconsWithStructuralTypes =
4321- ( envMutRecPrelim, withEnvs)
4322- ||> MutRecShapes.mapTyconsWithEnv ( fun envForDecls ( origInfo , tyconOpt ) ->
4323- match origInfo, tyconOpt with
4324- | ( typeDefCore, _, _), Some tycon -> Some ( tycon, GetStructuralElementsOfTyconDefn cenv envForDecls tpenv typeDefCore tycon)
4325- | _ -> None)
4326- |> MutRecShapes.collectTycons
4327- |> List.choose id
4371+ let tyconsWithStructuralTypes =
4372+ let all =
4373+ ( envMutRecPrelim, withEnvs)
4374+ ||> MutRecShapes.mapTyconsWithEnv ( fun envForDecls ( origInfo , tyconOpt ) ->
4375+ match origInfo, tyconOpt with
4376+ | ( typeDefCore, _, _), Some tycon -> Some ( tycon, GetStructuralElementsOfTyconDefn cenv envForDecls tpenv typeDefCore tycon)
4377+ | _ -> None)
4378+ |> MutRecShapes.collectTycons
4379+ |> List.choose id
4380+
4381+ // Check for cyclic spreads.
4382+ do
4383+ if cenv.g.langVersion.SupportsFeature LanguageFeature.RecordSpreads then
4384+ let (| PotentiallyRecursiveTycon | _ |) ty =
4385+ tryTcrefOfAppTy cenv.g ty
4386+ |> ValueOption.bind _. TryDeref
4387+
4388+ let edges =
4389+ [
4390+ for dst, (_, spreadSrcs) in all do
4391+ for src in spreadSrcs do
4392+ match src with
4393+ | PotentiallyRecursiveTycon src -> dst, src
4394+ | _ -> ()
4395+ ]
4396+
4397+ let tycons =
4398+ [
4399+ for dst, src in edges do
4400+ yield dst
4401+ yield src
4402+ ]
4403+
4404+ let graph = Graph< Tycon, Stamp> (_. Stamp, tycons, edges)
4405+ graph.IterateCycles ( fun path -> errorR ( Error ( FSComp.SR.tcTypeDefinitionIsCyclicThroughSpreads (), ( List.head path) .Range)))
4406+
4407+ [ for tycon, ( tys, _) in all -> tycon, tys]
43284408
43294409 let scSet = TyconConstraintInference.InferSetOfTyconsSupportingComparable cenv envMutRecPrelim.DisplayEnv tyconsWithStructuralTypes
43304410 let seSet = TyconConstraintInference.InferSetOfTyconsSupportingEquatable cenv envMutRecPrelim.DisplayEnv tyconsWithStructuralTypes
0 commit comments