Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 20 additions & 57 deletions src/Compiler/Checking/Expressions/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ exception FunctionExpected of DisplayEnv * TType * range

exception NotAFunction of DisplayEnv * TType * range * range

exception NotAFunctionButIndexer of DisplayEnv * TType * string option * range * range * bool
exception NotAFunctionButIndexer of DisplayEnv * TType * string option * range * range

exception Recursion of DisplayEnv * Ident * TType * TType * range

Expand Down Expand Up @@ -4115,13 +4115,10 @@ let GetInstanceMemberThisVariable (vspec: Val, expr) =
None

/// c.atomicLeftMethExpr[idx] and atomicLeftExpr[idx] as applications give warnings
let checkHighPrecedenceFunctionApplicationToList (g: TcGlobals) args atomicFlag exprRange =
let checkHighPrecedenceFunctionApplicationToList args atomicFlag exprRange =
match args, atomicFlag with
| ([SynExpr.ArrayOrList (false, _, _)] | [SynExpr.ArrayOrListComputed (false, _, _)]), ExprAtomicFlag.Atomic ->
if g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then
informationalWarning(Error(FSComp.SR.tcHighPrecedenceFunctionApplicationToListDeprecated(), exprRange))
elif not (g.langVersion.IsExplicitlySpecifiedAs50OrBefore()) then
informationalWarning(Error(FSComp.SR.tcHighPrecedenceFunctionApplicationToListReserved(), exprRange))
informationalWarning(Error(FSComp.SR.tcHighPrecedenceFunctionApplicationToListDeprecated(), exprRange))
| _ -> ()

/// Indicates whether a syntactic type is allowed to include new type variables
Expand Down Expand Up @@ -5613,41 +5610,29 @@ and TryTcStmt (cenv: cenv) env tpenv synExpr =
let hasTypeUnit = TryUnifyUnitTypeWithoutWarning cenv env m ty
hasTypeUnit, ty, expr, tpenv

and CheckForAdjacentListExpression (cenv: cenv) synExpr hpa isInfix delayed (arg: SynExpr) =
let g = cenv.g
and CheckForAdjacentListExpression synExpr hpa isInfix delayed (arg: SynExpr) =
// func (arg)[arg2] gives warning that .[ must be used.
match delayed with
| DelayedApp (hpa2, isSugar2, _, arg2, _) :: _ when not isInfix && (hpa = ExprAtomicFlag.NonAtomic) && isAdjacentListExpr isSugar2 hpa2 (Some synExpr) arg2 ->
let mWarning = unionRanges arg.Range arg2.Range

match arg with
| SynExpr.Paren _ ->
if g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then
warning(Error(FSComp.SR.tcParenThenAdjacentListArgumentNeedsAdjustment(), mWarning))
elif not (g.langVersion.IsExplicitlySpecifiedAs50OrBefore()) then
informationalWarning(Error(FSComp.SR.tcParenThenAdjacentListArgumentReserved(), mWarning))
warning(Error(FSComp.SR.tcParenThenAdjacentListArgumentNeedsAdjustment(), mWarning))

| SynExpr.ArrayOrListComputed _
| SynExpr.ArrayOrList _ ->
if g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then
warning(Error(FSComp.SR.tcListThenAdjacentListArgumentNeedsAdjustment(), mWarning))
elif not (g.langVersion.IsExplicitlySpecifiedAs50OrBefore()) then
informationalWarning(Error(FSComp.SR.tcListThenAdjacentListArgumentReserved(), mWarning))
warning(Error(FSComp.SR.tcListThenAdjacentListArgumentNeedsAdjustment(), mWarning))

| _ ->
if g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then
warning(Error(FSComp.SR.tcOtherThenAdjacentListArgumentNeedsAdjustment(), mWarning))
elif not (g.langVersion.IsExplicitlySpecifiedAs50OrBefore()) then
informationalWarning(Error(FSComp.SR.tcOtherThenAdjacentListArgumentReserved(), mWarning))
warning(Error(FSComp.SR.tcOtherThenAdjacentListArgumentNeedsAdjustment(), mWarning))

| _ -> ()

/// During checking of expressions of the form (x(y)).z(w1, w2)
/// keep a stack of things on the right. This lets us recognize
/// method applications and other item-based syntax.
and TcExprThen (cenv: cenv) overallTy env tpenv isArg synExpr delayed =
let g = cenv.g

let cachedExpression =
env.eCachedImplicitYieldExpressions.FindAll synExpr.Range
|> List.tryPick (fun (se, ty, e) ->
Expand Down Expand Up @@ -5697,7 +5682,7 @@ and TcExprThen (cenv: cenv) overallTy env tpenv isArg synExpr delayed =

TcNonControlFlowExpr env <| fun env ->

CheckForAdjacentListExpression cenv synExpr hpa isInfix delayed arg
CheckForAdjacentListExpression synExpr hpa isInfix delayed arg

TcExprThen cenv overallTy env tpenv false func ((DelayedApp (hpa, isInfix, Some func, arg, mFuncAndArg)) :: delayed)

Expand All @@ -5721,7 +5706,7 @@ and TcExprThen (cenv: cenv) overallTy env tpenv isArg synExpr delayed =
// etc.
| SynExpr.DotIndexedGet (expr1, IndexerArgs indexArgs, mDot, mWholeExpr) ->
TcNonControlFlowExpr env <| fun env ->
if not isArg && g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then
if not isArg then
informationalWarning(Error(FSComp.SR.tcIndexNotationDeprecated(), mDot))
TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv None expr1 indexArgs delayed

Expand All @@ -5730,8 +5715,7 @@ and TcExprThen (cenv: cenv) overallTy env tpenv isArg synExpr delayed =
// etc.
| SynExpr.DotIndexedSet (expr1, IndexerArgs indexArgs, expr3, mOfLeftOfSet, mDot, mWholeExpr) ->
TcNonControlFlowExpr env <| fun env ->
if g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then
warning(Error(FSComp.SR.tcIndexNotationDeprecated(), mDot))
warning(Error(FSComp.SR.tcIndexNotationDeprecated(), mDot))
// Wrap in extra parens: like MakeDelayedSet,
// but we don't actually want to delay it here.
let setInfo = SynExpr.Paren (expr3, range0, None, expr3.Range), mOfLeftOfSet
Expand Down Expand Up @@ -8734,41 +8718,22 @@ and Propagate (cenv: cenv) (overallTy: OverallTy) (env: TcEnv) tpenv (expr: Appl
// expr[idx1..idx2]
| SynExpr.ArrayOrListComputed(false, _, _) ->
let isAdjacent = isAdjacentListExpr isSugar atomicFlag synLeftExprOpt synArg
if isAdjacent && g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then
if isAdjacent then
// This is the non-error path
()
else
// This is the error path. The error we give depends on what's enabled.
//
// First, 'delayed' is about to be dropped on the floor, do rudimentary checking to get name resolutions in its body
// 'delayed' is about to be dropped on the floor, do rudimentary checking to get name resolutions in its body
RecordNameAndTypeResolutionsDelayed cenv env tpenv delayed
let vName =
match expr.Expr with
| Expr.Val (d, _, _) -> Some d.DisplayName
| _ -> None
if isAdjacent then
if IsIndexerType g cenv.amap expr.Type then
if g.langVersion.IsExplicitlySpecifiedAs50OrBefore() then
error (NotAFunctionButIndexer(denv, overallTy.Commit, vName, mExpr, mArg, false))
match vName with
| Some nm ->
error(Error(FSComp.SR.tcNotAFunctionButIndexerNamedIndexingNotYetEnabled(RichText.mkMember nm, RichText.mkMember nm), mExprAndArg))
| _ ->
error(Error(FSComp.SR.tcNotAFunctionButIndexerIndexingNotYetEnabled(), mExprAndArg))
else
match vName with
| Some nm ->
error(Error(FSComp.SR.tcNotAnIndexerNamedIndexingNotYetEnabled(RichText.mkMember nm), mExprAndArg))
| _ ->
error(Error(FSComp.SR.tcNotAnIndexerIndexingNotYetEnabled(), mExprAndArg))
if IsIndexerType g cenv.amap expr.Type then
// NotAFunctionButIndexer uses overallTy (expected type) for the indexer suggestion message.
error (NotAFunctionButIndexer(denv, overallTy.Commit, vName, mExpr, mArg))
else
if IsIndexerType g cenv.amap expr.Type then
let old = not (g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot)
// NotAFunctionButIndexer uses overallTy (expected type) for the indexer suggestion message.
error (NotAFunctionButIndexer(denv, overallTy.Commit, vName, mExpr, mArg, old))
else
// NotAFunction uses exprTy (actual type) to show "has type X, which does not accept arguments".
error (NotAFunction(denv, exprTy, mExpr, mArg))
// NotAFunction uses exprTy (actual type) to show "has type X, which does not accept arguments".
error (NotAFunction(denv, exprTy, mExpr, mArg))

// f x (where 'f' is not a function)
| _ ->
Expand Down Expand Up @@ -9019,7 +8984,7 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg

// atomicLeftExpr[idx] unifying as application gives a warning
if not isSugar then
checkHighPrecedenceFunctionApplicationToList g [synArg] atomicFlag mExprAndArg
checkHighPrecedenceFunctionApplicationToList [synArg] atomicFlag mExprAndArg

match leftExpr with
| ApplicableExpr(expr=NameOfExpr g _) when g.langVersion.SupportsFeature LanguageFeature.NameOf ->
Expand Down Expand Up @@ -9088,9 +9053,7 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg
// leftExpr[idx]
// leftExpr[idx] <- expr2
| SynExpr.ArrayOrListComputed(false, IndexerArgs indexArgs, m)
when
isAdjacentListExpr isSugar atomicFlag synLeftExprOpt synArg &&
g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot ->
when isAdjacentListExpr isSugar atomicFlag synLeftExprOpt synArg ->

let expandedIndexArgs = ExpandIndexArgs cenv synLeftExprOpt indexArgs
let setInfo, delayed =
Expand Down Expand Up @@ -10245,7 +10208,7 @@ and TcMethodApplicationThen
let mWholeExpr = (m, args) ||> List.fold (fun m arg -> unionRanges m arg.Range)

// c.atomicLeftMethExpr[idx] as application gives a warning
checkHighPrecedenceFunctionApplicationToList g args atomicFlag mWholeExpr
checkHighPrecedenceFunctionApplicationToList args atomicFlag mWholeExpr

// Work out if we know anything about the return type of the overall expression. If there are any delayed
// lookups then we don't know anything.
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/Expressions/CheckExpressions.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ exception FunctionExpected of DisplayEnv * TType * range

exception NotAFunction of DisplayEnv * TType * range * range

exception NotAFunctionButIndexer of DisplayEnv * TType * string option * range * range * bool
exception NotAFunctionButIndexer of DisplayEnv * TType * string option * range * range

exception Recursion of DisplayEnv * Ident * TType * TType * range

Expand Down
15 changes: 5 additions & 10 deletions src/Compiler/Driver/CompilerDiagnostics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ type Exception with

| NotAFunction(_, _, mfun, _) -> Some mfun

| NotAFunctionButIndexer(_, _, _, mfun, _, _) -> Some mfun
| NotAFunctionButIndexer(_, _, _, mfun, _) -> Some mfun

| IllegalFileNameChar _ -> Some rangeCmdArgs

Expand Down Expand Up @@ -1092,15 +1092,10 @@ type Exception with

| InterfaceNotRevealed(denv, intfTy, _) -> os.Append(InterfaceNotRevealedE(), NicePrint.minimalRichTextOfType denv intfTy)

| NotAFunctionButIndexer(_, _, name, _, _, old) ->
if old then
match name with
| Some name -> os.Append(FSComp.SR.notAFunctionButMaybeIndexerWithName (RichText.mkLocal name))
| _ -> os.Append(FSComp.SR.notAFunctionButMaybeIndexer ())
else
match name with
| Some name -> os.Append(FSComp.SR.notAFunctionButMaybeIndexerWithName2 (RichText.mkLocal name))
| _ -> os.Append(FSComp.SR.notAFunctionButMaybeIndexer2 ())
| NotAFunctionButIndexer(_, _, name, _, _) ->
match name with
| Some name -> os.Append(FSComp.SR.notAFunctionButMaybeIndexerWithName2 (RichText.mkLocal name))
| _ -> os.Append(FSComp.SR.notAFunctionButMaybeIndexer2 ())

| NotAFunction(denv, ty, _, marg) ->
if marg.StartColumn = 0 then
Expand Down
11 changes: 0 additions & 11 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1248,7 +1248,6 @@ invalidFullNameForProvidedType,"invalid full name for provided type"
3087,tcCustomOperationMayNotBeOverloaded,"The custom operation '%s' refers to a method which is overloaded. The implementations of custom operations may not be overloaded."
featureOverloadsForCustomOperations,"overloads for custom operations"
featureExpandedMeasurables,"more types support units of measure"
featureIndexerNotationWithoutDot,"expr[idx] notation for indexing and slicing"
featureRefCellNotationInformationals,"informational messages related to reference cells"
featureNonVariablePatternsToRightOfAsPatterns,"non-variable patterns to the right of 'as' patterns"
featureAttributesToRightOfModuleKeyword,"attributes to the right of the 'module' keyword"
Expand Down Expand Up @@ -1484,8 +1483,6 @@ keywordDescriptionUntypedQuotation,"Delimits a untyped code quotation."
descriptionWordIs,"is"
notAFunction,"This value is not a function and cannot be applied."
notAFunctionWithType,"This value is not a function and cannot be applied. It has type '%s', which does not accept arguments."
notAFunctionButMaybeIndexerWithName,"This value is not a function and cannot be applied. Did you intend to access the indexer via '%s.[index]'?"
notAFunctionButMaybeIndexer,"This expression is not a function and cannot be applied. Did you intend to access the indexer via 'expr.[index]'?"
notAFunctionButMaybeIndexerWithName2,"This value is not a function and cannot be applied. Did you intend to access the indexer via '%s[index]'?"
notAFunctionButMaybeIndexer2,"This expression is not a function and cannot be applied. Did you intend to access the indexer via 'expr[index]'?"
3217,notAFunctionButMaybeIndexerErrorCode,""
Expand Down Expand Up @@ -1603,10 +1600,6 @@ featureEnforceAttributeTargets,"Enforce AttributeTargets"
featureLowerInterpolatedStringToConcat,"Optimizes interpolated strings in certain cases, by lowering to concatenation"
featureLowerIntegralRangesToFastLoops,"Optimizes certain uses of the integral range (..) and range-step (.. ..) operators to fast while-loops."
featureLowerSimpleMappingsInComprehensionsToFastLoops,"Lowers [for x in xs -> f x] and [|for x in xs -> f x|] to fast loops when xs is a list or an array, respectively."
3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
3355,tcNotAnIndexerNamedIndexingNotYetEnabled,"The value '%s' is not a function and does not support index notation."
3355,tcNotAnIndexerIndexingNotYetEnabled,"This expression is not a function and does not support index notation."
3356,tcDuplicateExtensionMemberNames,"Extension members extending types with the same simple name '%s' but different fully qualified names cannot be defined in the same module. Consider defining these extensions in separate modules."
3360,typrelInterfaceWithConcreteAndVariable,"'%s' cannot implement the interface '%s' with the two instantiations '%s' and '%s' because they may unify."
3361,typrelInterfaceWithConcreteAndVariableObjectExpression,"You cannot implement the interface '%s' with the two instantiations '%s' and '%s' because they may unify."
Expand All @@ -1615,10 +1608,6 @@ featureLowerSimpleMappingsInComprehensionsToFastLoops,"Lowers [for x in xs -> f
3364,tcInvalidUseOfReverseIndex,"Invalid use of reverse index in list expression."
3365,tcHighPrecedenceFunctionApplicationToListDeprecated,"The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'."
3366,tcIndexNotationDeprecated,"The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code."
3367,tcHighPrecedenceFunctionApplicationToListReserved,"The syntax 'expr1[expr2]' is now reserved for indexing. See https://aka.ms/fsharp-index-notation. If calling a function, add a space between the function and argument, e.g. 'someFunction [expr]'."
3368,tcParenThenAdjacentListArgumentReserved,"The syntax '(expr1)[expr2]' is now reserved for indexing and is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction (expr1) [expr2]'."
3368,tcListThenAdjacentListArgumentReserved,"The syntax '[expr1][expr2]' is now reserved for indexing and is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction [expr1] [expr2]'."
3368,tcOtherThenAdjacentListArgumentReserved,"The syntax 'expr1[expr2]' is now reserved for indexing and is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'."
3369,tcParenThenAdjacentListArgumentNeedsAdjustment,"The syntax '(expr1)[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use '(expr1).[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction (expr1) [expr2]'."
3369,tcListThenAdjacentListArgumentNeedsAdjustment,"The syntax '[expr1][expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use '(expr1).[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction [expr1] [expr2]'."
3369,tcOtherThenAdjacentListArgumentNeedsAdjustment,"The syntax 'expr1[expr2]' is ambiguous when used as an argument. See https://aka.ms/fsharp-index-notation. If you intend indexing or slicing then you must use 'expr1.[expr2]' in argument position. If calling a function with multiple curried arguments, add a space between them, e.g. 'someFunction expr1 [expr2]'."
Expand Down
Loading
Loading