@@ -145,47 +145,84 @@ and ValidateOptArgOrder (synSimplePats: SynSimplePats) =
145145 List.iter ( fun pat -> if isOptArg pat then hitOptArg <- true elif hitOptArg then error( Error( FSComp.SR.tcOptionalArgsMustComeAfterNonOptionalArgs(), m))) pats
146146
147147
148- /// Bind the patterns used in argument position for a function, method or lambda.
149- and TcSimplePats ( cenv : cenv ) optionalArgsOK checkConstraints ty env patEnv synSimplePats =
148+ /// Bind the patterns used in the argument position for a function, method or lambda.
149+ and TcSimplePats ( cenv : cenv ) optionalArgsOK checkConstraints ty env patEnv synSimplePats ( parsedPatterns : SynPat list * bool ) =
150150
151- let g = cenv.g
152- let ( TcPatLinearEnv ( tpenv , names , takenNames )) = patEnv
153-
154- // validate optional argument declaration
151+ let rec collectBoundIdTextsFromPat ( acc : string list ) ( p : SynPat ) : string list =
152+ match p with
153+ | SynPat.FromParseError( p, _)
154+ | SynPat.Paren( p, _) -> collectBoundIdTextsFromPat acc p
155+ | SynPat.Tuple(_, ps, _, _)
156+ | SynPat.ArrayOrList(_, ps, _) -> List.fold collectBoundIdTextsFromPat acc ps
157+ | SynPat.As( lhs, rhs, _) -> collectBoundIdTextsFromPat ( collectBoundIdTextsFromPat acc lhs) rhs
158+ | SynPat.Named( SynIdent( id, _), _, _, _)
159+ | SynPat.OptionalVal( id, _) -> id.idText :: acc
160+ | SynPat.LongIdent( argPats = SynArgPats.Pats ps) -> List.fold collectBoundIdTextsFromPat acc ps
161+ | SynPat.Or( p1, p2, _, _) -> collectBoundIdTextsFromPat ( collectBoundIdTextsFromPat acc p1) p2
162+ | SynPat.Ands( pats, _) -> List.fold collectBoundIdTextsFromPat acc pats
163+ | SynPat.Record( fieldPats = fields) ->
164+ ( acc, fields)
165+ ||> List.fold ( fun acc ( NamePatPairField ( _ , _ , _ , pat , _ )) -> collectBoundIdTextsFromPat acc pat)
166+ | SynPat.ListCons( lhsPat = l; rhsPat = r) -> collectBoundIdTextsFromPat ( collectBoundIdTextsFromPat acc l) r
167+ | _ -> acc
168+
169+ let augmentTakenNamesFromFirstGroup ( parsedData : SynPat list * bool ) ( patEnvOut : TcPatLinearEnv ) : TcPatLinearEnv =
170+ match parsedData, patEnvOut with
171+ | ( pats , true ), TcPatLinearEnv( tpenvR, namesR, takenNamesR) ->
172+ match pats with
173+ | pat :: _ ->
174+ let extra = collectBoundIdTextsFromPat [] pat |> Set.ofList
175+ TcPatLinearEnv( tpenvR, namesR, Set.union takenNamesR extra)
176+ | _ -> patEnvOut
177+ | _ -> patEnvOut
178+
179+ let bindCurriedGroup ( synSimplePats : SynSimplePats ) : string list * TcPatLinearEnv =
180+ let g = cenv.g
181+ let ( TcPatLinearEnv ( tpenv , names , takenNames )) = patEnv
182+ match synSimplePats with
183+ | SynSimplePats.SimplePats ([], _, m) ->
184+ // Unit "()" patterns in argument position become SynSimplePats.SimplePats([], _) in the
185+ // syntactic translation when building bindings. This is done because the
186+ // use of "()" has special significance for arity analysis and argument counting.
187+ //
188+ // Here we give a name to the single argument implied by those patterns.
189+ // This is a little awkward since it would be nice if this was
190+ // uniform with the process where we give names to other (more complex)
191+ // patterns used in argument position, e.g. "let f (D(x)) = ..."
192+ let id = ident( " unitVar" + string takenNames.Count, m)
193+ UnifyTypes cenv env m ty g.unit_ ty
194+ let vFlags = TcPatValFlags ( ValInline.Optional, permitInferTypars, noArgOrRetAttribs, false , None, true )
195+ let _ , namesR , takenNamesR = TcPatBindingName cenv env id ty false None None vFlags ( names, takenNames)
196+ [ id.idText ], TcPatLinearEnv( tpenv, namesR, takenNamesR)
197+ | SynSimplePats.SimplePats ([ sp], _, _) ->
198+ // Single parameter: no tuple splitting, check directly
199+ let v , patEnv' = TcSimplePat optionalArgsOK checkConstraints cenv ty env patEnv sp []
200+ [ v ], patEnv'
201+ | SynSimplePats.SimplePats ( ps, _, m) ->
202+ // Multiple parameters: treat a domain type as a ref-tuple and map each simple pat
203+ let ptys = UnifyRefTupleType env.eContextInfo cenv env.DisplayEnv m ty ps
204+ let namesOut , patEnvR =
205+ ( patEnv, List.zip ptys ps)
206+ ||> List.mapFold ( fun penv ( pty , sp ) -> TcSimplePat optionalArgsOK checkConstraints cenv pty env penv sp [])
207+ namesOut, patEnvR
208+
209+ // 1) validate optional-arg ordering
155210 ValidateOptArgOrder synSimplePats
156211
157- match synSimplePats with
158- | SynSimplePats.SimplePats ([],_, m) ->
159- // Unit "()" patterns in argument position become SynSimplePats.SimplePats([], _) in the
160- // syntactic translation when building bindings. This is done because the
161- // use of "()" has special significance for arity analysis and argument counting.
162- //
163- // Here we give a name to the single argument implied by those patterns.
164- // This is a little awkward since it would be nice if this was
165- // uniform with the process where we give names to other (more complex)
166- // patterns used in argument position, e.g. "let f (D(x)) = ..."
167- let id = ident( " unitVar" + string takenNames.Count, m)
168- UnifyTypes cenv env m ty g.unit_ ty
169- let vFlags = TcPatValFlags ( ValInline.Optional, permitInferTypars, noArgOrRetAttribs, false , None, true )
170- let _ , namesR , takenNamesR = TcPatBindingName cenv env id ty false None None vFlags ( names, takenNames)
171- let patEnvR = TcPatLinearEnv( tpenv, namesR, takenNamesR)
172- [ id.idText], patEnvR
212+ // 2) bind the current curried group
213+ let namesOut , patEnvOut = bindCurriedGroup synSimplePats
173214
174- | SynSimplePats.SimplePats ( pats = [ synSimplePat]) ->
175- let v , patEnv = TcSimplePat optionalArgsOK checkConstraints cenv ty env patEnv synSimplePat []
176- [ v], patEnv
215+ // 3) post-augment takenNames for later groups (using the original first-group pattern)
216+ let patEnvOut = augmentTakenNamesFromFirstGroup parsedPatterns patEnvOut
177217
178- | SynSimplePats.SimplePats ( ps, _, m) ->
179- let ptys = UnifyRefTupleType env.eContextInfo cenv env.DisplayEnv m ty ps
180- let ps ' , patEnvR = ( patEnv, List.zip ptys ps) ||> List.mapFold ( fun patEnv ( ty , pat ) -> TcSimplePat optionalArgsOK checkConstraints cenv ty env patEnv pat [])
181- ps', patEnvR
218+ namesOut, patEnvOut
182219
183220and TcSimplePatsOfUnknownType ( cenv : cenv ) optionalArgsOK checkConstraints env tpenv ( pat : SynPat ) =
184221 let g = cenv.g
185222 let argTy = NewInferenceType g
186223 let patEnv = TcPatLinearEnv ( tpenv, NameMap.empty, Set.empty)
187224 let spats , _ = SimplePatsOfPat cenv.synArgNameGenerator pat
188- let names , patEnv = TcSimplePats cenv optionalArgsOK checkConstraints argTy env patEnv spats
225+ let names , patEnv = TcSimplePats cenv optionalArgsOK checkConstraints argTy env patEnv spats ([], false )
189226 names, patEnv, spats
190227
191228and TcPatBindingName cenv env id ty isMemberThis vis1 valReprInfo ( vFlags : TcPatValFlags ) ( names , takenNames : Set < string >) =
0 commit comments