Merge pull request #42036 from xedin/dont-infer-from-magic-defaults

[TypeChecker] SE-0347: Avoid type inference from caller-site defaults
This commit is contained in:
Pavel Yaskevich
2022-03-25 20:11:39 -07:00
committed by GitHub
4 changed files with 22 additions and 0 deletions

View File

@@ -7067,6 +7067,10 @@ Expr *ParamDecl::getTypeCheckedDefaultExpr() const {
Type ParamDecl::getTypeOfDefaultExpr() const { Type ParamDecl::getTypeOfDefaultExpr() const {
auto &ctx = getASTContext(); auto &ctx = getASTContext();
// If this is a caller-side default, the type is determined based on
// a particular call site.
assert(!hasCallerSideDefaultExpr());
if (Type type = evaluateOrDefault( if (Type type = evaluateOrDefault(
ctx.evaluator, ctx.evaluator,
DefaultArgumentTypeRequest{const_cast<ParamDecl *>(this)}, nullptr)) { DefaultArgumentTypeRequest{const_cast<ParamDecl *>(this)}, nullptr)) {

View File

@@ -1782,6 +1782,11 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
if (!PD->getInterfaceType()->hasTypeParameter()) if (!PD->getInterfaceType()->hasTypeParameter())
continue; continue;
// The type of the default value is going to be determined
// based on a type deduced for the parameter at this call site.
if (PD->hasCallerSideDefaultExpr())
continue;
auto defaultExprType = PD->getTypeOfDefaultExpr(); auto defaultExprType = PD->getTypeOfDefaultExpr();
// A caller side default. // A caller side default.

View File

@@ -468,6 +468,11 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
if (!ctx.TypeCheckerOpts.EnableTypeInferenceFromDefaultArguments) if (!ctx.TypeCheckerOpts.EnableTypeInferenceFromDefaultArguments)
return Type(); return Type();
// Caller-side defaults are always type-checked based on the concrete
// type of the argument deduced at a particular call site.
if (isa<MagicIdentifierLiteralExpr>(defaultValue))
return Type();
// Parameter type doesn't have any generic parameters mentioned // Parameter type doesn't have any generic parameters mentioned
// in it, so there is nothing to infer. // in it, so there is nothing to infer.
if (!paramInterfaceTy->hasTypeParameter()) if (!paramInterfaceTy->hasTypeParameter())

View File

@@ -167,3 +167,11 @@ func main() {
takesRectangle(.init()) takesRectangle(.init())
// expected-error@-1 {{cannot convert default value of type 'Rectangle' to expected argument type 'Circle' for parameter #0}} // expected-error@-1 {{cannot convert default value of type 'Rectangle' to expected argument type 'Circle' for parameter #0}}
} }
func test_magic_defaults() {
func with_magic(_: Int = #function) {} // expected-error {{default argument value of type 'String' cannot be converted to type 'Int'}}
func generic_with_magic<T>(_: T = #line) -> T {} // expected-error {{default argument value of type 'Int' cannot be converted to type 'T'}}
let _ = with_magic()
let _: String = generic_with_magic()
}