diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 4001b801aa5..c779a609c2c 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -248,6 +248,12 @@ type ConstraintSolverState = /// Indicates if the constraint solver is being run after type checking is complete, /// e.g. during codegen to determine solutions and witnesses for trait constraints. /// Suppresses the generation of certain errors such as missing constraint warnings. + afterTypeCheck: bool + + /// Indicates if the constraint solver is being run at very last stage (ilxgen) + /// Allows constraints to be added to type parameters to produce a witness. + /// There is no really good reason this should be allowed nor should it be needed, + /// but it was in the codebase and remains active for legacy compat reasons. codegen: bool /// This table stores all unsolved, ungeneralized trait constraints, indexed by free type variable. @@ -262,6 +268,7 @@ type ConstraintSolverState = amap = amap ExtraCxs = HashMultiMap(10, HashIdentity.Structural) InfoReader = infoReader + afterTypeCheck = false codegen = false TcVal = tcVal } @@ -1952,7 +1959,7 @@ and AddConstraint (csenv: ConstraintSolverEnv) ndeep m2 trace tp newConstraint // will-be-made-rigid type variable. This is because the existence of these warnings // is relevant to the overload resolution rules (see 'candidateWarnCount' in the overload resolution // implementation). - if tp.Rigidity.WarnIfMissingConstraint && not csenv.SolverState.codegen then + if tp.Rigidity.WarnIfMissingConstraint && not csenv.SolverState.afterTypeCheck then do! WarnD (ConstraintSolverMissingConstraint(denv, tp, newConstraint, m, m2)) let newConstraints = @@ -3060,17 +3067,18 @@ let ApplyTyparDefaultAtPriority denv css priority (tp: Typar) = |> RaiseOperationResult | _ -> ()) -let CreateCodegenState tcVal g amap = +let CreateCodegenState tcVal g amap codegen = { g = g amap = amap TcVal = tcVal ExtraCxs = HashMultiMap(10, HashIdentity.Structural) InfoReader = new InfoReader(g, amap) - codegen = true } + codegen = codegen + afterTypeCheck = true } /// Generate a witness expression if none is otherwise available, e.g. in legacy non-witness-passing code -let CodegenWitnessForTraitConstraint tcVal g amap m (traitInfo:TraitConstraintInfo) argExprs = trackErrors { - let css = CreateCodegenState tcVal g amap +let CodegenWitnessForTraitConstraint tcVal g amap m (traitInfo:TraitConstraintInfo) argExprs codegen = trackErrors { + let css = CreateCodegenState tcVal g amap codegen let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) let! _res = SolveMemberConstraint csenv true PermitWeakResolution.Yes 0 m NoTrace traitInfo let sln = GenWitnessExpr amap g m traitInfo argExprs @@ -3078,8 +3086,8 @@ let CodegenWitnessForTraitConstraint tcVal g amap m (traitInfo:TraitConstraintIn } /// Generate the lambda argument passed for a use of a generic construct that accepts trait witnesses -let CodegenWitnessesForTyparInst tcVal g amap m typars tyargs = trackErrors { - let css = CreateCodegenState tcVal g amap +let CodegenWitnessesForTyparInst tcVal g amap m typars tyargs codegen = trackErrors { + let css = CreateCodegenState tcVal g amap codegen let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) let ftps, _renaming, tinst = FreshenTypeInst m typars let traitInfos = GetTraitConstraintInfosOfTypars g ftps @@ -3088,8 +3096,8 @@ let CodegenWitnessesForTyparInst tcVal g amap m typars tyargs = trackErrors { } /// Generate the lambda argument passed for a use of a generic construct that accepts trait witnesses -let CodegenWitnessesForTraitWitness tcVal g amap m traitInfo = trackErrors { - let css = CreateCodegenState tcVal g amap +let CodegenWitnessesForTraitWitness tcVal g amap m traitInfo codegen = trackErrors { + let css = CreateCodegenState tcVal g amap codegen let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) let! _res = SolveMemberConstraint csenv true PermitWeakResolution.Yes 0 m NoTrace traitInfo return MethodCalls.GenWitnessExprLambda amap g m traitInfo @@ -3140,6 +3148,7 @@ let IsApplicableMethApprox g amap m (minfo: MethInfo) availObjTy = amap = amap TcVal = (fun _ -> failwith "should not be called") ExtraCxs = HashMultiMap(10, HashIdentity.Structural) + afterTypeCheck = false codegen = false InfoReader = new InfoReader(g, amap) } let csenv = MakeConstraintSolverEnv ContextInfo.NoContext css m (DisplayEnv.Empty g) diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index 78872f1d805..abd3ef4c314 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -192,13 +192,13 @@ val SolveTypeAsError: DisplayEnv -> ConstraintSolverState -> range -> TType -> u val ApplyTyparDefaultAtPriority: DisplayEnv -> ConstraintSolverState -> priority: int -> Typar -> unit /// Generate a witness expression if none is otherwise available, e.g. in legacy non-witness-passing code -val CodegenWitnessForTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> OperationResult +val CodegenWitnessForTraitConstraint : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> Expr list -> bool -> OperationResult /// Generate the arguments passed when using a generic construct that accepts traits witnesses -val CodegenWitnessesForTyparInst : TcValF -> TcGlobals -> ImportMap -> range -> Typars -> TType list -> OperationResult list> +val CodegenWitnessesForTyparInst : TcValF -> TcGlobals -> ImportMap -> range -> Typars -> TType list -> bool -> OperationResult list> /// Generate the lambda argument passed for a use of a generic construct that accepts trait witnesses -val CodegenWitnessesForTraitWitness : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> OperationResult> +val CodegenWitnessesForTraitWitness : TcValF -> TcGlobals -> ImportMap -> range -> TraitConstraintInfo -> bool -> OperationResult> /// For some code like "let f() = ([] = [])", a free choice is made for a type parameter /// for an interior type variable. This chooses a solution for a type parameter subject diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index f029114e1e2..f7da5fdf10a 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -3114,7 +3114,7 @@ and GenWitnessArgFromTraitInfo cenv cgbuf eenv m traitInfo = match storage with | None -> let witnessExpr = - ConstraintSolver.CodegenWitnessesForTraitWitness cenv.tcVal g cenv.amap m traitInfo + ConstraintSolver.CodegenWitnessesForTraitWitness cenv.tcVal g cenv.amap m traitInfo true |> CommitOperationResult match witnessExpr with | Choice1Of2 _traitInfo -> @@ -3152,7 +3152,7 @@ and GenWitnessArgs cenv cgbuf eenv m tps tyargs = // Witness arguments are only generated in emitted 'inline' code where witness parameters are available. if generateWitnesses then let mwitnesses = - ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal g cenv.amap m tps tyargs + ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal g cenv.amap m tps tyargs true |> CommitOperationResult for witnessArg in mwitnesses do @@ -4084,7 +4084,7 @@ and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExp // If witnesses are available, we should now always find trait witnesses in scope assert not generateWitnesses - let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs) + let minfoOpt = CommitOperationResult (ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs true) match minfoOpt with | None -> let exnArg = mkString g m (FSComp.SR.ilDynamicInvocationNotSupported(traitInfo.MemberName)) diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 1c8e4928b0d..c14c8e56d9e 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -520,9 +520,9 @@ let BindInternalLocalVal cenv (v: Val) vval env = env let BindExternalLocalVal cenv (v: Val) vval env = -#if CHECKED - CheckInlineValueIsComplete v vval -#endif +//#if CHECKED + CheckInlineValueIsComplete v vval.ValExprInfo +//#endif let vval = if v.IsMutable then {vval with ValExprInfo=UnknownValue } else vval let env = @@ -2451,7 +2451,7 @@ and OptimizeWhileLoop cenv env (spWhile, marker, e1, e2, m) = and OptimizeTraitCall cenv env (traitInfo, args, m) = // Resolve the static overloading early (during the compulsory rewrite phase) so we can inline. - match ConstraintSolver.CodegenWitnessForTraitConstraint cenv.TcVal cenv.g cenv.amap m traitInfo args with + match ConstraintSolver.CodegenWitnessForTraitConstraint cenv.TcVal cenv.g cenv.amap m traitInfo args false with | OkResult (_, Some expr) -> OptimizeExpr cenv env expr diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 5b154ebf22d..e6f360c11a2 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -249,7 +249,7 @@ and GetWitnessArgs cenv (env : QuotationTranslationEnv) m tps tyargs = let g = cenv.g if g.generateWitnesses && not env.suppressWitnesses then let witnessExprs = - ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal g cenv.amap m tps tyargs + ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcVal g cenv.amap m tps tyargs false |> CommitOperationResult let env = { env with suppressWitnesses = true } witnessExprs |> List.map (fun arg -> @@ -737,7 +737,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let minfoOpt = if g.generateWitnesses then - ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal g cenv.amap m traitInfo args |> CommitOperationResult + ConstraintSolver.CodegenWitnessForTraitConstraint cenv.tcVal g cenv.amap m traitInfo args false |> CommitOperationResult else None match minfoOpt with