diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md index 4f5975f3e8d..df9024958bb 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md @@ -1,6 +1,7 @@ ### Added * Add opt-in warning attribute not valid for union case with fields [PR #18532](https://github.com/dotnet/fsharp/pull/18532)) * Add support for `when 'T : Enum` library-only static optimization constraint. ([PR #18546](https://github.com/dotnet/fsharp/pull/18546)) +* Allow mixing ranges and values to construct sequences. ([PR #18670](https://github.com/dotnet/fsharp/pull/18670)) * Add support for tail calls in computation expressions ([PR #18804](https://github.com/dotnet/fsharp/pull/18804)) * Add `--typecheck-only` flag support for F# Interactive (FSI) scripts to type-check without execution. ([Issue #18686](https://github.com/dotnet/fsharp/issues/18686)) diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index b9afee7582e..3dac5c63276 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -8,6 +8,7 @@ * Warn when `unit` is passed to an `obj`-typed argument ([PR #18330](https://github.com/dotnet/fsharp/pull/18330)) * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) * Scoped Nowarn: added the #warnon compiler directive ([Language suggestion #278](https://github.com/fsharp/fslang-suggestions/issues/278), [RFC FS-1146 PR](https://github.com/fsharp/fslang-design/pull/782), [PR #18049](https://github.com/dotnet/fsharp/pull/18049)) +* Allow mixing ranges and values to construct sequences. ([PR #18670](https://github.com/dotnet/fsharp/pull/18670)) * Allow `let!`, `use!`, `and!` type annotations without requiring parentheses (([PR #18508](https://github.com/dotnet/fsharp/pull/18508) and [PR #18682](https://github.com/dotnet/fsharp/pull/18682))) * Exception names are now validated for illegal characters using the same mechanism as types/modules/namespaces ([Issue #18763](https://github.com/dotnet/fsharp/issues/18763)) * Support tail calls in computation expressions ([PR #18804](https://github.com/dotnet/fsharp/pull/18804)) diff --git a/src/Compiler/Checking/Expressions/CheckArrayOrListComputedExpressions.fs b/src/Compiler/Checking/Expressions/CheckArrayOrListComputedExpressions.fs index f8a2abd7d73..9ff4c6d4eb9 100644 --- a/src/Compiler/Checking/Expressions/CheckArrayOrListComputedExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckArrayOrListComputedExpressions.fs @@ -7,12 +7,43 @@ open FSharp.Compiler.CheckBasics open FSharp.Compiler.ConstraintSolver open FSharp.Compiler.CheckExpressionsOps open FSharp.Compiler.CheckExpressions +open FSharp.Compiler.CheckSequenceExpressions open FSharp.Compiler.NameResolution open FSharp.Compiler.TypedTreeOps open FSharp.Compiler.Features open FSharp.Compiler.DiagnosticsLogger open FSharp.Compiler.Syntax -open FSharp.Compiler.CheckSequenceExpressions + +let private tcMixedSequencesWithRanges (cenv: TcFileState) env overallTy tpenv isArray elems m = + let g = cenv.g + let transformedBody = insertImplicitYieldsAndYieldBangs elems m + + let genCollElemTy = NewInferenceType g + let genCollTy = (if isArray then mkArrayType else mkListTy) g genCollElemTy + + TcPropagatingExprLeafThenConvert cenv overallTy genCollTy env m (fun () -> + let exprTy = mkSeqTy g genCollElemTy + + let expr, tpenv' = + TcSequenceExpression cenv env tpenv transformedBody (MustEqual exprTy) m + + let expr = mkCoerceIfNeeded g exprTy (tyOfExpr g expr) expr + + let expr = + if g.compilingFSharpCore then + expr + else + mkCallSeq g m genCollElemTy expr + + let expr = mkCoerceExpr (expr, exprTy, expr.Range, overallTy.Commit) + + let expr = + if isArray then + mkCallSeqToArray g m genCollElemTy expr + else + mkCallSeqToList g m genCollElemTy expr + + expr, tpenv') let TcArrayOrListComputedExpression (cenv: TcFileState) env (overallTy: OverallTy) tpenv (isArray, comp) m = let g = cenv.g @@ -68,65 +99,127 @@ let TcArrayOrListComputedExpression (cenv: TcFileState) env (overallTy: OverallT errorR (Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis (), m)) | _ -> () - let replacementExpr = - if isArray then - // This are to improve parsing/processing speed for parser tables by converting to an array blob ASAP - let nelems = elems.Length - - if - nelems > 0 - && List.forall - (function - | SynExpr.Const(SynConst.UInt16 _, _) -> true - | _ -> false) - elems - then - SynExpr.Const( - SynConst.UInt16s( - Array.ofList ( - List.map - (function - | SynExpr.Const(SynConst.UInt16 x, _) -> x - | _ -> failwith "unreachable") - elems - ) - ), - m - ) - elif - nelems > 0 - && List.forall - (function - | SynExpr.Const(SynConst.Byte _, _) -> true - | _ -> false) - elems - then - SynExpr.Const( - SynConst.Bytes( - Array.ofList ( - List.map - (function - | SynExpr.Const(SynConst.Byte x, _) -> x - | _ -> failwith "unreachable") - elems + if g.langVersion.SupportsFeature LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions then + tcMixedSequencesWithRanges cenv env overallTy tpenv isArray elems m + else + let reportRangeExpressionsNotSupported expr = + let rec loop exprs = + match exprs with + | [] -> () + | SynExpr.IndexRange(_, _, _, _, _, m) :: exprs -> + checkLanguageFeatureAndRecover g.langVersion LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions m + loop exprs + | SynExpr.Sequential(_, true, e1, e2, _, _) :: exprs -> loop (e1 :: e2 :: exprs) + | _ :: exprs -> loop exprs + + loop [ expr ] + + reportRangeExpressionsNotSupported comp + + let replacementExpr = + // These are to improve parsing/processing speed for parser tables by converting to an array blob ASAP + if isArray then + let nelems = elems.Length + + if + nelems > 0 + && List.forall + (function + | SynExpr.Const(SynConst.UInt16 _, _) -> true + | _ -> false) + elems + then + SynExpr.Const( + SynConst.UInt16s( + Array.ofList ( + List.map + (function + | SynExpr.Const(SynConst.UInt16 x, _) -> x + | _ -> failwith "unreachable") + elems + ) + ), + m + ) + elif + nelems > 0 + && List.forall + (function + | SynExpr.Const(SynConst.Byte _, _) -> true + | _ -> false) + elems + then + SynExpr.Const( + SynConst.Bytes( + Array.ofList ( + List.map + (function + | SynExpr.Const(SynConst.Byte x, _) -> x + | _ -> failwith "unreachable") + elems + ), + SynByteStringKind.Regular, + m ), - SynByteStringKind.Regular, m - ), - m - ) + ) + else + SynExpr.ArrayOrList(isArray, elems, m) + else if cenv.g.langVersion.SupportsFeature(LanguageFeature.ReallyLongLists) then + SynExpr.ArrayOrList(isArray, elems, m) else + if elems.Length > 500 then + error (Error(FSComp.SR.tcListLiteralMaxSize (), m)) + SynExpr.ArrayOrList(isArray, elems, m) - else if cenv.g.langVersion.SupportsFeature(LanguageFeature.ReallyLongLists) then - SynExpr.ArrayOrList(isArray, elems, m) + + TcExprUndelayed cenv overallTy env tpenv replacementExpr + | _ -> + let containsRangeMixedWithYields = + let rec hasRangeAndYield expr hasRange hasYield cont = + match expr with + | SynExpr.IndexRange _ -> cont true hasYield + | SynExpr.YieldOrReturnFrom _ -> cont hasRange true + | SynExpr.Sequential(_, _, e1, e2, _, _) -> + hasRangeAndYield e1 hasRange hasYield (fun r1 y1 -> hasRangeAndYield e2 r1 y1 cont) + | _ -> cont hasRange hasYield + + hasRangeAndYield comp false false (fun r y -> r && y) + + // Transform mixed expressions with explicit yields to ensure all elements are properly yielded + let comp = + if + containsRangeMixedWithYields + && g.langVersion.SupportsFeature LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + then + match comp with + | SynExpr.Sequential _ -> + // Extract the elements from the sequential expression + let rec getElems expr acc = + match expr with + | SynExpr.Sequential(_, true, e1, e2, _, _) -> getElems e2 (e1 :: acc) + | e -> List.rev (e :: acc) + + let elems = getElems comp [] + insertImplicitYieldsAndYieldBangs elems m + | _ -> comp else - if elems.Length > 500 then - error (Error(FSComp.SR.tcListLiteralMaxSize (), m)) + // Report language feature error for each range expression in a sequence + let reportRangeExpressionsNotSupported expr = + let rec loop exprs = + match exprs with + | [] -> () + | SynExpr.IndexRange(_, _, _, _, _, m) :: exprs -> + checkLanguageFeatureAndRecover g.langVersion LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions m + loop exprs + | SynExpr.Sequential(_, true, e1, e2, _, _) :: exprs -> loop (e1 :: e2 :: exprs) + | _ :: exprs -> loop exprs - SynExpr.ArrayOrList(isArray, elems, m) + loop [ expr ] - TcExprUndelayed cenv overallTy env tpenv replacementExpr - | _ -> + reportRangeExpressionsNotSupported comp + + comp let genCollElemTy = NewInferenceType g diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs index 1f31414599d..d0fdaca9a73 100644 --- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs @@ -959,7 +959,7 @@ let requireBuilderMethod methodName ceenv m1 m2 = error (Error(FSComp.SR.tcRequireBuilderMethod methodName, m2)) /// -/// Try translate the syntax sugar +/// Try to translate the syntax sugar /// /// Computation expression context (carrying caches, environments, ranges, etc) /// Flag if it's initial check @@ -1603,12 +1603,70 @@ let rec TryTranslateComputationExpression Some(ConsumeCustomOpClauses ceenv comp q varSpace dataCompPriorToOp comp false mClause) | SynExpr.Sequential(sp, true, innerComp1, innerComp2, m, _) -> + let containsRangeExpressions expr = + let rec loop exprs = + match exprs with + | SynExpr.IndexRange _ :: _ -> true + | SynExpr.Sequential(_, true, e1, e2, _, _) :: exprs -> loop (e1 :: e2 :: exprs) + | _ -> false + + loop [ expr ] + + let containsRangeExpressions = containsRangeExpressions comp + + /// Report language feature error for each range expression in a sequence + let reportRangeExpressionsNotSupported ceenv expr = + let rec loop exprs = + match exprs with + | [] -> () + | SynExpr.IndexRange(_, _, _, _, _, m) :: exprs -> + checkLanguageFeatureAndRecover ceenv.cenv.g.langVersion LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions m + loop exprs + | SynExpr.Sequential(_, true, e1, e2, _, _) :: exprs -> loop (e1 :: e2 :: exprs) + | _ :: exprs -> loop exprs + + loop [ expr ] + if + ceenv.cenv.g.langVersion.SupportsFeature LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + && containsRangeExpressions + then + let builderSupportsMixedRanges ceenv m = + hasBuilderMethod ceenv m "Yield" + && hasBuilderMethod ceenv m "Combine" + && hasBuilderMethod ceenv m "Delay" + + if builderSupportsMixedRanges ceenv m then + let transformSequenceWithRanges ceenv expr = + let rec loop expr cont = + match expr with + | SynExpr.Sequential(sp, true, e1, e2, m, trivia) -> + // Transform each part to yield/yieldFrom + let e1Transformed = TransformExprToYieldOrYieldFrom ceenv e1 + // Create a new sequential expression with the transformed parts + loop + e2 + (cont + << fun e2Transformed -> SynExpr.Sequential(sp, true, e1Transformed, e2Transformed, m, trivia)) + | e -> cont (TransformExprToYieldOrYieldFrom ceenv e) + + loop expr id + + let transformed = transformSequenceWithRanges ceenv comp + Some(TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace transformed translatedCtxt) + else + None // Check for 'where x > y' and other mis-applications of infix operators. If detected, give a good error message, and just ignore innerComp1 - if ceenv.isQuery && checkForBinaryApp ceenv innerComp1 then + elif ceenv.isQuery && checkForBinaryApp ceenv innerComp1 then + if containsRangeExpressions then + reportRangeExpressionsNotSupported ceenv comp + Some(TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace innerComp2 translatedCtxt) else + if containsRangeExpressions then + reportRangeExpressionsNotSupported ceenv comp + if ceenv.isQuery && not (innerComp1.IsArbExprAndThusAlreadyReportedError) then match innerComp1 with | SynExpr.JoinIn _ -> () @@ -2251,6 +2309,20 @@ let rec TryTranslateComputationExpression Some(translatedCtxt callExpr) | SynExpr.YieldOrReturnFrom((true, _), synYieldExpr, _, { YieldOrReturnFromKeyword = m }) -> + + let synYieldExpr = + match synYieldExpr with + | SynExpr.IndexRange _ -> + checkLanguageFeatureAndRecover + ceenv.cenv.g.langVersion + LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + synYieldExpr.Range + + match RewriteRangeExpr synYieldExpr with + | Some rewrittenExpr -> rewrittenExpr + | None -> synYieldExpr + | _ -> synYieldExpr + let yieldFromExpr = mkSourceExpr synYieldExpr ceenv.sourceMethInfo ceenv.builderValName @@ -2311,6 +2383,19 @@ let rec TryTranslateComputationExpression if ceenv.isQuery && not isYield then error (Error(FSComp.SR.tcReturnMayNotBeUsedInQueries (), m)) + let synYieldOrReturnExpr = + match synYieldOrReturnExpr with + | SynExpr.IndexRange _ when isYield -> + checkLanguageFeatureAndRecover + ceenv.cenv.g.langVersion + LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + synYieldOrReturnExpr.Range + + match RewriteRangeExpr synYieldOrReturnExpr with + | Some rewrittenExpr -> rewrittenExpr + | None -> synYieldOrReturnExpr + | _ -> synYieldOrReturnExpr + requireBuilderMethod methName ceenv m m let yieldOrReturnCall = @@ -2741,6 +2826,26 @@ and isSimpleExpr ceenv comp = | SynExpr.DoBang _ -> false | _ -> true +/// Transform a single expression to Yield or YieldFrom based on whether it's a range +and TransformExprToYieldOrYieldFrom ceenv expr = + let m = expr.Range + + let ``yield!`` rewrittenRange = + SynExpr.YieldOrReturnFrom((true, false), rewrittenRange, m, { YieldOrReturnFromKeyword = m }) + + let ``yield`` rewrittenRange = + SynExpr.YieldOrReturn((true, false), rewrittenRange, m, { YieldOrReturnKeyword = m }) + + // If there is no YieldFrom defined on the builder, use Yield; + // create a YieldOrReturn expression and let the CE machinery handle it. + match RewriteRangeExpr expr with + | Some rewrittenRange -> + if hasBuilderMethod ceenv m "YieldFrom" then + ``yield!`` rewrittenRange + else + ``yield`` rewrittenRange + | None -> ``yield`` expr + and TranslateComputationExpression (ceenv: ComputationExpressionContext<'a>) firstTry q varSpace comp translatedCtxt = ceenv.cenv.stackGuard.Guard diff --git a/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs b/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs index 6c12485c4ed..f37774ce286 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs @@ -17,6 +17,7 @@ open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeBasics open FSharp.Compiler.TypedTreeOps open FSharp.Compiler.SyntaxTreeOps +open FSharp.Compiler.SyntaxTrivia let TryAllowFlexibleNullnessInControlFlow isFirst (g: TcGlobals.TcGlobals) ty = match isFirst, g.checkNullness, GetTyparTyIfSupportsNull g ty with @@ -389,3 +390,87 @@ let inline mkOptionalParamTyBasedOnAttribute (g: TcGlobals.TcGlobals) tyarg attr mkValueOptionTy g tyarg else mkOptionTy g tyarg + +/// Adds implicit `yield!` before ranges in a mixed list/array/seq comprehension if necessary. +/// E.g., [-3; 1..10; 19] becomes [yield -3; yield! (..) 1 10; yield 19] +let insertImplicitYieldsAndYieldBangs elems m = + let (|RangeExpr|_|) = RewriteRangeExpr + + let (|IfThenElseExpr|_|) expr = + match expr with + | SynExpr.IfThenElse(ifExpr, thenExpr, elseExpr, spIfToThen, isFromErrorRecovery, range, trivia) -> + ValueSome(thenExpr, elseExpr, (ifExpr, spIfToThen, isFromErrorRecovery, range, trivia)) + | _ -> ValueNone + + let ``yield!`` rewritten (orig: SynExpr) = + SynExpr.YieldOrReturnFrom( + (true, false), + rewritten, + orig.Range, + { + YieldOrReturnFromKeyword = orig.Range + } + ) + + let ``yield`` (orig: SynExpr) = + SynExpr.YieldOrReturn((true, false), orig, orig.Range, { YieldOrReturnKeyword = orig.Range }) + + let ``if then`` (ifExpr, spIfToThen, isFromErrorRecovery, m, trivia) thenExpr = + SynExpr.IfThenElse(ifExpr, thenExpr, None, spIfToThen, isFromErrorRecovery, m, trivia) + + let ``if then else`` (ifExpr, spIfToThen, isFromErrorRecovery, m, trivia) thenExpr elseExpr = + SynExpr.IfThenElse(ifExpr, thenExpr, Some elseExpr, spIfToThen, isFromErrorRecovery, m, trivia) + + let ``match`` (dbg, expr, m, trivia) clauses = + SynExpr.Match(dbg, expr, clauses, m, trivia) + + let ``match!`` (dbg, expr, m, trivia) clauses = + SynExpr.MatchBang(dbg, expr, clauses, m, trivia) + + let ``;`` expr1 expr2 = + SynExpr.Sequential(DebugPointAtSequential.SuppressNeither, true, expr1, expr2, m, SynExprSequentialTrivia.Zero) + + let rec loopElems elems cont = + match elems with + | [] -> cont (SynExpr.Const(SynConst.Unit, m)) + + | [ elem & RangeExpr rangeExpr ] -> cont (``yield!`` rangeExpr elem) + + | [ elem & SynExpr.YieldOrReturn _ ] + | [ elem & SynExpr.YieldOrReturnFrom _ ] -> cont elem + + | [ IfThenElseExpr(thenExpr, None, info) ] -> loopElems [ thenExpr ] (cont << ``if then`` info) + | [ IfThenElseExpr(thenExpr, Some elseExpr, info) ] -> + loopElems [ thenExpr ] (fun thenExpr -> loopElems [ elseExpr ] (cont << ``if then else`` info thenExpr)) + + | [ SynExpr.Match(dbg, expr, clauses, m, trivia) ] -> loopMatchClauses [] clauses (cont << ``match`` (dbg, expr, m, trivia)) + | [ SynExpr.MatchBang(dbg, expr, clauses, m, trivia) ] -> loopMatchClauses [] clauses (cont << ``match!`` (dbg, expr, m, trivia)) + + | [ elem ] -> cont (``yield`` elem) + + | (elem & RangeExpr rangeExpr) :: elems -> loopElems elems (cont << ``;`` (``yield!`` rangeExpr elem)) + + | (elem & SynExpr.YieldOrReturn _) :: elems + | (elem & SynExpr.YieldOrReturnFrom _) :: elems -> loopElems elems (cont << ``;`` elem) + + | IfThenElseExpr(thenExpr, None, info) :: elems -> + loopElems [ thenExpr ] (fun thenExpr -> loopElems elems (cont << ``;`` (``if then`` info thenExpr))) + | IfThenElseExpr(thenExpr, Some elseExpr, info) :: elems -> + loopElems [ thenExpr ] (fun thenExpr -> + loopElems [ elseExpr ] (fun elseExpr -> loopElems elems (cont << ``;`` (``if then else`` info thenExpr elseExpr)))) + + | SynExpr.Match(dbg, expr, clauses, m, trivia) :: elems -> + loopMatchClauses [] clauses (fun clauses -> loopElems elems (cont << ``;`` (``match`` (dbg, expr, m, trivia) clauses))) + | SynExpr.MatchBang(dbg, expr, clauses, m, trivia) :: elems -> + loopMatchClauses [] clauses (fun clauses -> loopElems elems (cont << ``;`` (``match!`` (dbg, expr, m, trivia) clauses))) + + | elem :: elems -> loopElems elems (cont << ``;`` (``yield`` elem)) + + and loopMatchClauses acc clauses cont = + match clauses with + | [] -> cont (List.rev acc) + | SynMatchClause(pat, whenExpr, resultExpr, m, dbg, trivia) :: clauses -> + loopElems [ resultExpr ] (fun resultExpr -> + loopMatchClauses (SynMatchClause(pat, whenExpr, resultExpr, m, dbg, trivia) :: acc) clauses cont) + + loopElems elems id diff --git a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs index c7eed9034b6..c739231a641 100644 --- a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs @@ -12,6 +12,7 @@ open FSharp.Compiler.Features open FSharp.Compiler.NameResolution open FSharp.Compiler.PatternMatchCompilation open FSharp.Compiler.Syntax +open FSharp.Compiler.SyntaxTrivia open FSharp.Compiler.Text open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeOps @@ -363,6 +364,20 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT | SynExpr.YieldOrReturnFrom(flags = (isYield, _); expr = synYieldExpr; trivia = { YieldOrReturnFromKeyword = m }) -> let env = { env with eIsControlFlow = false } + + let synYieldExpr = + match synYieldExpr with + | SynExpr.IndexRange _ -> + checkLanguageFeatureAndRecover + g.langVersion + LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + synYieldExpr.Range + + match RewriteRangeExpr synYieldExpr with + | Some rewrittenExpr -> rewrittenExpr + | None -> synYieldExpr + | _ -> synYieldExpr + let resultExpr, genExprTy, tpenv = TcExprOfUnknownType cenv env tpenv synYieldExpr if not isYield then @@ -388,6 +403,19 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT if not isYield then errorR (Error(FSComp.SR.tcSeqResultsUseYield (), m)) + let synYieldExpr = + match synYieldExpr with + | SynExpr.IndexRange _ -> + checkLanguageFeatureAndRecover + cenv.g.langVersion + LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + synYieldExpr.Range + + match RewriteRangeExpr synYieldExpr with + | Some rewrittenExpr -> rewrittenExpr + | None -> synYieldExpr + | _ -> synYieldExpr + UnifyTypes cenv env synYieldExpr.Range genOuterTy (mkSeqTy cenv.g genResultTy) let resultExpr, tpenv = TcExprFlex cenv flex true genResultTy env tpenv synYieldExpr @@ -449,6 +477,10 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT let delayedExpr = mkSeqDelayedExpr coreExpr.Range coreExpr delayedExpr, tpenv +let private TcMixedSequencesWithRanges cenv env tpenv overallTy elems m = + let transformedBody = insertImplicitYieldsAndYieldBangs elems m + TcSequenceExpression cenv env tpenv transformedBody overallTy m + let TcSequenceExpressionEntry (cenv: TcFileState) env (overallTy: OverallTy) tpenv (hasBuilder, comp) m = match RewriteRangeExpr comp with | Some replacementExpr -> TcExpr cenv overallTy env tpenv replacementExpr @@ -460,10 +492,45 @@ let TcSequenceExpressionEntry (cenv: TcFileState) env (overallTy: OverallTy) tpe match comp with | SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression -> - errorR (Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression (), m)) - | _ -> () - - if not hasBuilder && not cenv.g.compilingFSharpCore then - error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m)) - - TcSequenceExpression cenv env tpenv comp overallTy m + error (Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression (), m)) + | SimpleSemicolonSequence cenv false elems when hasBuilder -> + let containsRanges = + elems + |> List.exists (function + | SynExpr.IndexRange _ -> true + | _ -> false) + + if + containsRanges + && cenv.g.langVersion.SupportsFeature LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + then + TcMixedSequencesWithRanges cenv env tpenv overallTy elems m + else + // Check if ranges are present but feature is disabled + if containsRanges then + // Report language feature error for each range expression in a sequence + let reportRangeExpressionsNotSupported expr = + let rec loop exprs = + match exprs with + | [] -> () + | SynExpr.IndexRange(_, _, _, _, _, m) :: exprs -> + checkLanguageFeatureAndRecover + cenv.g.langVersion + LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions + m + + loop exprs + | SynExpr.Sequential(_, true, e1, e2, _, _) :: exprs -> loop (e1 :: e2 :: exprs) + | _ :: exprs -> loop exprs + + loop [ expr ] + + reportRangeExpressionsNotSupported comp + + // No ranges, use regular handling + TcSequenceExpression cenv env tpenv comp overallTy m + | _ -> + if not hasBuilder && not cenv.g.compilingFSharpCore then + error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m)) + + TcSequenceExpression cenv env tpenv comp overallTy m diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 1f2dc3cfb3c..b3a53e9bd24 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1802,6 +1802,7 @@ featureSupportWarnWhenUnitPassedToObjArg,"Warn when unit is passed to a member a featureUseBangBindingValueDiscard,"Allows use! _ = ... in computation expressions" featureBetterAnonymousRecordParsing,"Support for better anonymous record parsing" featureScopedNowarn,"Support for scoped enabling / disabling of warnings by #warn and #nowarn directives, also inside modules" +featureAllowMixedRangesAndValuesInSeqExpressions,"Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }}" featureAllowLetOrUseBangTypeAnnotationWithoutParens,"Allow let! and use! type annotations without requiring parentheses" 3874,lexWarnDirectiveMustBeFirst,"#nowarn/#warnon directives must appear as the first non-whitespace characters on a line" 3875,lexWarnDirectiveMustHaveArgs,"Warn directives must have warning number(s) as argument(s)" diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 9e57e5b96af..16649dec877 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -102,6 +102,7 @@ type LanguageFeature = | UseBangBindingValueDiscard | BetterAnonymousRecordParsing | ScopedNowarn + | AllowMixedRangesAndValuesInSeqExpressions | AllowTypedLetUseAndBang | ReturnFromFinal @@ -243,6 +244,7 @@ type LanguageVersion(versionText) = // F# preview (still preview in 10.0) LanguageFeature.FromEndSlicing, previewVersion // Unfinished features --- needs work + LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions, previewVersion ] static let defaultLanguageVersion = LanguageVersion("default") @@ -410,6 +412,7 @@ type LanguageVersion(versionText) = | LanguageFeature.UseBangBindingValueDiscard -> FSComp.SR.featureUseBangBindingValueDiscard () | LanguageFeature.BetterAnonymousRecordParsing -> FSComp.SR.featureBetterAnonymousRecordParsing () | LanguageFeature.ScopedNowarn -> FSComp.SR.featureScopedNowarn () + | LanguageFeature.AllowMixedRangesAndValuesInSeqExpressions -> FSComp.SR.featureAllowMixedRangesAndValuesInSeqExpressions () | LanguageFeature.AllowTypedLetUseAndBang -> FSComp.SR.featureAllowLetOrUseBangTypeAnnotationWithoutParens () | LanguageFeature.ReturnFromFinal -> FSComp.SR.featureReturnFromFinal () diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index 2e123eb1593..781632a1d28 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -93,6 +93,7 @@ type LanguageFeature = | UseBangBindingValueDiscard | BetterAnonymousRecordParsing | ScopedNowarn + | AllowMixedRangesAndValuesInSeqExpressions | AllowTypedLetUseAndBang | ReturnFromFinal diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 7333400397b..99a3f90ad51 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index ea6271cfbcb..3adb52d50a5 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 6abcce332e0..deeda11111a 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 4eb06dccb14..1fcf9a26dc5 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 4e48e1db287..26d77b6864d 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 295256c5cf4..ea7ddc5bb90 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 7ab04d5a12a..de8007ebed5 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index b31f4083071..e58c73e5f12 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 3e544e2f90c..d5824ed92da 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 75f9c8dadc7..09b261d5453 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 66166fd9023..23be3ec10ff 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 50981ab1e98..d01f0d84a39 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index aa2c95dbd4b..230bbcc6c82 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -292,6 +292,11 @@ Allow let! and use! type annotations without requiring parentheses + + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + Allow mixed ranges and values in sequence expressions, e.g. seq {{ 1..10; 20 }} + + Allow object expressions without overrides Allow object expressions without overrides diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index da13333f878..3ff071526bb 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -235,6 +235,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/E_SequenceExpressions02.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/E_SequenceExpressions02.fs new file mode 100644 index 00000000000..79003c6dcf4 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/E_SequenceExpressions02.fs @@ -0,0 +1,34 @@ +module MixedRangeVersionTest + +let a: int list = [ yield 1..10 ] +let a1: int list = [ yield! 1..10 ] + +let b: int list = [ yield [1..10] ] +let b: int list = [ yield! [1..10] ] + +let c: int seq = seq { yield seq { 1..10 } } +let c1: int seq = seq { yield! seq { 1..10 } } + +let d: int list = [ if true then yield 1 else yield 1..10] +let d1: int list = [ if true then yield 1 else yield! 1..10] +let d2: int list = [ if true then yield 1..10] +let d3: int list = [ if true then yield! 1..10] + +let e: int list = [if true then yield 1 else yield [1..10]] +let e1: int list = [if true then yield 1 else yield! [1..10]] +let e2 : int list = [if true then yield [1..10]] +let e3 : int list = [if true then yield! [1..10]] + +let g: int seq = seq { if true then yield 1 else yield seq { 1..10 } } +let g1: int seq = seq { if true then yield 1 else yield! seq { 1..10 } } +let g2: int seq = seq { if true then yield seq { 1..10 } } +let g3: int seq = seq { if true then yield! seq { 1..10 } } + +let h: int list = [ match true with | true -> yield 1 | false -> yield 1..10] +let h1: int list = [ match true with | true -> yield 1 | false -> yield! 1..10] + +let i: int list = [ match true with | true -> yield 1 | false -> yield [1..10]] +let i1: int list = [ match true with | true -> yield 1 | false -> yield! [1..10]] + +let j: int seq = seq { match true with | true -> yield 1 | false -> yield seq { 1..10 } } +let j1: int seq = seq { match true with | true -> yield 1 | false -> yield! seq { 1..10 } } \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/MixedSequenceExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/MixedSequenceExpressionTests.fs new file mode 100644 index 00000000000..f617b4f90ef --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/MixedSequenceExpressionTests.fs @@ -0,0 +1,754 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Language + +open FSharp.Test +open Xunit +open FSharp.Test.Compiler + +module MixedSequenceExpressionTests = + + let verifyCompile compilation = + compilation + |> asExe + |> withOptions ["--nowarn:988"] + |> compile + + let verifyCompileAndRun compilation = + compilation + |> asExe + |> withOptions ["--nowarn:988"] + |> compileAndRun + + // SOURCE=SequenceExpressions00.fs # SequenceExpressions00.fs + [] + let ``Version 9: Mixed ranges and values without preview should fail (baseline comparison)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 8, Col 15, Line 8, Col 20, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 8, Col 15, Line 8, Col 20, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 9, Col 14, Line 9, Col 19, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 9, Col 14, Line 9, Col 19, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 10, Col 15, Line 10, Col 20, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 10, Col 15, Line 10, Col 20, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions00.fs # SequenceExpressions00.fs + [] + let ``Preview: Mixed ranges and values compile in all collection forms (baseline comparison)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldSucceed + + // SOURCE=SequenceExpressions02a.fs # SequenceExpressions02a.fs + [] + let ``Version 9: List literal mixing a single ascending range with a leading value (02a)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 17, Line 3, Col 22, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 3, Col 17, Line 3, Col 22, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions02a.fs # SequenceExpressions02a.fs + [] + let ``Preview: List literal mixing a single ascending range with a leading value (02a)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions02b.fs # SequenceExpressions02b.fs + [] + let ``Version 9: List literal mixing a range in the middle of values (02b)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 17, Line 3, Col 22, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 3, Col 17, Line 3, Col 22, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions02b.fs # SequenceExpressions02b.fs + [] + let ``Preview: List literal mixing a range in the middle of values (02b)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions02c.fs # SequenceExpressions02c.fs + [] + let ``Version 9: List literal with multiple ranges and trailing value (02c)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 13, Line 3, Col 17, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 3, Col 19, Line 3, Col 23, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 3, Col 13, Line 3, Col 17, "Incomplete expression or invalid use of indexer syntax") + (Error 751, Line 3, Col 19, Line 3, Col 23, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions02c.fs # SequenceExpressions02c.fs + [] + let ``Preview: List literal with multiple ranges and trailing value (02c)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions02d.fs # SequenceExpressions02d.fs + [] + let ``Version 9: List literal with stepped range between values (02d)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 16, Line 3, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 3, Col 16, Line 3, Col 24, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions02d.fs # SequenceExpressions02d.fs + [] + let ``Preview: List literal with stepped range between values (02d)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions03.fs # SequenceExpressions03.fs + [] + let ``Preview: seq builder: ranges as splices are accepted (03)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions03.fs # SequenceExpressions03.fs + [] + let ``Version 9: seq builder: ranges without preview should fail (03)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 19, Line 3, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 3, Col 19, Line 3, Col 24, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 7, Col 19, Line 7, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 7, Col 19, Line 7, Col 24, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 11, Col 15, Line 11, Col 19, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 11, Col 21, Line 11, Col 25, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 11, Col 15, Line 11, Col 19, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 11, Col 21, Line 11, Col 25, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 15, Col 18, Line 15, Col 26, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 15, Col 18, Line 15, Col 26, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 19, Col 18, Line 19, Col 22, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 19, Col 18, Line 19, Col 22, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 23, Col 18, Line 23, Col 22, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 23, Col 18, Line 23, Col 22, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions04.fs # SequenceExpressions04.fs + [] + let ``Preview: seq builder: ranges in branches etc. accepted (04)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions04.fs # SequenceExpressions04.fs + [] + let ``Version 9: seq builder: ranges without preview should fail (04)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 19, Line 3, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 3, Col 19, Line 3, Col 24, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 7, Col 23, Line 7, Col 27, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 7, Col 29, Line 7, Col 35, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 7, Col 23, Line 7, Col 27, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 7, Col 29, Line 7, Col 35, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 11, Col 22, Line 11, Col 30, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 11, Col 22, Line 11, Col 30, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions05.fs # SequenceExpressions05.fs + [] + let ``Preview: seq builder: mixing ranges with values compiles and runs (05)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions05.fs # SequenceExpressions05.fs + [] + let ``Version 9: seq builder: mixing ranges with values requires preview (05)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 19, Line 3, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 3, Col 19, Line 3, Col 24, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 7, Col 22, Line 7, Col 30, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 7, Col 22, Line 7, Col 30, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions06.fs # SequenceExpressions06.fs + [] + let ``Preview: Type inference across list/array/seq with mixed ranges (06)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions06.fs # SequenceExpressions06.fs + [] + let ``Version 9: Type inference with mixed ranges requires preview (06)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 24, Line 3, Col 28, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 3, Col 24, Line 3, Col 28, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 4, Col 26, Line 4, Col 30, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 4, Col 26, Line 4, Col 30, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 5, Col 29, Line 5, Col 33, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 5, Col 29, Line 5, Col 33, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 8, Col 6, Line 8, Col 19, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 8, Col 6, Line 8, Col 19, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions07.fs # SequenceExpressions07.fs + [] + let ``Preview: Custom CE builder splices built-in ranges via YieldFrom (07)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + + // SOURCE=SequenceExpressions07.fs # SequenceExpressions07.fs + [] + let ``Version 9: Custom CE with mixed ranges requires preview (07)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 13, Col 25, Line 13, Col 30, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 13, Col 25, Line 13, Col 30, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 17, Col 21, Line 17, Col 25, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 17, Col 27, Line 17, Col 31, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 17, Col 21, Line 17, Col 25, "Incomplete expression or invalid use of indexer syntax") + (Error 751, Line 17, Col 27, Line 17, Col 31, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 21, Col 24, Line 21, Col 32, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 21, Col 24, Line 21, Col 32, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions08.fs # SequenceExpressions08.fs + [] + let ``Version 9: Equivalence examples require preview (08)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 7, Col 15, Line 7, Col 20, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 7, Col 15, Line 7, Col 20, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 8, Col 14, Line 8, Col 19, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 8, Col 14, Line 8, Col 19, "Incomplete expression or invalid use of indexer syntax") + (Error 3350, Line 9, Col 15, Line 9, Col 20, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 9, Col 15, Line 9, Col 20, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions08.fs # SequenceExpressions08.fs + [] + let ``Preview: Equivalence: direct ranges equal explicit yield! in seq/list/array (08)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions09.fs # SequenceExpressions09.fs + [] + let ``Preview: Non-interference: custom (..) operator is not treated as range (09)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions09.fs # SequenceExpressions09.fs + [] + let ``Version 9: Non-interference: custom (..) operator is not treated as range (09)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions10.fs # SequenceExpressions10.fs + [] + let ``Version 9: Mixed ranges and values across seq/list/array blocks require preview (10)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 5, Col 5, Line 5, Col 9, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 7, Col 5, Line 7, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 9, Col 5, Line 9, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 5, Col 5, Line 5, Col 9, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 7, Col 5, Line 7, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 9, Col 5, Line 9, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 14, Col 5, Line 14, Col 9, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 16, Col 5, Line 16, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 18, Col 5, Line 18, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 14, Col 5, Line 14, Col 9, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 16, Col 5, Line 16, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 18, Col 5, Line 18, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 22, Col 5, Line 22, Col 9, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 24, Col 5, Line 24, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 26, Col 5, Line 26, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 22, Col 5, Line 22, Col 9, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 24, Col 5, Line 24, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 26, Col 5, Line 26, Col 11, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions10.fs # SequenceExpressions10.fs + [] + let ``Preview: Mixed ranges and values across seq/list/array blocks compile and match explicit yield! (10)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions11.fs # SequenceExpressions11.fs + [] + let ``Version 9: Stepped ranges mixed with values require preview (11)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 5, Col 5, Line 5, Col 13, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 7, Col 5, Line 7, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 9, Col 5, Line 9, Col 14, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 5, Col 5, Line 5, Col 13, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 7, Col 5, Line 7, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 9, Col 5, Line 9, Col 14, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 14, Col 5, Line 14, Col 13, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 16, Col 5, Line 16, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 18, Col 5, Line 18, Col 14, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 14, Col 5, Line 14, Col 13, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 16, Col 5, Line 16, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 18, Col 5, Line 18, Col 14, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 22, Col 5, Line 22, Col 13, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 24, Col 5, Line 24, Col 11, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 26, Col 5, Line 26, Col 14, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 22, Col 5, Line 22, Col 13, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 24, Col 5, Line 24, Col 11, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 26, Col 5, Line 26, Col 14, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions11.fs # SequenceExpressions11.fs + [] + let ``Preview: Stepped ranges mixed with values compile and match explicit yield! (11)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions12.fs # SequenceExpressions12.fs + [] + let ``Version 9: Single direct range in list/seq/array requires preview (12)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 18, Line 3, Col 23, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + // SOURCE=SequenceExpressions12.fs # SequenceExpressions12.fs + [] + let ``Preview: Single direct range in list/seq/array equals explicit yield! (12)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions13.fs # SequenceExpressions13.fs + [] + let ``Version 9: Interleaving ranges and values requires preview (13)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 18, Line 3, Col 23, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 5, Col 38, Line 5, Col 44, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 9, Col 11, Line 9, Col 16, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 9, Col 11, Line 9, Col 16, "Incomplete expression or invalid use of indexer syntax"); + (Error 3350, Line 9, Col 29, Line 9, Col 35, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 10, Col 22, Line 10, Col 27, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 10, Col 40, Line 10, Col 46, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 11, Col 19, Line 11, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 11, Col 37, Line 11, Col 43, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + // SOURCE=SequenceExpressions13.fs # SequenceExpressions13.fs + [] + let ``Preview: Interleaving ranges and values equals explicit forms (13)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions14.fs # SequenceExpressions14.fs + [] + let ``Version 9: No ranges: existing yield/yield! behavior unchanged (14)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions13.fs # SequenceExpressions13.fs + [] + let ``Preview: No ranges: existing yield/yield! behavior unchanged (14)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=E_SequenceExpressions02.fs # E_SequenceExpressions02.fs + [] + let ``Version 9: Invalid 'yield range' vs 'yield! range' typing diagnostics (E_02)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 27, Line 3, Col 32, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 1, Line 3, Col 27, Line 3, Col 32, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 3, Col 27, Line 3, Col 32, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 3350, Line 4, Col 29, Line 4, Col 34, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 1, Line 6, Col 27, Line 6, Col 34, "This expression was expected to have type + 'int' +but here has type + ''a list' "); + (Error 1, Line 9, Col 30, Line 9, Col 43, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 9, Col 30, Line 9, Col 43, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 3350, Line 12, Col 53, Line 12, Col 58, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 1, Line 12, Col 53, Line 12, Col 58, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 12, Col 53, Line 12, Col 58, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 3350, Line 13, Col 55, Line 13, Col 60, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 14, Col 41, Line 14, Col 46, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 1, Line 14, Col 41, Line 14, Col 46, "This expression was expected to have type +'int' +but here has type +''a seq' "); + (Error 1, Line 14, Col 41, Line 14, Col 46, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 3350, Line 15, Col 42, Line 15, Col 47, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 1, Line 17, Col 53, Line 17, Col 60, "This expression was expected to have type + 'int' +but here has type + ''a list' "); + (Error 1, Line 19, Col 42, Line 19, Col 49, "This expression was expected to have type + 'int' +but here has type + ''a list' "); + (Error 1, Line 22, Col 56, Line 22, Col 69, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 22, Col 56, Line 22, Col 69, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 24, Col 44, Line 24, Col 57, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 24, Col 44, Line 24, Col 57, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 3350, Line 27, Col 72, Line 27, Col 77, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 1, Line 27, Col 72, Line 27, Col 77, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 27, Col 72, Line 27, Col 77, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 3350, Line 28, Col 74, Line 28, Col 79, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 1, Line 30, Col 72, Line 30, Col 79, "This expression was expected to have type + 'int' +but here has type + ''a list' "); + (Error 1, Line 33, Col 75, Line 33, Col 88, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 33, Col 75, Line 33, Col 88, "This expression was expected to have type + 'int' +but here has type + 'int seq' ") + ] + + // SOURCE=E_SequenceExpressions02.fs # E_SequenceExpressions02.fs + [] + let ``Preview: Invalid 'yield range' vs 'yield! range' typing diagnostics (E_02)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 3, Col 27, Line 3, Col 32, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 3, Col 27, Line 3, Col 32, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 6, Col 27, Line 6, Col 34, "This expression was expected to have type + 'int' +but here has type + ''a list' "); + (Error 1, Line 9, Col 30, Line 9, Col 43, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 9, Col 30, Line 9, Col 43, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 12, Col 53, Line 12, Col 58, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 12, Col 53, Line 12, Col 58, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 14, Col 41, Line 14, Col 46, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 14, Col 41, Line 14, Col 46, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 17, Col 53, Line 17, Col 60, "This expression was expected to have type + 'int' +but here has type + ''a list' ") + (Error 1, Line 19, Col 42, Line 19, Col 49, "This expression was expected to have type + 'int' +but here has type + ''a list' "); + (Error 1, Line 22, Col 56, Line 22, Col 69, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 22, Col 56, Line 22, Col 69, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 24, Col 44, Line 24, Col 57, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 24, Col 44, Line 24, Col 57, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 27, Col 72, Line 27, Col 77, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 27, Col 72, Line 27, Col 77, "This expression was expected to have type + 'int' +but here has type + 'int seq' "); + (Error 1, Line 30, Col 72, Line 30, Col 79, "This expression was expected to have type + 'int' +but here has type + ''a list' "); + (Error 1, Line 33, Col 75, Line 33, Col 88, "This expression was expected to have type + 'int' +but here has type + ''a seq' "); + (Error 1, Line 33, Col 75, Line 33, Col 88, "This expression was expected to have type + 'int' +but here has type + 'int seq' ") + ] + + // SOURCE=SequenceExpressions15.fs # SequenceExpressions15.fs + [] + let ``Preview: yield vs yield! ranges baseline (15)`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions15.fs # SequenceExpressions15.fs + [] + let ``Version 9: yield vs yield! baseline compilation behavior (15)`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 19, Line 3, Col 23, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 4, Col 23, Line 4, Col 27, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 5, Col 20, Line 5, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 9, Col 29, Line 9, Col 33, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 10, Col 32, Line 10, Col 36, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 3350, Line 11, Col 31, Line 11, Col 35, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + // SOURCE=SequenceExpressions16.fs # SequenceExpressions16.fs + [] + let ``Preview: SequenceExpressions16 fs`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions16.fs # SequenceExpressions16.fs + [] + let ``Version 9: SequenceExpressions16 fs`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 28, Line 3, Col 33, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 8, Col 54, Line 8, Col 59, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 9, Col 42, Line 9, Col 47, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 17, Col 73, Line 17, Col 78, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + // SOURCE=SequenceExpressions17.fs # SequenceExpressions17.fs + [] + let ``Preview: SequenceExpressions17 fs`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions17.fs # SequenceExpressions17.fs + [] + let ``Version 9: SequenceExpressions17 fs`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 15, Col 30, Line 15, Col 35, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 18, Col 34, Line 18, Col 39, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 41, Col 25, Line 41, Col 30, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 49, Col 31, Line 49, Col 36, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + ] + + // SOURCE=SequenceExpressions18.fs # SequenceExpressions18.fs + [] + let ``Preview: char ranges mixed with values compile and run`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions18.fs # SequenceExpressions18.fs + [] + let ``Version 9: char ranges mixed with values require preview`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 18, Line 3, Col 26, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 3, Col 18, Line 3, Col 26, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions19.fs # SequenceExpressions19.fs + [] + let ``Preview: bigint ranges mixed with values compile and run`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions19.fs # SequenceExpressions19.fs + [] + let ``Version 9: bigint ranges mixed with values require preview`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 4, Col 14, Line 4, Col 24, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater.") + (Error 751, Line 4, Col 14, Line 4, Col 24, "Incomplete expression or invalid use of indexer syntax") + ] + + // SOURCE=SequenceExpressions20.fs # SequenceExpressions20.fs + [] + let ``Preview: empty and singleton ranges preserve order`` compilation = + compilation + |> withLangVersionPreview + |> verifyCompileAndRun + |> shouldSucceed + + // SOURCE=SequenceExpressions20.fs # SequenceExpressions20.fs + [] + let ``Version 9: empty and singleton ranges inside list literals require preview`` compilation = + compilation + |> withLangVersion90 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Error 3350, Line 3, Col 17, Line 3, Col 21, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 3, Col 23, Line 3, Col 27, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 3350, Line 3, Col 29, Line 3, Col 33, "Feature 'Allow mixed ranges and values in sequence expressions, e.g. seq { 1..10; 20 }' is not available in F# 9.0. Please use language version 'PREVIEW' or greater."); + (Error 751, Line 3, Col 17, Line 3, Col 21, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 3, Col 23, Line 3, Col 27, "Incomplete expression or invalid use of indexer syntax"); + (Error 751, Line 3, Col 29, Line 3, Col 33, "Incomplete expression or invalid use of indexer syntax") + ] diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions00.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions00.fs new file mode 100644 index 00000000000..ce3fb1443d6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions00.fs @@ -0,0 +1,10 @@ + +module MixedRangeVersionTest + +let a = seq { yield! seq { 1..10 }; 19 } +let b = [-3; yield! [1..10]] +let c = [|-3; yield! [|1..10|]; 19|] + +let d = seq { 1..10; 19 } +let e = [-3; 1..10] +let f = [|-3; 1..10; 19|] diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02.fs new file mode 100644 index 00000000000..98576ac716c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02.fs @@ -0,0 +1,11 @@ +module MixedRangeListTests + +// This aggregated file is now split into SequenceExpressions02a.fs..02d.fs. +// Keeping a trivial test here to maintain references where needed. + +let test = [0] +let expected = [0] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02a.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02a.fs new file mode 100644 index 00000000000..a0a66b83526 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02a.fs @@ -0,0 +1,8 @@ +module MixedRangeListTest01 + +let test = [-3; 1..10] +let expected = [-3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02b.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02b.fs new file mode 100644 index 00000000000..98384aaed9d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02b.fs @@ -0,0 +1,8 @@ +module MixedRangeListTest02 + +let test = [-3; 1..10; 19] +let expected = [-3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 19] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02c.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02c.fs new file mode 100644 index 00000000000..89fca24084a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02c.fs @@ -0,0 +1,8 @@ +module MixedRangeListTest03 + +let test = [1..3; 5..7; 10] +let expected = [1; 2; 3; 5; 6; 7; 10] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02d.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02d.fs new file mode 100644 index 00000000000..bd95c934f10 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions02d.fs @@ -0,0 +1,8 @@ +module MixedRangeListTest04 + +let test = [0; 2..2..10; 15] +let expected = [0; 2; 4; 6; 8; 10; 15] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions03.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions03.fs new file mode 100644 index 00000000000..f835c06052f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions03.fs @@ -0,0 +1,27 @@ +module MixedRangeArrayTests + +let test1 = [|-3; 1..10|] +let expected1 = [|-3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|] +if test1 <> expected1 then failwith $"test1 failed: got {test1}" + +let test2 = [|-3; 1..10; 19|] +let expected2 = [|-3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 19|] +if test2 <> expected2 then failwith $"test2 failed: got {test2}" + +let test3 = [|1..3; 5..7; 10|] +let expected3 = [|1; 2; 3; 5; 6; 7; 10|] +if test3 <> expected3 then failwith $"test3 failed: got {test3}" + +let test4 = [|0; 2..2..10; 15|] +let expected4 = [|0; 2; 4; 6; 8; 10; 15|] +if test4 <> expected4 then failwith $"test4 failed: got {test4}" + +let test5 = [|1; 5..4; 10|] +let expected5 = [|1; 10|] +if test5 <> expected5 then failwith $"test5 failed: got {test5}" + +let test6 = [|0; 5..5; 10|] +let expected6 = [|0; 5; 10|] +if test6 <> expected6 then failwith $"test6 failed: got {test6}" + +printfn "All array tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions04.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions04.fs new file mode 100644 index 00000000000..46b6ccaef15 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions04.fs @@ -0,0 +1,25 @@ +module MixedRangeSeqTests + +let test1 = seq { 1..10; 19 } +let expected1 = seq { 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 19 } +if List.ofSeq test1 <> List.ofSeq expected1 then failwith $"test1 failed got {test1}" + +let test2 = seq { -3; 1..5; 10..12 } +let expected2 = seq { -3; 1; 2; 3; 4; 5; 10; 11; 12 } +if List.ofSeq test2 <> List.ofSeq expected2 then failwith $"test2 failed got {test2}" + +let test3 = seq { 0; 2..2..10; 15 } +let expected3 = seq { 0; 2; 4; 6; 8; 10; 15 } +if List.ofSeq test3 <> List.ofSeq expected3 then failwith $"test3 failed got {test3}" + +let test4 = seq { + yield 1 + yield! seq { 2..5 } + yield 10 + yield! seq { 15..2..20 } +} + +let expected4 = seq { 1; 2; 3; 4; 5; 10; 15; 17; 19 } +if List.ofSeq test4 <> List.ofSeq expected4 then failwith $"test4 failed got {test4}" + +printfn "All sequence tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions05.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions05.fs new file mode 100644 index 00000000000..0a7e119714b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions05.fs @@ -0,0 +1,21 @@ +module MixedRangeSeqTests + +let test1 = seq { 1..10; 19 } +let expected1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 19] +if List.ofSeq test1 <> expected1 then failwith $"test1 failed" + +let test2 = seq { 0; 2..2..10; 15 } +let expected2 = [|0; 2; 4; 6; 8; 10; 15|] +if Array.ofSeq test2 <> expected2 then failwith $"test2 failed" + +let test3 = seq { + yield 1 + yield! [2..5] + yield 10 + yield! [| 15..2..20 |] +} + +let expected3 = [1; 2; 3; 4; 5; 10; 15; 17; 19] +if List.ofSeq test3 <> expected3 then failwith $"test3 failed" + +printfn "All sequence tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions06.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions06.fs new file mode 100644 index 00000000000..8a9bce2ed58 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions06.fs @@ -0,0 +1,18 @@ +module TypeInferenceTests + +let test1: int list = [1..5; 10] +let test2: int array = [|1..5; 10|] +let test3: seq = seq { 1..5; 10 } + +let inline mixedRange start finish extra = + [start..finish; extra] + +let test4 = mixedRange 1 5 10 +let test5 = mixedRange 1.0 5.0 10.0 +let test6 = mixedRange 'a' 'e' 'z' + +if test4 <> [1; 2; 3; 4; 5; 10] then failwith "int range failed" +if test5 <> [1.0; 2.0; 3.0; 4.0; 5.0; 10.0] then failwith "float range failed" +if test6 <> ['a'; 'b'; 'c'; 'd'; 'e'; 'z'] then failwith "char range failed" + +printfn "Type inference tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions07.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions07.fs new file mode 100644 index 00000000000..7989a0ace81 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions07.fs @@ -0,0 +1,25 @@ +module CustomCEWithRanges + +type ArrayBuilder() = + member _.Yield(x) = [| x |] + member _.YieldFrom(xs: seq<_>) = Seq.toArray xs + member _.Zero() = [||] + member _.Combine(a: int array, b: unit -> int array) = Array.append a (b()) + member _.Delay(f) = f + member _.Run(f) = f() + +let array = ArrayBuilder() + +let test1 = array { -3; 1..10; 19 } +let expected1 = [| -3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 19 |] +if test1 <> expected1 then failwith $"test1 failed: got {test1}" + +let test2 = array { 1..3; 5..7; 10 } +let expected2 = [| 1; 2; 3; 5; 6; 7; 10 |] +if test2 <> expected2 then failwith $"test2 failed: got {test2}" + +let test3 = array { 0; 2..2..10; 15 } +let expected3 = [| 0; 2; 4; 6; 8; 10; 15 |] +if test3 <> expected3 then failwith $"test3 failed: got {test3}" + +printfn "Custom CE with ranges tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions08.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions08.fs new file mode 100644 index 00000000000..6090432cf8c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions08.fs @@ -0,0 +1,17 @@ +module MixedRangeVersionTest + +let a = seq { yield! seq { 1..10 }; 19 } +let b = [-3; yield! [1..10]] +let c = [|-3; yield! [|1..10|]; 19|] + +let d = seq { 1..10; 19 } +let e = [-3; 1..10] +let f = [|-3; 1..10; 19|] + +if List.ofSeq a <> List.ofSeq d then failwithf $"a = d failed got {List.ofSeq a}" + +if b <> e then failwithf $"b = e failed got {b}" + +if c <> f then failwithf $"c = f failed got {c}" + +printfn "All sequence tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions09.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions09.fs new file mode 100644 index 00000000000..8c183dd8428 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions09.fs @@ -0,0 +1,30 @@ +module OverridingRangeOperator + +open System.Collections +open System.Collections.Generic + +type X(elements: X list) = + member this.Elements = elements + + interface IEnumerable with + member this.GetEnumerator() = + (this.Elements :> IEnumerable).GetEnumerator() + + member this.GetEnumerator() : IEnumerator = + (this.Elements :> IEnumerable).GetEnumerator() + + static member Combine(x1: X, x2: X) = + X(x1.Elements @ x2.Elements) + +let (..) a b = seq { X.Combine(a,b) } + +let a = X([]) +let b = X([]) + +let whatIsThis = seq { a..b } + +let result1 = [ whatIsThis ;a ; b] +let result2 = [ yield! whatIsThis; a; b ] + +printfn $"As is: {result1}" +printfn $"Implicit yield! {result2}" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions10.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions10.fs new file mode 100644 index 00000000000..0434fd0a57b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions10.fs @@ -0,0 +1,63 @@ +module MixedRangeVersionTest + +let a = seq { + 0 + 1..5 + 10 + 11..15 + 20 + 21..25 +} + +let b = [ + 0 + 1..5 + 10 + 11..15 + 20 + 21..25 +] +let c = [| + 0 + 1..5 + 10 + 11..15 + 20 + 21..25 +|] + +let d = seq { + 0 + yield! [1..5] + 10 + yield! [11..15] + 20 + yield! [21..25] + +} + +let e = [ + 0 + yield! [1..5] + 10 + yield! [11..15] + 20 + yield! [21..25] +] + +let f = [| + 0 + yield! [1..5] + 10 + yield! [11..15] + 20 + yield! [21..25] +|] + +if List.ofSeq a <> List.ofSeq d then failwithf $"a = d failed got {List.ofSeq a}" + +if b <> e then failwithf $"b = e failed got {b}" + +if c <> f then failwithf $"c = f failed got {c}" + +printfn "All sequence tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions11.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions11.fs new file mode 100644 index 00000000000..b85c0e03565 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions11.fs @@ -0,0 +1,63 @@ +module MixedRangeVersionTest + +let a = seq { + 0 + 1..2..10 + 10 + 11..15 + 20 + 21..1..30 +} + +let b = [ + 0 + 1..2..10 + 10 + 11..15 + 20 + 21..1..30 +] +let c = [| + 0 + 1..2..10 + 10 + 11..15 + 20 + 21..1..30 +|] + +let d = seq { + 0 + yield! [1..2..10] + 10 + yield! [11..15] + 20 + yield! [21..1..30] + +} + +let e = [ + 0 + yield! [1..2..10] + 10 + yield! [11..15] + 20 + yield! [21..1..30] +] + +let f = [| + 0 + yield! [1..2..10] + 10 + yield! [11..15] + 20 + yield! [21..1..30] +|] + +if List.ofSeq a <> List.ofSeq d then failwithf $"a = d failed got {List.ofSeq a}" + +if b <> e then failwithf $"b = e failed got {b}" + +if c <> f then failwithf $"c = f failed got {c}" + +printfn "All sequence tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions12.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions12.fs new file mode 100644 index 00000000000..a3c010c5fbe --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions12.fs @@ -0,0 +1,17 @@ +module MixedRangeVersionTest + +let a = [ yield! 1..10 ] + +let b = [ yield! [1..10] ] + +let c = seq { yield! seq { 1..10 } } + +let d = [ 1..10 ] +let e = seq { 1..10 } +let f = [| 1..10 |] + +if a <> d then failwithf $"a = d failed got {a}" +if b <> List.ofSeq e then failwithf $"b = d failed got {b}" +if Array.ofSeq c <> f then failwithf $"f = d failed got {f}" + +printfn "All sequence tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions13.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions13.fs new file mode 100644 index 00000000000..e7e713f8a9c --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions13.fs @@ -0,0 +1,17 @@ +module MixedRangeVersionTest + +let a = [ yield! 1..10; 19; yield! [20..30] ] + +let b = [ yield! [1..10]; 19; yield! 20..30 ] + +let c = seq { yield! seq { 1..10 }; 19; yield! seq { 20..30 } } + +let d = [ 1..10; 19; yield! 20..30 ] +let e = seq { yield! 1..10; 19; yield! 20..30 } +let f = [| yield! 1..10; 19; yield! 20..30 |] + +if a <> d then failwithf $"a = d failed got {a}" +if b <> List.ofSeq e then failwithf $"b = d failed got {b}" +if Array.ofSeq c <> f then failwithf $"f = d failed got {f}" + +printfn "All sequence tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions14.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions14.fs new file mode 100644 index 00000000000..2995b7d4fbd --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions14.fs @@ -0,0 +1,16 @@ +module BackwardCompatTest + +let makeCustomAttributes() = + [| + if true then + yield "attr1" + yield! ["attr2"; "attr3"] + yield! ["attr4"] + |] + +let attrs = makeCustomAttributes() +let expected = [|"attr1"; "attr2"; "attr3"; "attr4"|] + +if attrs <> expected then failwithf $"attrs failed: got {attrs}" + +printfn "Backward compatibility test passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions15.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions15.fs new file mode 100644 index 00000000000..8b85e5dfc46 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions15.fs @@ -0,0 +1,22 @@ +module YieldVsYieldBang + +let a1 = [ yield! 1..5 ] +let a2 = seq { yield! 1..5 } +let a3 = [| yield! 1..5 |] + +// let b1: int list = [ yield 1..5 ] // Would give type error + +let c1: int list = [ yield! 1..5 ] +let c2: int seq = seq { yield! 1..5 } +let c3: int array = [| yield! 1..5 |] + +let expected = [1; 2; 3; 4; 5] + +if a1 <> expected then failwithf $"a1 failed: got {a1}" +if List.ofSeq a2 <> expected then failwithf $"a2 failed: got {List.ofSeq a2}" +if List.ofArray a3 <> expected then failwithf $"a3 failed: got {List.ofArray a3}" +if c1 <> expected then failwithf $"c1 failed: got {c1}" +if List.ofSeq c2 <> expected then failwithf $"c2 failed: got {List.ofSeq c2}" +if List.ofArray c3 <> expected then failwithf $"c3 failed: got {List.ofArray c3}" + +printfn "yield vs yield! tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions16.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions16.fs new file mode 100644 index 00000000000..98466908767 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions16.fs @@ -0,0 +1,39 @@ +module MixedRangeVersionTest + +let a: int list = [ yield! 1..10 ] +let a1: int list = [ yield! [1..10] ] + +let b: int seq = seq { yield! seq { 1..10 } } + +let c: int list = [ if true then yield 1 else yield! 1..10] +let c1: int list = [ if true then yield! 1..10] + +let d: int list = [if true then yield 1 else yield! [1..10]] +let d1 : int list = [if true then yield! [1..10]] + +let e: int seq = seq { if true then yield 1 else yield! seq { 1..10 } } +let e1: int seq = seq { if true then yield! seq { 1..10 } } + +let f: int list = [ match true with | true -> yield 1 | false -> yield! 1..10] + +let f1: int list = [ match true with | true -> yield 1 | false -> yield! [1..10]] + +let g: int seq = seq { match true with | true -> yield 1 | false -> yield! seq { 1..10 } } + +let expected = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] +let expectedOne = [1] + +if a <> expected then failwithf $"a failed: got {a}" +if a1 <> expected then failwithf $"a1 failed: got {a1}" +if List.ofSeq b <> expected then failwithf $"b failed: got {List.ofSeq b}" +if c <> expectedOne then failwithf $"c failed: got {c}" +if c1 <> expected then failwithf $"c1 failed: got {c1}" +if d <> expectedOne then failwithf $"d failed: got {d}" +if d1 <> expected then failwithf $"d1 failed: got {d1}" +if List.ofSeq e <> expectedOne then failwithf $"e failed: got {List.ofSeq e}" +if List.ofSeq e1 <> expected then failwithf $"e1 failed: got {List.ofSeq e1}" +if f <> expectedOne then failwithf $"f failed: got {f}" +if f1 <> expectedOne then failwithf $"f1 failed: got {f1}" +if List.ofSeq g <> expectedOne then failwithf $"g failed: got {List.ofSeq g}" + +printfn "yield vs yield! tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions17.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions17.fs new file mode 100644 index 00000000000..39fbaa196b8 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions17.fs @@ -0,0 +1,55 @@ +module MixedRangeVersionTest + +let f p q r = + [ + if p then + if q then 3 + if p then + if q then + if r then 3 + ] + +let f1 p q r = + [ + if p then + if q then yield! 1..10 + if p then + if q then + if r then yield! 1..10 + ] + +let f2 x (|P|_|) (|Q|_|) (|R|_|) = + [ + match x with + | P _ -> 3 + | _ -> () + + match x with + | P y -> + match y with + | Q z -> + match z with + | R -> 3 + | _ -> () + | _ -> () + | _ -> () + ] + +let f3 x (|P|_|) (|Q|_|) (|R|_|) = + [ + match x with + | P _ -> yield! 1..10 + | _ -> () + + match x with + | P y -> + match y with + | Q z -> + match z with + | R -> yield! 1..10 + | _ -> () + | _ -> () + | _ -> () + ] + +printfn "yield vs yield! tests passed!" \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions18.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions18.fs new file mode 100644 index 00000000000..c05b2893c6a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions18.fs @@ -0,0 +1,8 @@ +module CharRangesTest + +let test = seq { 'a'..'c'; 'Z' } |> Seq.toArray +let expected = [| 'a'; 'b'; 'c'; 'Z' |] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions19.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions19.fs new file mode 100644 index 00000000000..4e7863d73fc --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions19.fs @@ -0,0 +1,9 @@ +module BigIntRangesTest +open System.Numerics + +let test = [ 0I..2I..6I; 10I ] +let expected = [0I;2I;4I;6I;10I] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions20.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions20.fs new file mode 100644 index 00000000000..928797117ea --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressions/SequenceExpressions20.fs @@ -0,0 +1,8 @@ +module EmptyRangesTest + +let test = [ 0; 1..0; 2..2; 3..1; 4 ] +let expected = [0;2;4] + +if test <> expected then failwith $"test failed: got {test}" + +printfn "All list tests passed!" diff --git a/tests/fsharp/typecheck/sigs/version46/neg24.bsl b/tests/fsharp/typecheck/sigs/version46/neg24.bsl index 97aa11a5d26..eec18e70ccd 100644 --- a/tests/fsharp/typecheck/sigs/version46/neg24.bsl +++ b/tests/fsharp/typecheck/sigs/version46/neg24.bsl @@ -13,8 +13,6 @@ neg24.fs(16,14,16,35): typecheck error FS0035: This construct is deprecated: Thi neg24.fs(17,18,17,45): typecheck error FS0739: Invalid object, sequence or record expression -neg24.fs(17,20,17,43): typecheck error FS0793: This construct is ambiguous as part of a sequence expression. Nested expressions may be written using 'let _ = (...)' and nested sequences using 'yield! seq {... }'. - neg24.fs(53,24,53,30): typecheck error FS0816: One or more of the overloads of this method has curried arguments. Consider redesigning these members to take arguments in tupled form. neg24.fs(55,31,55,37): typecheck error FS0816: One or more of the overloads of this method has curried arguments. Consider redesigning these members to take arguments in tupled form.