Skip to content

Commit 4ecc05d

Browse files
authored
Merge pull request swiftlang#42264 from xedin/err-in-default-expr
[TypeChecker] Fix a crash in inherited default argument type-checking
2 parents 4a5f4d1 + 8f55238 commit 4ecc05d

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

lib/AST/Decl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7125,12 +7125,19 @@ void ParamDecl::setDefaultExpr(Expr *E, bool isTypeChecked) {
71257125
"Can't overwrite type-checked default with un-type-checked default");
71267126
}
71277127
defaultInfo->DefaultArg = E;
7128-
defaultInfo->ExprType = E->getType();
7128+
// `Inherited` default arguments do not have an expression,
7129+
// so if the storage has been pre-allocated already we need
7130+
// to be careful requesting type here.
7131+
defaultInfo->ExprType = E ? E->getType() : Type();
71297132
defaultInfo->InitContextAndIsTypeChecked.setInt(isTypeChecked);
71307133
}
71317134

71327135
void ParamDecl::setDefaultExprType(Type type) {
71337136
if (!DefaultValueAndFlags.getPointer()) {
7137+
// If there is no type, let's not allocate storage.
7138+
if (!type)
7139+
return;
7140+
71347141
DefaultValueAndFlags.setPointer(
71357142
getASTContext().Allocate<StoredDefaultArgument>());
71367143
}

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,8 +1065,10 @@ Expr *DefaultArgumentExprRequest::evaluate(Evaluator &evaluator,
10651065

10661066
Type DefaultArgumentTypeRequest::evaluate(Evaluator &evaluator,
10671067
ParamDecl *param) const {
1068-
if (auto expr = param->getTypeCheckedDefaultExpr())
1069-
return expr->getType();
1068+
if (auto *expr = param->getTypeCheckedDefaultExpr()) {
1069+
// If the request failed, let's not propagate ErrorType up.
1070+
return isa<ErrorExpr>(expr) ? Type() : expr->getType();
1071+
}
10701072
return Type();
10711073
}
10721074

test/Constraints/type_inference_from_default_exprs.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,35 @@ func test_allow_same_type_between_dependent_types() {
199199
s.test() // expected-error {{instance method 'test' requires the types 'String' and 'Default.X' (aka 'Int') be equivalent}}
200200
}
201201
}
202+
203+
// Crash when default type is requested before inherited constructor is type-checked
204+
205+
protocol StorageType {
206+
var identifier: String { get }
207+
}
208+
209+
class Storage {
210+
}
211+
212+
extension Storage {
213+
struct Test {
214+
static let test = CustomStorage<String>("") // triggers default type request
215+
}
216+
}
217+
218+
class BaseStorage<T> : Storage, StorageType {
219+
enum StorageType {
220+
case standard
221+
}
222+
223+
let identifier: String
224+
let type: StorageType
225+
226+
init(_ id: String, type: StorageType = .standard) {
227+
self.identifier = id
228+
self.type = type
229+
}
230+
}
231+
232+
final class CustomStorage<T>: BaseStorage<T> { // Ok - no crash typechecking inherited init
233+
}

0 commit comments

Comments
 (0)