mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema] Diagnose and reject top-level placeholders
This commit is contained in:
@@ -3598,6 +3598,8 @@ ERROR(cannot_force_unwrap_nil_literal,none,
|
||||
|
||||
ERROR(could_not_infer_placeholder,none,
|
||||
"could not infer type for placeholder", ())
|
||||
ERROR(top_level_placeholder_type,none,
|
||||
"placeholders are not allowed as top-level types", ())
|
||||
|
||||
ERROR(type_of_expression_is_ambiguous,none,
|
||||
"type of expression is ambiguous without more context", ())
|
||||
|
||||
@@ -1551,7 +1551,9 @@ TypeExpr *PreCheckExpression::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) {
|
||||
},
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
PlaceholderType::get);
|
||||
[](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
});
|
||||
const auto BaseTy = resolution.resolveType(InnerTypeRepr);
|
||||
|
||||
if (BaseTy->mayHaveMembers()) {
|
||||
@@ -2095,7 +2097,9 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) {
|
||||
},
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
PlaceholderType::get);
|
||||
[](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
});
|
||||
const auto result = resolution.resolveType(typeExpr->getTypeRepr());
|
||||
if (result->hasError())
|
||||
return nullptr;
|
||||
|
||||
@@ -2126,7 +2126,9 @@ static Type validateParameterType(ParamDecl *decl) {
|
||||
};
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
placeholderHandler = PlaceholderType::get;
|
||||
placeholderHandler = [](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
};
|
||||
} else if (isa<AbstractFunctionDecl>(dc)) {
|
||||
options = TypeResolutionOptions(TypeResolverContext::AbstractFunctionDecl);
|
||||
} else if (isa<SubscriptDecl>(dc)) {
|
||||
@@ -2760,7 +2762,9 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const {
|
||||
},
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
PlaceholderType::get);
|
||||
[](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
});
|
||||
|
||||
const auto extendedType = resolution.resolveType(extendedRepr);
|
||||
|
||||
|
||||
@@ -477,7 +477,9 @@ public:
|
||||
},
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
PlaceholderType::get);
|
||||
[](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
});
|
||||
const auto ty = resolution.resolveType(repr);
|
||||
auto *enumDecl = dyn_cast_or_null<EnumDecl>(ty->getAnyNominal());
|
||||
if (!enumDecl)
|
||||
@@ -599,7 +601,9 @@ public:
|
||||
},
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
PlaceholderType::get)
|
||||
[](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
})
|
||||
.resolveType(prefixRepr);
|
||||
auto *enumDecl = dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal());
|
||||
if (!enumDecl)
|
||||
@@ -809,7 +813,9 @@ Type PatternTypeRequest::evaluate(Evaluator &evaluator,
|
||||
};
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
placeholderHandler = PlaceholderType::get;
|
||||
placeholderHandler = [](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
};
|
||||
}
|
||||
return validateTypedPattern(
|
||||
cast<TypedPattern>(P),
|
||||
@@ -877,7 +883,9 @@ Type PatternTypeRequest::evaluate(Evaluator &evaluator,
|
||||
};
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
placeholderHandler = PlaceholderType::get;
|
||||
placeholderHandler = [](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
};
|
||||
}
|
||||
TypedPattern *TP = cast<TypedPattern>(somePat->getSubPattern());
|
||||
const auto type = validateTypedPattern(
|
||||
|
||||
@@ -1938,6 +1938,31 @@ Type ResolveTypeRequest::evaluate(Evaluator &evaluator,
|
||||
if (validateAutoClosureAttributeUse(ctx.Diags, TyR, result, options))
|
||||
return ErrorType::get(ctx);
|
||||
|
||||
// Diagnose an attempt to use a placeholder at the top level.
|
||||
if (result->getCanonicalType()->is<PlaceholderType>() &&
|
||||
resolution->getOptions().contains(TypeResolutionFlags::Direct)) {
|
||||
if (!resolution->getOptions().contains(TypeResolutionFlags::SilenceErrors))
|
||||
ctx.Diags.diagnose(loc, diag::top_level_placeholder_type);
|
||||
|
||||
TyR->setInvalid();
|
||||
return ErrorType::get(ctx);
|
||||
}
|
||||
|
||||
// Now that top-level placeholders have been diagnosed, replace them according
|
||||
// to the user-specified handler (if it exists).
|
||||
if (const auto handlerFn = resolution->getPlaceholderHandler()) {
|
||||
result = result.get().transform([&](Type ty) {
|
||||
if (auto *oldTy = ty->getAs<PlaceholderType>()) {
|
||||
auto originator = oldTy->getOriginator();
|
||||
if (auto *repr = originator.dyn_cast<PlaceholderTypeRepr *>())
|
||||
if (auto newTy = handlerFn(ctx, repr))
|
||||
return newTy;
|
||||
}
|
||||
|
||||
return ty;
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2066,18 +2091,21 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
|
||||
options);
|
||||
|
||||
case TypeReprKind::Placeholder: {
|
||||
auto &ctx = getASTContext();
|
||||
// Fill in the placeholder if there's an appropriate handler.
|
||||
if (const auto handlerFn = resolution.getPlaceholderHandler())
|
||||
if (const auto ty = handlerFn(ctx, cast<PlaceholderTypeRepr>(repr)))
|
||||
return ty;
|
||||
if (resolution.getPlaceholderHandler())
|
||||
// For now, just form a `PlaceholderType` so that we can properly diagnose
|
||||
// invalid top-level placeholders. `ResolveTypeRequest::evaluate` will
|
||||
// take care of substituting the placeholder based on the caller-specified
|
||||
// handler.
|
||||
return PlaceholderType::get(getASTContext(),
|
||||
cast<PlaceholderTypeRepr>(repr));
|
||||
|
||||
// Complain if we're allowed to and bail out with an error.
|
||||
// If there's no handler, complain if we're allowed to and bail out with an
|
||||
// error.
|
||||
if (!options.contains(TypeResolutionFlags::SilenceErrors))
|
||||
ctx.Diags.diagnose(repr->getLoc(),
|
||||
getASTContext().Diags.diagnose(repr->getLoc(),
|
||||
diag::placeholder_type_not_allowed);
|
||||
|
||||
return ErrorType::get(resolution.getASTContext());
|
||||
return ErrorType::get(getASTContext());
|
||||
}
|
||||
|
||||
case TypeReprKind::Fixed:
|
||||
|
||||
@@ -281,7 +281,9 @@ public:
|
||||
/// \returns the \c null type on failure.
|
||||
using OpenUnboundGenericTypeFn = llvm::function_ref<Type(UnboundGenericType *)>;
|
||||
|
||||
/// A function reference used to handle a PlaceholderTypeRepr.
|
||||
/// A function reference used to handle a \c PlaceholderTypeRepr. If the
|
||||
/// function returns a null type, then the unmodified \c PlaceholderType will be
|
||||
/// used.
|
||||
using HandlePlaceholderTypeReprFn =
|
||||
llvm::function_ref<Type(ASTContext &, PlaceholderTypeRepr *)>;
|
||||
|
||||
|
||||
@@ -378,7 +378,9 @@ Type swift::performTypeResolution(TypeRepr *TyR, ASTContext &Ctx,
|
||||
},
|
||||
// FIXME: Don't let placeholder types escape type resolution.
|
||||
// For now, just return the placeholder type.
|
||||
PlaceholderType::get);
|
||||
[](auto &ctx, auto *originator) {
|
||||
return Type();
|
||||
});
|
||||
|
||||
Optional<DiagnosticSuppression> suppression;
|
||||
if (!ProduceDiagnostics)
|
||||
|
||||
@@ -1137,7 +1137,7 @@ func badTypes() {
|
||||
// rdar://34357545
|
||||
func unresolvedTypeExistential() -> Bool {
|
||||
return (Int.self==_{})
|
||||
// expected-error@-1 {{type of expression is ambiguous without more context}}
|
||||
// expected-error@-1 {{placeholders are not allowed as top-level types}}
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
let x: _ = 0
|
||||
let x: _ = 0 // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let x2 = x
|
||||
let dict1: [_: Int] = ["hi": 0]
|
||||
let dict2: [Character: _] = ["h": 0]
|
||||
@@ -9,8 +9,8 @@ let arr = [_](repeating: "hi", count: 3)
|
||||
|
||||
func foo(_ arr: [_] = [0]) {} // expected-error {{placeholder type not allowed here}}
|
||||
|
||||
let foo = _.foo // expected-error {{could not infer type for placeholder}}
|
||||
let zero: _ = .zero // expected-error {{cannot infer contextual base in reference to member 'zero'}}
|
||||
let foo = _.foo // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let zero: _ = .zero // expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
struct S<T> {
|
||||
var x: T
|
||||
@@ -48,9 +48,10 @@ func dictionary<K, V>(ofType: [K: V].Type) -> [K: V] { [:] }
|
||||
|
||||
let _: [String: _] = dictionary(ofType: [_: Int].self)
|
||||
let _: [_: _] = dictionary(ofType: [String: Int].self)
|
||||
let _: [String: Int] = dictionary(ofType: _.self)
|
||||
let _: [String: Int] = dictionary(ofType: _.self) // expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
let _: @convention(c) _ = { 0 } // expected-error {{@convention attribute only applies to function types}}
|
||||
// expected-error@-1 {{placeholders are not allowed as top-level types}}
|
||||
let _: @convention(c) (_) -> _ = { (x: Double) in 0 }
|
||||
let _: @convention(c) (_) -> Int = { (x: Double) in 0 }
|
||||
|
||||
@@ -98,18 +99,18 @@ extension Bar {
|
||||
}
|
||||
|
||||
// FIXME: We should probably have better diagnostics for these situations--the user probably meant to use implicit member syntax
|
||||
let _: Int = _() // expected-error {{type of expression is ambiguous without more context}}
|
||||
let _: () -> Int = { _() } // expected-error {{unable to infer closure type in the current context}}
|
||||
let _: Int = _.init() // expected-error {{could not infer type for placeholder}}
|
||||
let _: () -> Int = { _.init() } // expected-error {{could not infer type for placeholder}}
|
||||
let _: Int = _() // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let _: () -> Int = { _() } // expected-error {{unable to infer closure type in the current context}} expected-error {{placeholders are not allowed as top-level types}}
|
||||
let _: Int = _.init() // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let _: () -> Int = { _.init() } // expected-error {{unable to infer closure type in the current context}} expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
func returnsInt() -> Int { _() } // expected-error {{type of expression is ambiguous without more context}}
|
||||
func returnsIntClosure() -> () -> Int { { _() } } // expected-error {{unable to infer closure type in the current context}}
|
||||
func returnsInt2() -> Int { _.init() } // expected-error {{could not infer type for placeholder}}
|
||||
func returnsIntClosure2() -> () -> Int { { _.init() } } // expected-error {{could not infer type for placeholder}}
|
||||
func returnsInt() -> Int { _() } // expected-error {{placeholders are not allowed as top-level types}}
|
||||
func returnsIntClosure() -> () -> Int { { _() } } // expected-error {{unable to infer closure type in the current context}} expected-error {{placeholders are not allowed as top-level types}}
|
||||
func returnsInt2() -> Int { _.init() } // expected-error {{placeholders are not allowed as top-level types}}
|
||||
func returnsIntClosure2() -> () -> Int { { _.init() } } // expected-error {{unable to infer closure type in the current context}} expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
let _: Int.Type = _ // expected-error {{'_' can only appear in a pattern or on the left side of an assignment}}
|
||||
let _: Int.Type = _.self
|
||||
let _: Int.Type = _.self // expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
struct SomeSuperLongAndComplexType {}
|
||||
func getSomething() -> SomeSuperLongAndComplexType? { .init() }
|
||||
@@ -135,13 +136,13 @@ let _ = [_].otherStaticMember.method()
|
||||
func f(x: Any, arr: [Int]) {
|
||||
// FIXME: Better diagnostics here. Maybe we should suggest replacing placeholders with 'Any'?
|
||||
|
||||
if x is _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if x is _ {} // expected-error {{placeholders are not allowed as top-level types}}
|
||||
if x is [_] {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if x is () -> _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if let y = x as? _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if let y = x as? _ {} // expected-error {{placeholders are not allowed as top-level types}}
|
||||
if let y = x as? [_] {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if let y = x as? () -> _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
let y1 = x as! _ // expected-error {{type of expression is ambiguous without more context}}
|
||||
let y1 = x as! _ // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let y2 = x as! [_] // expected-error {{type of expression is ambiguous without more context}}
|
||||
let y3 = x as! () -> _ // expected-error {{type of expression is ambiguous without more context}}
|
||||
|
||||
@@ -154,13 +155,13 @@ func f(x: Any, arr: [Int]) {
|
||||
case let y as () -> _: break // expected-error {{placeholder type not allowed here}}
|
||||
}
|
||||
|
||||
if arr is _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if arr is _ {} // expected-error {{placeholders are not allowed as top-level types}}
|
||||
if arr is [_] {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if arr is () -> _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if let y = arr as? _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if let y = arr as? _ {} // expected-error {{placeholders are not allowed as top-level types}}
|
||||
if let y = arr as? [_] {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
if let y = arr as? () -> _ {} // expected-error {{type of expression is ambiguous without more context}}
|
||||
let y1 = arr as! _ // expected-error {{type of expression is ambiguous without more context}}
|
||||
let y1 = arr as! _ // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let y2 = arr as! [_] // expected-error {{type of expression is ambiguous without more context}}
|
||||
let y3 = arr as! () -> _ // expected-error {{type of expression is ambiguous without more context}}
|
||||
|
||||
@@ -186,15 +187,18 @@ struct Just<Output>: Publisher {
|
||||
struct SetFailureType<Output, Failure>: Publisher {}
|
||||
|
||||
extension Publisher {
|
||||
func setFailureType<T>(to: T.Type) -> SetFailureType<Output, T> { // expected-note {{in call to function 'setFailureType(to:)'}}
|
||||
func setFailureType<T>(to: T.Type) -> SetFailureType<Output, T> {
|
||||
return .init()
|
||||
}
|
||||
}
|
||||
|
||||
let _: SetFailureType<Int, String> = Just<Int>().setFailureType(to: _.self)
|
||||
let _: SetFailureType<Int, String> = Just<Int>().setFailureType(to: _.self) // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let _: SetFailureType<Int, [String]> = Just<Int>().setFailureType(to: [_].self)
|
||||
let _: SetFailureType<Int, (String) -> Double> = Just<Int>().setFailureType(to: ((_) -> _).self)
|
||||
let _: SetFailureType<Int, (String, Double)> = Just<Int>().setFailureType(to: (_, _).self)
|
||||
|
||||
// TODO: Better error message here? Would be nice if we could point to the placeholder...
|
||||
let _: SetFailureType<Int, String> = Just<Int>().setFailureType(to: _.self).setFailureType(to: String.self) // expected-error {{generic parameter 'T' could not be inferred}}
|
||||
let _: SetFailureType<Int, String> = Just<Int>().setFailureType(to: _.self).setFailureType(to: String.self) // expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
let _: (_) = 0 as Int // expected-error {{placeholders are not allowed as top-level types}}
|
||||
let _: Int = 0 as (_) // expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
@@ -865,7 +865,7 @@ func r20802757(_ z: inout Int = &g20802757) { // expected-error {{cannot provide
|
||||
print(z)
|
||||
}
|
||||
|
||||
_ = _.foo // expected-error {{could not infer type for placeholder}}
|
||||
_ = _.foo // expected-error {{placeholders are not allowed as top-level types}}
|
||||
|
||||
// <rdar://problem/22211854> wrong arg list crashing sourcekit
|
||||
func r22211854() {
|
||||
|
||||
Reference in New Issue
Block a user