diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 4ec04085af10f..f4d91d487cc5b 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7523,13 +7523,6 @@ ERROR(result_builder_buildpartialblock_accumulated_not_accessible,none, "expression shuffles the elements of this tuple; " "this behavior is deprecated", ()) -//------------------------------------------------------------------------------ -// MARK: Implicit conversion diagnostics -//------------------------------------------------------------------------------ -ERROR(cannot_implicitly_convert_in_optional_context,none, - "cannot implicitly convert value of type %0 to expected type %1", - (Type, Type)) - //------------------------------------------------------------------------------ // MARK: marker protocol diagnostics //------------------------------------------------------------------------------ diff --git a/include/swift/AST/SimpleRequest.h b/include/swift/AST/SimpleRequest.h index 83eac4a9ebf9e..766b33eaec2b5 100644 --- a/include/swift/AST/SimpleRequest.h +++ b/include/swift/AST/SimpleRequest.h @@ -57,7 +57,7 @@ enum class RequestFlags { /// incremental dependency pair and defines a new dependency scope. /// /// This bit is optional. High-level requests - /// (e.g. \c TypeCheckSourceFileRequest) will require it. + /// (e.g. \c TypeCheckPrimaryFileRequest) will require it. /// /// For further discussion on incremental dependencies /// see DependencyAnalysis.md. diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 815fb92564ebc..6b8fb2a58cc00 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -3300,9 +3300,9 @@ class ApplyAccessNoteRequest void cacheResult(evaluator::SideEffect value) const; }; -class TypeCheckSourceFileRequest +class TypeCheckPrimaryFileRequest : public SimpleRequest< - TypeCheckSourceFileRequest, evaluator::SideEffect(SourceFile *), + TypeCheckPrimaryFileRequest, evaluator::SideEffect(SourceFile *), RequestFlags::SeparatelyCached | RequestFlags::DependencySource> { public: using SimpleRequest::SimpleRequest; diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index cee89e508b8e1..6105588880e76 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -424,7 +424,7 @@ SWIFT_REQUEST(TypeChecker, HasDefaultInitRequest, bool(NominalTypeDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, SynthesizeDefaultInitRequest, ConstructorDecl *(NominalTypeDecl *), Cached, NoLocationInfo) -SWIFT_REQUEST(TypeChecker, TypeCheckSourceFileRequest, +SWIFT_REQUEST(TypeChecker, TypeCheckPrimaryFileRequest, bool(SouceFile *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, ConformanceAccessScopeRequest, ConformanceAccessScope(DeclContext *, ProtocolDecl *), diff --git a/include/swift/Sema/ConstraintLocator.h b/include/swift/Sema/ConstraintLocator.h index 4bbc583804a2d..edec6a1f22344 100644 --- a/include/swift/Sema/ConstraintLocator.h +++ b/include/swift/Sema/ConstraintLocator.h @@ -1275,7 +1275,7 @@ class ConstraintLocatorBuilder { auto last = std::find_if( path.rbegin(), path.rend(), [](LocatorPathElt &elt) -> bool { - return elt.getKind() != ConstraintLocator::OptionalPayload && + return elt.getKind() != ConstraintLocator::OptionalInjection && elt.getKind() != ConstraintLocator::GenericArgument; }); diff --git a/include/swift/Sema/ConstraintLocatorPathElts.def b/include/swift/Sema/ConstraintLocatorPathElts.def index cb752023a9d44..a8b0bc15e55c7 100644 --- a/include/swift/Sema/ConstraintLocatorPathElts.def +++ b/include/swift/Sema/ConstraintLocatorPathElts.def @@ -153,8 +153,8 @@ CUSTOM_LOCATOR_PATH_ELT(OpenedGeneric) /// type at the base of the locator. CUSTOM_LOCATOR_PATH_ELT(OpenedOpaqueArchetype) -/// An optional payload. -SIMPLE_LOCATOR_PATH_ELT(OptionalPayload) +/// The optional payload in an optional injection, ie a T -> T? conversion. +SIMPLE_LOCATOR_PATH_ELT(OptionalInjection) /// The parent of a nested type. SIMPLE_LOCATOR_PATH_ELT(ParentType) diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 94fe00e139eaf..c359a4021818d 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1655,16 +1655,16 @@ void RenamedDeclRequest::cacheResult(ValueDecl *value) const { } //----------------------------------------------------------------------------// -// TypeCheckSourceFileRequest computation. +// TypeCheckPrimaryFileRequest computation. //----------------------------------------------------------------------------// -evaluator::DependencySource TypeCheckSourceFileRequest::readDependencySource( +evaluator::DependencySource TypeCheckPrimaryFileRequest::readDependencySource( const evaluator::DependencyRecorder &e) const { return std::get<0>(getStorage()); } std::optional -TypeCheckSourceFileRequest::getCachedResult() const { +TypeCheckPrimaryFileRequest::getCachedResult() const { auto *SF = std::get<0>(getStorage()); if (SF->ASTStage == SourceFile::TypeChecked) return std::make_tuple<>(); @@ -1672,7 +1672,7 @@ TypeCheckSourceFileRequest::getCachedResult() const { return std::nullopt; } -void TypeCheckSourceFileRequest::cacheResult(evaluator::SideEffect) const { +void TypeCheckPrimaryFileRequest::cacheResult(evaluator::SideEffect) const { auto *SF = std::get<0>(getStorage()); // Verify that we've checked types correctly. diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 1730bb425065e..6182619a525b0 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -940,7 +940,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { while (!path.empty()) { auto last = path.back(); - if (last.is() || + if (last.is() || last.is() || last.is()) { path = path.drop_back(); @@ -2837,22 +2837,6 @@ bool ContextualFailure::diagnoseAsError() { break; } - case ConstraintLocator::OptionalPayload: { - // If this is an attempt at a Double <-> CGFloat conversion - // through optional chaining, let's produce a tailored diagnostic. - if (isExpr(getAnchor())) { - if ((fromType->isDouble() || fromType->isCGFloat()) && - (toType->isDouble() || toType->isCGFloat())) { - fromType = OptionalType::get(fromType); - toType = OptionalType::get(toType); - diagnostic = diag::cannot_implicitly_convert_in_optional_context; - break; - } - } - - return false; - } - case ConstraintLocator::EnumPatternImplicitCastMatch: { // In this case, the types are reversed, as we are checking whether we // can convert the pattern type to the context type. diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index b4a441cceec3c..ee5eda8b56947 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -4672,7 +4672,7 @@ generateForEachStmtConstraints(ConstraintSystem &cs, DeclContext *dc, // Add a conversion constraint between the element type of the sequence // and the type of the element pattern. auto *elementTypeLoc = cs.getConstraintLocator( - elementLocator, ConstraintLocator::OptionalPayload); + elementLocator, ConstraintLocator::OptionalInjection); auto elementType = cs.createTypeVariable(elementTypeLoc, /*flags=*/0); { diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 80156cfa0b607..66f74ae5a9cf9 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3323,11 +3323,11 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, SmallVector path; locator.getLocatorParts(path); - // Find the last path element, skipping OptionalPayload elements + // Find the last path element, skipping OptionalInjection elements // so that we allow this exception in cases of optional injection. auto last = std::find_if( path.rbegin(), path.rend(), [](LocatorPathElt &elt) -> bool { - return elt.getKind() != ConstraintLocator::OptionalPayload; + return elt.getKind() != ConstraintLocator::OptionalInjection; }); auto &ctx = getASTContext(); @@ -3431,12 +3431,12 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, // Find the last path element, skipping GenericArgument elements // so that we allow this exception in cases of optional types, and - // skipping OptionalPayload elements so that we allow this + // skipping OptionalInjection elements so that we allow this // exception in cases of optional injection. auto last = std::find_if( path.rbegin(), path.rend(), [](LocatorPathElt &elt) -> bool { return elt.getKind() != ConstraintLocator::GenericArgument && - elt.getKind() != ConstraintLocator::OptionalPayload; + elt.getKind() != ConstraintLocator::OptionalInjection; }); if (last != path.rend()) { @@ -3484,7 +3484,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, // // func foo(_: ((Int, Int) -> Void)?) {} // _ = foo { _ in } <- missing second closure parameter. - if (loc->isLastElement()) { + if (loc->isLastElement()) { auto path = loc->getPath(); loc = getConstraintLocator(loc->getAnchor(), path.drop_back()); } @@ -4144,7 +4144,7 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2, // `value-to-optional` or `optional-to-optional` conversion // associated with them (expected argument is `AnyObject?`). if (!path.empty() && - (path.back().is() || + (path.back().is() || path.back().is())) path.pop_back(); @@ -4200,7 +4200,7 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2, // If the path ends at `optional payload` it means that this // check is part of an implicit value-to-optional conversion, // and it could be safely dropped. - if (!path.empty() && path.back().is()) + if (!path.empty() && path.back().is()) path.pop_back(); // Determine whether this conformance mismatch is @@ -6495,7 +6495,7 @@ bool ConstraintSystem::repairFailures( // If the mismatch is a part of either optional-to-optional or // value-to-optional conversions, let's allow fix refer to a complete // top level type and not just a part of it. - if (tupleLocator->findLast()) + if (tupleLocator->findLast()) break; if (tupleLocator->isForContextualType()) { @@ -6636,7 +6636,7 @@ bool ConstraintSystem::repairFailures( break; } - case ConstraintLocator::OptionalPayload: { + case ConstraintLocator::OptionalInjection: { if (lhs->isPlaceholder() || rhs->isPlaceholder()) return true; @@ -7446,7 +7446,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, // Look through all value-to-optional promotions to allow // conversions like Double -> CGFloat?? and vice versa. // T -> Optional - if (location.endsWith() || + if (location.endsWith() || location.endsWith()) { SmallVector path; auto anchor = location.getLocatorParts(path); @@ -7456,7 +7456,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, path.erase(llvm::remove_if( path, [](const LocatorPathElt &elt) { - return elt.is() || + return elt.is() || elt.is(); }), path.end()); @@ -14608,7 +14608,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( if (generic2->getDecl()->isOptionalDecl()) { auto result = matchTypes( type1, generic2->getGenericArgs()[0], matchKind, subflags, - locator.withPathElement(ConstraintLocator::OptionalPayload)); + locator.withPathElement(ConstraintLocator::OptionalInjection)); if (!(shouldAttemptFixes() && result.isFailure())) return result; diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index 44cb8ab171b5b..ce8205e45f9df 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -52,7 +52,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const { case ConstraintLocator::ResultBuilderBodyResult: case ConstraintLocator::InstanceType: case ConstraintLocator::AutoclosureResult: - case ConstraintLocator::OptionalPayload: + case ConstraintLocator::OptionalInjection: case ConstraintLocator::Member: case ConstraintLocator::MemberRefBase: case ConstraintLocator::UnresolvedMember: @@ -176,8 +176,8 @@ void LocatorPathElt::dump(raw_ostream &out) const { out << "apply function"; break; - case ConstraintLocator::OptionalPayload: - out << "optional payload"; + case ConstraintLocator::OptionalInjection: + out << "optional injection"; break; case ConstraintLocator::ApplyArgToParam: { diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 8a614baef458a..1aefa14596efc 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -644,7 +644,7 @@ ConstraintLocator *ConstraintSystem::getImplicitValueConversionLocator( // Drop any value-to-optional conversions that were applied along the // way to reach this one. while (!path.empty()) { - if (path.back().is()) { + if (path.back().is()) { path.pop_back(); continue; } @@ -3772,7 +3772,7 @@ void constraints::simplifyLocator(ASTNode &anchor, case ConstraintLocator::Witness: case ConstraintLocator::WrappedValue: - case ConstraintLocator::OptionalPayload: + case ConstraintLocator::OptionalInjection: case ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice: case ConstraintLocator::FallbackType: case ConstraintLocator::KeyPathSubscriptIndex: @@ -4068,7 +4068,7 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const { // Look for the apply-arg-to-param element in the locator's path. We may // have to look through other elements that are generated from an argument // conversion such as GenericArgument for an optional-to-optional conversion, - // and OptionalPayload for a value-to-optional conversion. + // and OptionalInjection for a value-to-optional conversion. auto iter = path.rbegin(); auto applyArgElt = locator->findLast(iter); if (!applyArgElt) @@ -4343,7 +4343,7 @@ bool ConstraintSystem::isArgumentOfImportedDecl( // locator elements at the end of the path, they came from // either value-to-optional promotion or optional-to-optional // conversion. - if (last.is() || + if (last.is() || last.is()) { path.pop_back(); continue; diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 8c6ed7edce4b9..a3fc274b3311e 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -3991,7 +3991,7 @@ class DeclChecker : public DeclVisitor { return; } - // Record a dependency from TypeCheckSourceFileRequest to + // Record a dependency from TypeCheckPrimaryFileRequest to // ExtendedNominalRequest, since the call to getExtendedNominal() // above doesn't record a dependency when reading a cached value. ED->computeExtendedNominal(); diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 38c61b4893ed5..667393e38b94b 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -251,11 +251,11 @@ void swift::performTypeChecking(SourceFile &SF) { } return (void)evaluateOrDefault(SF.getASTContext().evaluator, - TypeCheckSourceFileRequest{&SF}, {}); + TypeCheckPrimaryFileRequest{&SF}, {}); } evaluator::SideEffect -TypeCheckSourceFileRequest::evaluate(Evaluator &eval, SourceFile *SF) const { +TypeCheckPrimaryFileRequest::evaluate(Evaluator &eval, SourceFile *SF) const { assert(SF && "Source file cannot be null!"); assert(SF->ASTStage != SourceFile::TypeChecked && "Should not be re-typechecking this file!"); diff --git a/test/Constraints/implicit_double_cgfloat_conversion.swift b/test/Constraints/implicit_double_cgfloat_conversion.swift index a70f3c6dfd39f..94bbb3659d265 100644 --- a/test/Constraints/implicit_double_cgfloat_conversion.swift +++ b/test/Constraints/implicit_double_cgfloat_conversion.swift @@ -20,7 +20,7 @@ func test_returns_cgfloat(_: Double) -> CGFloat { let d: Double = 0.0 let cgf: CGFloat = 0.0 -// CHECK: test_various_situations_converting_to_cgfloat() +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion038test_various_situations_converting_to_C0yyF : $@convention(thin) () -> () { func test_various_situations_converting_to_cgfloat() { // CHECK: function_ref @$s12CoreGraphics7CGFloatVyACSdcfC : $@convention(method) (Double, @thin CGFloat.Type) -> CGFloat let _: CGFloat = d @@ -58,6 +58,7 @@ func test_various_situations_converting_to_cgfloat() { test_to_cgfloat(test_returns_double(d)) // Two conversions // Overloads with CGFloat are preferred if that allows to avoid any implicit conversions. + // CHECK-LABEL: sil private [ossa] @$s34implicit_double_cgfloat_conversion038test_various_situations_converting_to_C0yyF0E23_loading_tuple_elementsL_6valuesy12CoreGraphics7CGFloatV_AGtz_tF : $@convention(thin) (@inout (CGFloat, CGFloat)) -> () { func test_loading_tuple_elements(values: inout (CGFloat, CGFloat)) { struct S { init(x: Double, y: Double) {} @@ -69,7 +70,7 @@ func test_various_situations_converting_to_cgfloat() { } } -// CHECK: test_various_situations_converting_to_double() +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion038test_various_situations_converting_to_B0yyF : $@convention(thin) () -> () { func test_various_situations_converting_to_double() { // function_ref @$sSd12CoreGraphicsEySdAA7CGFloatVcfC : $@convention(method) (CGFloat, @thin Double.Type) -> Double let _: Double = cgf @@ -102,12 +103,14 @@ func test_various_situations_converting_to_double() { test_from_cgfloat(test_returns_cgfloat(cgf)) // Two conversions - argument and result. } +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion31test_conversions_with_optionals1vy12CoreGraphics7CGFloatVSg_tF : $@convention(thin) (Optional) -> () { func test_conversions_with_optionals(v: CGFloat?) { // CHECK: function_ref @$s34implicit_double_cgfloat_conversion31test_conversions_with_optionals1vy12CoreGraphics7CGFloatVSg_tFAFyKXEfu_ // CHECK: function_ref @$sSd12CoreGraphicsEySdAA7CGFloatVcfC : $@convention(method) (CGFloat, @thin Double.Type) -> Double let _: Double = (v ?? 0) } +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion48test_static_members_are_contextually_convertibleyyF : $@convention(thin) () -> () { func test_static_members_are_contextually_convertible() { struct S { static var testProp: CGFloat { 42 } @@ -125,6 +128,7 @@ func test_static_members_are_contextually_convertible() { } } +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion25test_narrowing_is_delayed1x1yySd_12CoreGraphics7CGFloatVtF : $@convention(thin) (Double, CGFloat) -> () { func test_narrowing_is_delayed(x: Double, y: CGFloat) { func test(_: CGFloat) {} @@ -181,6 +185,7 @@ extension CGFloat { } // Make sure that solution with no Double/CGFloat conversions is preferred +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion38test_no_ambiguity_with_unary_operators5width6heighty12CoreGraphics7CGFloatV_AGtF : $@convention(thin) (CGFloat, CGFloat) -> () { func test_no_ambiguity_with_unary_operators(width: CGFloat, height: CGFloat) { struct R { init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) {} @@ -193,6 +198,7 @@ func test_no_ambiguity_with_unary_operators(width: CGFloat, height: CGFloat) { _ = R(x: width / 4, y: -height / 2, width: width, height: height) } +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion40test_conversions_with_optional_promotion1d3cgfySd_12CoreGraphics7CGFloatVtF : $@convention(thin) (Double, CGFloat) -> () { func test_conversions_with_optional_promotion(d: Double, cgf: CGFloat) { func test_double(_: Double??, _: Double???) {} func test_cgfloat(_: CGFloat??, _: CGFloat???) {} @@ -332,6 +338,7 @@ func test_implicit_conversion_clash_with_partial_application_check() { } // rdar://99352676 +// CHECK-LABEL: sil hidden [ossa] @$s34implicit_double_cgfloat_conversion20test_init_validationyyF : $@convention(thin) () -> () { func test_init_validation() { class Foo { static let bar = 100.0 diff --git a/test/Frontend/debug-cycles.swift b/test/Frontend/debug-cycles.swift index 709eedb3acf23..768ae726b53e8 100644 --- a/test/Frontend/debug-cycles.swift +++ b/test/Frontend/debug-cycles.swift @@ -5,7 +5,7 @@ class Outer2: Outer2.Inner { class Inner {} } // CHECK:===CYCLE DETECTED=== -// CHECK-NEXT: `--TypeCheckSourceFileRequest({{.*}}) +// CHECK-NEXT: `--TypeCheckPrimaryFileRequest({{.*}}) // CHECK-NEXT: `--SuperclassDeclRequest({{.*}}) // CHECK-NEXT: `--InheritedDeclsReferencedRequest({{.*}}) // CHECK-NEXT: `--QualifiedLookupRequest({{.*}})