diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index ce202a0d7ec..e78bdb049d4 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1129,7 +1129,8 @@ RemoveReturn *RemoveReturn::create(ConstraintSystem &cs, Type resultTy, NotCompileTimeConst::NotCompileTimeConst(ConstraintSystem &cs, Type paramTy, ConstraintLocator *locator): ContextualMismatch(cs, FixKind::NotCompileTimeConst, paramTy, - cs.getASTContext().TheEmptyTupleType, locator) {} + cs.getASTContext().TheEmptyTupleType, locator, + /*warning*/true) {} NotCompileTimeConst * NotCompileTimeConst::create(ConstraintSystem &cs, Type paramTy, @@ -1138,7 +1139,14 @@ NotCompileTimeConst::create(ConstraintSystem &cs, Type paramTy, } bool NotCompileTimeConst::diagnose(const Solution &solution, bool asNote) const { - NotCompileTimeConstFailure failure(solution, getLocator()); + auto *locator = getLocator(); + // Referencing an enum element directly is considered a compile-time literal. + if (auto *d = solution.resolveLocatorToDecl(locator).getDecl()) { + if (isa(d)) { + return true; + } + } + NotCompileTimeConstFailure failure(solution, locator); return failure.diagnose(asNote); } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 44e0c99297b..dfa08d61718 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -1506,8 +1506,17 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments( } if (!argument.isCompileTimeConst() && param.isCompileTimeConst()) { if (cs.shouldAttemptFixes()) { - cs.recordFix(NotCompileTimeConst::create(cs, paramTy, - cs.getConstraintLocator(loc))); + auto *locator = cs.getConstraintLocator(loc); + SourceRange range; + // simplify locator so the anchor is the exact argument. + locator = simplifyLocator(cs, locator, range); + if (locator->getPath().empty() && + locator->getAnchor().isExpr(ExprKind::UnresolvedMemberChainResult)) { + locator = + cs.getConstraintLocator(cast( + locator->getAnchor().get())->getChainBase()); + } + cs.recordFix(NotCompileTimeConst::create(cs, paramTy, locator)); } } diff --git a/test/Sema/const_enum_elements.swift b/test/Sema/const_enum_elements.swift new file mode 100644 index 00000000000..cbc408894cb --- /dev/null +++ b/test/Sema/const_enum_elements.swift @@ -0,0 +1,30 @@ +// RUN: %target-typecheck-verify-swift + +enum CarKind { + case coupe + case sedan + case other(String) +} + +extension CarKind { + static var myCoupe: CarKind { + return .coupe + } +} + +func getCarKind() -> CarKind { return .sedan } + +func drive(_ k1: _const CarKind, k2: _const CarKind) {} + +func main() { + drive(.coupe, k2: .sedan) + drive(.sedan, k2: .coupe) + drive(CarKind.coupe, k2: CarKind.sedan) + drive(CarKind.sedan, k2: CarKind.coupe) + drive(.other(""), k2: .sedan) + + drive(.myCoupe, k2: .sedan) // expected-error {{expect a compile-time constant literal}} + drive(.coupe, k2: .myCoupe) // expected-error {{expect a compile-time constant literal}} + drive(.coupe, k2: getCarKind()) // expected-error {{expect a compile-time constant literal}} + drive(getCarKind(), k2: .coupe) // expected-error {{expect a compile-time constant literal}} +}