Skip to content

[TypeChecker] Avoid dropping pre-check diagnostics in `typeCheckParam… #80280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions lib/Sema/TypeCheckConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,10 +419,12 @@ TypeChecker::typeCheckTarget(SyntacticElementTarget &target,
PrettyStackTraceLocation stackTrace(Context, "type-checking-target",
target.getLoc());

// First, pre-check the target, validating any types that occur in the
// expression and folding sequence expressions.
if (ConstraintSystem::preCheckTarget(target))
return errorResult();
if (!options.contains(TypeCheckExprFlags::AvoidInvalidatingAST)) {
// First, pre-check the target, validating any types that occur in the
// expression and folding sequence expressions.
if (ConstraintSystem::preCheckTarget(target))
return errorResult();
}

// Check whether given target has a code completion token which requires
// special handling. Returns true if handled, in which case we've already
Expand Down Expand Up @@ -509,6 +511,11 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,

auto paramInterfaceTy = paramType->mapTypeOutOfContext();

// Attempt to pre-check expression first, if that fails - skip type-checking.
// This would make sure that diagnostics about invalid AST are never dropped.
if (ConstraintSystem::preCheckTarget(defaultExprTarget))
return Type();

{
// Buffer all of the diagnostics produced by \c typeCheckExpression
// since in some cases we need to try type-checking again with a
Expand All @@ -531,8 +538,8 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
// First, let's try to type-check default expression using
// archetypes, which guarantees that it would work for any
// substitution of the generic parameter (if they are involved).
if (auto result = typeCheckExpression(
defaultExprTarget, options, &diagnostics)) {
if (auto result =
typeCheckTarget(defaultExprTarget, options, &diagnostics)) {
defaultValue = result->getAsExpr();
return defaultValue->getType();
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ enum class TypeCheckExprFlags {
/// Don't expand macros.
DisableMacroExpansions = 0x04,

/// If set, typeCheckExpression will avoid invalidating the AST if
/// type-checking fails. Do not add new uses of this.
/// If set, typeCheckExpression will avoid pre-checking and invalidating
/// the AST if type-checking fails. Do not add new uses of this.
AvoidInvalidatingAST = 0x08,
};

Expand Down
2 changes: 2 additions & 0 deletions stdlib/public/Concurrency/TaskSleepDuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ extension Task where Success == Never, Failure == Never {
}
}

#if !$Embedded
/// Suspends the current task until the given deadline within a tolerance.
///
/// If the task is canceled before the time ends, this function throws
Expand Down Expand Up @@ -153,6 +154,7 @@ extension Task where Success == Never, Failure == Never {
) async throws {
try await clock.sleep(for: duration, tolerance: tolerance)
}
#endif
}
#else
@available(SwiftStdlib 5.7, *)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: %target-typecheck-verify-swift

// https://github.com/apple/swift/issues/73986

struct S {
init(_: () -> some Any = { Nonexistent() }) {}
// expected-error@-1 {{cannot find 'Nonexistent' in scope}}

init<C>(other: C = { _ = 42; return Nonexistent() }) {}
// expected-error@-1 {{cannot find 'Nonexistent' in scope}}
}

func test(x: some FixedWidthInteger = UNKNOWN_CONSTANT) {
// expected-error@-1 {{cannot find 'UNKNOWN_CONSTANT' in scope}}
}