Skip to content

Commit 7add744

Browse files
authored
Merge pull request swiftlang#26074 from theblixguy/fix/SR-11074
[CS] Don't crash when default argument is magic literal and types don't match
2 parents 56515ee + afa1471 commit 7add744

File tree

10 files changed

+131
-2
lines changed

10 files changed

+131
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ ERROR(cannot_convert_default_arg_value,none,
350350
(Type,Type))
351351
ERROR(cannot_convert_default_arg_value_protocol,none,
352352
"default argument value of type %0 does not conform to %1", (Type,Type))
353+
ERROR(default_argument_literal_cannot_convert, none,
354+
"cannot call %0 %1 because default argument of type %2 cannot be "
355+
"converted to type %3", (DescriptiveDeclKind, DeclName, Type, Type))
353356
ERROR(cannot_convert_default_arg_value_nil,none,
354357
"nil default argument value cannot be converted to type %0", (Type))
355358

lib/Sema/CSDiagnostics.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2728,6 +2728,21 @@ bool MissingArgumentsFailure::diagnoseTrailingClosure(ClosureExpr *closure) {
27282728
return true;
27292729
}
27302730

2731+
bool DefaultArgumentTypeMismatch::diagnoseAsError() {
2732+
auto choice = getChoiceFor(getRawAnchor());
2733+
if (!choice.hasValue())
2734+
return false;
2735+
2736+
auto declName = choice.getValue().choice.getName();
2737+
auto declKind = choice.getValue().choice.getDecl()->getDescriptiveKind();
2738+
2739+
emitDiagnostic(getAnchor()->getLoc(),
2740+
diag::default_argument_literal_cannot_convert, declKind,
2741+
declName, FromType, ToType);
2742+
2743+
return true;
2744+
}
2745+
27312746
bool ClosureParamDestructuringFailure::diagnoseAsError() {
27322747
auto *closure = cast<ClosureExpr>(getAnchor());
27332748
auto params = closure->getParameters();

lib/Sema/CSDiagnostics.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,21 @@ class MissingArgumentsFailure final : public FailureDiagnostic {
10861086
bool diagnoseTrailingClosure(ClosureExpr *closure);
10871087
};
10881088

1089+
class DefaultArgumentTypeMismatch final : public FailureDiagnostic {
1090+
using Param = AnyFunctionType::Param;
1091+
1092+
Type FromType;
1093+
Type ToType;
1094+
1095+
public:
1096+
DefaultArgumentTypeMismatch(Expr *root, ConstraintSystem &cs, Type fromType,
1097+
Type toType, ConstraintLocator *locator)
1098+
: FailureDiagnostic(root, cs, locator), FromType(fromType),
1099+
ToType(toType) {}
1100+
1101+
bool diagnoseAsError() override;
1102+
};
1103+
10891104
class OutOfOrderArgumentFailure final : public FailureDiagnostic {
10901105
using ParamBinding = SmallVector<unsigned, 1>;
10911106

lib/Sema/CSFix.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,21 @@ bool AddMissingArguments::diagnose(Expr *root, bool asNote) const {
451451
return failure.diagnose(asNote);
452452
}
453453

454+
IgnoreDefaultArgumentTypeMismatch *
455+
IgnoreDefaultArgumentTypeMismatch::create(ConstraintSystem &cs, Type fromType,
456+
Type toType,
457+
ConstraintLocator *locator) {
458+
return new (cs.getAllocator())
459+
IgnoreDefaultArgumentTypeMismatch(cs, fromType, toType, locator);
460+
}
461+
462+
bool IgnoreDefaultArgumentTypeMismatch::diagnose(Expr *root,
463+
bool asNote) const {
464+
DefaultArgumentTypeMismatch failure(root, getConstraintSystem(), FromType,
465+
ToType, getLocator());
466+
return failure.diagnose(asNote);
467+
}
468+
454469
AddMissingArguments *
455470
AddMissingArguments::create(ConstraintSystem &cs, FunctionType *funcType,
456471
llvm::ArrayRef<Param> synthesizedArgs,

lib/Sema/CSFix.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ enum class FixKind : uint8_t {
185185
/// when base is an r-value type.
186186
AllowMutatingMemberOnRValueBase,
187187

188+
/// Fix the type of the default argument
189+
DefaultArgumentTypeMismatch,
190+
188191
/// Allow a single tuple parameter to be matched with N arguments
189192
/// by forming all of the given arguments into a single tuple.
190193
AllowTupleSplatForSingleParameter,
@@ -946,6 +949,27 @@ class AddMissingArguments final
946949
}
947950
};
948951

952+
class IgnoreDefaultArgumentTypeMismatch final : public ConstraintFix {
953+
Type FromType;
954+
Type ToType;
955+
956+
IgnoreDefaultArgumentTypeMismatch(ConstraintSystem &cs, Type fromType,
957+
Type toType, ConstraintLocator *locator)
958+
: ConstraintFix(cs, FixKind::DefaultArgumentTypeMismatch, locator),
959+
FromType(fromType), ToType(toType) {}
960+
961+
public:
962+
std::string getName() const override {
963+
return "ignore default argument type mismatch";
964+
}
965+
966+
bool diagnose(Expr *root, bool asNote = false) const override;
967+
968+
static IgnoreDefaultArgumentTypeMismatch *create(ConstraintSystem &cs,
969+
Type fromType, Type toType,
970+
ConstraintLocator *locator);
971+
};
972+
949973
class MoveOutOfOrderArgument final : public ConstraintFix {
950974
using ParamBinding = SmallVector<unsigned, 1>;
951975

lib/Sema/CSSimplify.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,9 +966,36 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
966966

967967
for (unsigned paramIdx = 0, numParams = parameterBindings.size();
968968
paramIdx != numParams; ++paramIdx){
969-
// Skip unfulfilled parameters. There's nothing to do for them.
970-
if (parameterBindings[paramIdx].empty())
969+
// If a parameter is unfulfilled, validate the default argument if it is a
970+
// magic literal expression.
971+
if (parameterBindings[paramIdx].empty()) {
972+
if (!callee)
973+
continue;
974+
975+
if (!callee->hasParameterList())
976+
continue;
977+
978+
auto param = getParameterAt(callee, paramIdx);
979+
980+
auto defaultValueExpr = param->getDefaultValue();
981+
982+
if (!(defaultValueExpr &&
983+
isa<MagicIdentifierLiteralExpr>(defaultValueExpr)))
984+
continue;
985+
986+
if (defaultValueExpr->getType())
987+
continue;
988+
989+
cs.generateConstraints(defaultValueExpr, param->getDeclContext());
990+
991+
auto defaultTy = cs.getType(defaultValueExpr);
992+
auto paramTy = param->getType();
993+
cs.addConstraint(
994+
ConstraintKind::ArgumentConversion, defaultTy, paramTy,
995+
locator.withPathElement(ConstraintLocator::DefaultArgument));
996+
971997
continue;
998+
}
972999

9731000
// Determine the parameter type.
9741001
const auto &param = params[paramIdx];
@@ -2335,6 +2362,12 @@ bool ConstraintSystem::repairFailures(
23352362
break;
23362363
}
23372364

2365+
case ConstraintLocator::DefaultArgument: {
2366+
conversionsOrFixes.push_back(IgnoreDefaultArgumentTypeMismatch::create(
2367+
*this, lhs, rhs, getConstraintLocator(anchor, path)));
2368+
break;
2369+
}
2370+
23382371
case ConstraintLocator::TypeParameterRequirement:
23392372
case ConstraintLocator::ConditionalRequirement: {
23402373
// If dependent members are present here it's because
@@ -6965,6 +6998,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
69656998
case FixKind::SkipSuperclassRequirement:
69666999
case FixKind::ContextualMismatch:
69677000
case FixKind::AddMissingArguments:
7001+
case FixKind::DefaultArgumentTypeMismatch:
69687002
case FixKind::SkipUnhandledConstructInFunctionBuilder:
69697003
case FixKind::UsePropertyWrapper:
69707004
case FixKind::UseWrappedValue: {

lib/Sema/ConstraintLocator.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
5252
case ApplyArgument:
5353
case ApplyFunction:
5454
case FunctionArgument:
55+
case DefaultArgument:
5556
case FunctionResult:
5657
case OptionalPayload:
5758
case Member:
@@ -270,6 +271,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
270271
out << "function argument";
271272
break;
272273

274+
case DefaultArgument:
275+
out << "default argument";
276+
break;
277+
273278
case FunctionResult:
274279
out << "function result";
275280
break;

lib/Sema/ConstraintLocator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class ConstraintLocator : public llvm::FoldingSetNode {
6565
GenericParameter,
6666
/// The argument type of a function.
6767
FunctionArgument,
68+
/// The default argument type of a function.
69+
DefaultArgument,
6870
/// The result type of a function.
6971
FunctionResult,
7072
/// A tuple element referenced by position.
@@ -147,6 +149,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
147149
case ApplyFunction:
148150
case GenericParameter:
149151
case FunctionArgument:
152+
case DefaultArgument:
150153
case FunctionResult:
151154
case OptionalPayload:
152155
case Member:
@@ -244,6 +247,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
244247
return 0;
245248

246249
case FunctionArgument:
250+
case DefaultArgument:
247251
case FunctionResult:
248252
return IsFunctionConversion;
249253
}

test/decl/func/default-values.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,12 @@ let fooThing5 = Foo(a: 0, d: 1, h: nil) // expected-error {{missing argument for
168168
// Here b = false and g = nil, but we're checking that f doesn't get a default value
169169
let fooThing6 = Foo(a: 0, d: 1, e: 2, h: nil) // expected-error {{missing argument for parameter 'f' in call}}
170170
// expected-note@-29 {{'init(a:b:d:e:f:g:h:)' declared here}}
171+
172+
// SR-11074
173+
174+
func sr_11074(x: Int) {}
175+
func sr_11074(line: String = #line) {} // expected-error {{default argument value of type 'Int' cannot be converted to type 'String'}}
176+
sr_11074() // expected-error {{cannot call global function 'sr_11074(line:)' because default argument of type 'Int' cannot be converted to type 'String'}}
177+
178+
class SR_11074_C { init(line: String = #line) {} } // expected-error {{default argument value of type 'Int' cannot be converted to type 'String'}}
179+
let _ = SR_11074_C() // expected-error {{cannot call initializer 'init(line:)' because default argument of type 'Int' cannot be converted to type 'String'}}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: not %target-swift-frontend -typecheck %s
2+
3+
func foo(x: Int) {}
4+
func foo(line: String = #line) {}
5+
foo()

0 commit comments

Comments
 (0)