From 58be8eb56053cd1da639e1a305e02d9508f44fbb Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:23:33 -0300 Subject: [PATCH 01/24] [Diagnostics] Adding diagnostic message for redundant coercions --- include/swift/AST/DiagnosticsSema.def | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index abc49a1d3a5a7..1772dd64640c0 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -998,23 +998,29 @@ ERROR(super_initializer_not_in_initializer,none, WARNING(isa_is_always_true,none, "'%0' test is always true", (StringRef)) WARNING(isa_is_foreign_check,none, - "'is' test is always true because %0 is a Core Foundation type", - (Type)) + "'is' test is always true because %0 is a Core Foundation type", + (Type)) WARNING(conditional_downcast_coercion,none, - "conditional cast from %0 to %1 always succeeds", - (Type, Type)) + "conditional cast from %0 to %1 always succeeds", + (Type, Type)) WARNING(literal_conditional_downcast_to_coercion,none, "conditional downcast from literal to %0 always fails; " "consider using 'as' coercion", (Type)) +WARNING(unnecessary_same_type_coercion,none, + "redundant cast to %0 has no effect", + (Type)) +WARNING(unnecessary_same_typealias_type_coercion,none, + "redundant cast from %0 to %1 has no effect", + (Type, Type)) + WARNING(forced_downcast_noop,none, "forced cast of %0 to same type has no effect", (Type)) - WARNING(forced_downcast_coercion,none, - "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?", - (Type, Type)) + "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?", + (Type, Type)) // Note: the Boolean at the end indicates whether bridging is required after // the cast. From 9408302ad8f969db126cedf97354089ac2a0f8be Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:30:48 -0300 Subject: [PATCH 02/24] [ConstraintLocator] Creating ExplicitTypeCoercion constraint locator --- lib/Sema/ConstraintLocator.cpp | 5 +++++ lib/Sema/ConstraintLocatorPathElts.def | 3 +++ 2 files changed, 8 insertions(+) diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index c5b4a864e4e05..ec87b03ae2caf 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -76,6 +76,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const { case ConstraintLocator::KeyPathValue: case ConstraintLocator::KeyPathComponentResult: case ConstraintLocator::Condition: + case ConstraintLocator::ExplicitTypeCoercion: case ConstraintLocator::DynamicCallable: case ConstraintLocator::ImplicitCallAsFunction: case ConstraintLocator::TernaryBranch: @@ -445,6 +446,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) const { case Condition: out << "condition expression"; break; + + case ExplicitTypeCoercion: + out << "type coercion"; + break; case DynamicCallable: out << "implicit call to @dynamicCallable method"; diff --git a/lib/Sema/ConstraintLocatorPathElts.def b/lib/Sema/ConstraintLocatorPathElts.def index 67228bcbc5591..b3702d2fa52a0 100644 --- a/lib/Sema/ConstraintLocatorPathElts.def +++ b/lib/Sema/ConstraintLocatorPathElts.def @@ -176,6 +176,9 @@ CUSTOM_LOCATOR_PATH_ELT(Witness) /// The condition associated with 'if' expression or ternary operator. SIMPLE_LOCATOR_PATH_ELT(Condition) +/// An explicit type coercion. +SIMPLE_LOCATOR_PATH_ELT(ExplicitTypeCoercion) + SIMPLE_LOCATOR_PATH_ELT(DynamicCallable) /// The 'true' or 'false' branch of a ternary operator. From 08c886e9f3ffc4841d816c737ab690c5497fa5d8 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:34:02 -0300 Subject: [PATCH 03/24] [CSDiagnostics] Creating RemoveUnnecessaryCoercion Fix and UnnecessaryCoercionFailure diagnostics --- lib/Sema/CSDiagnostics.cpp | 29 ++++++++++++++ lib/Sema/CSDiagnostics.h | 21 +++++++++++ lib/Sema/CSFix.cpp | 77 ++++++++++++++++++++++++++++++++++++++ lib/Sema/CSFix.h | 22 +++++++++++ 4 files changed, 149 insertions(+) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 80bcf26c217d0..787b7df62e3a6 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -5540,6 +5540,35 @@ bool ThrowingFunctionConversionFailure::diagnoseAsError() { return true; } +bool UnnecessaryCoercionFailure::diagnoseAsError() { + auto expr = cast(getAnchor()); + auto sourceRange = + SourceRange(expr->getLoc(), expr->getCastTypeLoc().getSourceRange().End); + auto castType = expr->getCastTypeLoc().getType(); + + if (isa(getFromType().getPointer()) && + isa(getToType().getPointer())) { + auto fromTypeAlias = cast(getFromType().getPointer()); + auto toTypeAlias = cast(getToType().getPointer()); + // If the typealias are different, we need a warning mentioning both types. + if (fromTypeAlias->getDecl() != toTypeAlias->getDecl()) { + emitDiagnostic(expr->getLoc(), + diag::unnecessary_same_typealias_type_coercion, + getFromType(), castType) + .fixItRemove(sourceRange); + } else { + emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion, + castType) + .fixItRemove(sourceRange); + } + } else { + emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion, + castType) + .fixItRemove(sourceRange); + } + return true; +} + bool InOutConversionFailure::diagnoseAsError() { auto *locator = getLocator(); auto path = locator->getPath(); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index e1c925322d495..85bf872ea8c96 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -1791,6 +1791,27 @@ class ExpandArrayIntoVarargsFailure final : public ContextualFailure { void tryDropArrayBracketsFixIt(const Expr *anchor) const; }; +/// Diagnose a situation where there is an explicit type coercion +/// to the same type e.g.: +/// +/// ```swift +/// Double(1) as Double // redundant cast to 'Double' has no effect +/// 1 as Double as Double // redundant cast to 'Double' has no effect +/// let string = "String" +/// let s = string as String // redundant cast to 'String' has no effect +/// ``` +class UnnecessaryCoercionFailure final + : public ContextualFailure { + +public: + UnnecessaryCoercionFailure(ConstraintSystem &cs, + Type fromType, Type toType, + ConstraintLocator *locator) + : ContextualFailure(cs, fromType, toType, locator) {} + + bool diagnoseAsError() override; +}; + /// Diagnose a situation there is a mismatch between argument and parameter /// types e.g.: /// diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 80cc9fc225ad6..c271db333ba58 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1136,6 +1136,83 @@ IgnoreContextualType *IgnoreContextualType::create(ConstraintSystem &cs, IgnoreContextualType(cs, resultTy, specifiedTy, locator); } +bool RemoveUnnecessaryCoercion::diagnose(bool asNote) const { + auto &cs = getConstraintSystem(); + UnnecessaryCoercionFailure failure(cs, getFromType(), getToType(), + getLocator()); + return failure.diagnose(asNote); +} + +bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, + Type toType, + ConstraintLocatorBuilder locator) { + auto &ctx = cs.getASTContext(); + if (ctx.LangOpts.DisableRedundantCoercionWarning) + return false; + + auto last = locator.last(); + bool isExplicitCoercion = + last && last->is(); + if (!isExplicitCoercion) + return false; + + auto expr = cast(locator.getAnchor()); + + // Check to ensure the from and to types are equal the cast type. + // This is required to handle cases where the conversion is done + // using compiler intrinsics e.g. _HasCustomAnyHashableRepresentation + // to AnyHashable where if we coerce a generic type that conforms to + // this protocol to AnyHashable we match equal types here, but the + // explicit coercion is still required. + auto castType = cs.getType(expr->getCastTypeLoc()); + if (!fromType->isEqual(castType) && !castType->hasTypeVariable()) + return false; + + // Fixed type was already applied to the subEpxr. + if (expr->getSubExpr()->getType()) + return false; + + auto toTypeRepr = expr->getCastTypeLoc().getTypeRepr(); + + // Don't emit this diagnostic for Implicitly unwrapped optional types + // e.g. i as Int! + if (isa(toTypeRepr)) + return false; + + // If we are dealing with an OverloadedDeclRefExpr the coercion + // is probably being used to match a specific overload function type. + bool hasOverloadedDeclRefSubExpr = false; + expr->forEachChildExpr([&](Expr *childExpr) -> Expr *{ + if (isa(childExpr)) { + hasOverloadedDeclRefSubExpr = true; + return nullptr; + } + return childExpr; + }); + + if (hasOverloadedDeclRefSubExpr) + return false; + + auto coercedType = cs.getType(expr->getSubExpr()); + if (auto *typeVariable = coercedType->getAs()) { + // Only diagnose if we have all type variables resolved in the system. + if (cs.hasFreeTypeVariables()) + return false; + + if (auto *typeSourceLocator = cs.getTypeVariableBindingLocator(typeVariable)) { + // If the type variable binding source locator is the same the + // contextual type equality is coming from this coercion. + if (typeSourceLocator == cs.getConstraintLocator(locator)) + return false; + } + } + + auto *fix = new (cs.getAllocator()) RemoveUnnecessaryCoercion( + cs, fromType, toType, cs.getConstraintLocator(locator)); + + return cs.recordFix(fix); +} + bool IgnoreAssignmentDestinationType::diagnose(const Solution &solution, bool asNote) const { auto &cs = getConstraintSystem(); diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index 7bcaf50f85c65..f933d64691725 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -204,6 +204,10 @@ enum class FixKind : uint8_t { /// Allow a single tuple parameter to be matched with N arguments /// by forming all of the given arguments into a single tuple. AllowTupleSplatForSingleParameter, + + /// Remove an unnecessary coercion ('as') if the types are already equal. + /// e.g. Double(1) as Double + RemoveUnnecessaryCoercion, /// Allow a single argument type mismatch. This is the most generic /// failure related to argument-to-parameter conversions. @@ -1561,6 +1565,24 @@ class IgnoreContextualType : public ContextualMismatch { ConstraintLocator *locator); }; +class RemoveUnnecessaryCoercion : public ContextualMismatch { +protected: + RemoveUnnecessaryCoercion(ConstraintSystem &cs, Type fromType, Type toType, + ConstraintLocator *locator) + : ContextualMismatch(cs, FixKind::RemoveUnnecessaryCoercion, fromType, + toType, locator, /*isWarning*/ true) {} + +public: + std::string getName() const override { + return "remove unnecessary explicit type coercion"; + } + + bool diagnose(bool asNote = false) const override; + + static bool attempt(ConstraintSystem &cs, Type fromType, Type toType, + ConstraintLocatorBuilder locator); +}; + class IgnoreAssignmentDestinationType final : public ContextualMismatch { IgnoreAssignmentDestinationType(ConstraintSystem &cs, Type sourceTy, Type destTy, ConstraintLocator *locator) From 428639fceb13a9aedc011328d1e2149012180497 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:36:32 -0300 Subject: [PATCH 04/24] [ConstraintSystem] Recording the type variables bindings and attempting RemoveUnnecessaryCoercion fix on match types --- lib/Sema/CSSimplify.cpp | 48 +++++++++++++++++++++++++++-------- lib/Sema/ConstraintSystem.cpp | 9 +++++++ lib/Sema/ConstraintSystem.h | 23 ++++++++++++++--- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 1608f19e49155..a2daf9c6f4403 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -1949,7 +1949,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, auto *typeVar = createTypeVariable(getConstraintLocator(argLoc), TVO_CanBindToNoEscape); params.emplace_back(typeVar); - assignFixedType(typeVar, input); + assignFixedType(typeVar, input, getConstraintLocator(argLoc)); }; { @@ -2825,7 +2825,7 @@ ConstraintSystem::matchTypesBindTypeVar( : getTypeMatchFailure(locator); } - assignFixedType(typeVar, type); + assignFixedType(typeVar, type, getConstraintLocator(locator)); return getTypeMatchSuccess(); } @@ -3424,7 +3424,8 @@ bool ConstraintSystem::repairFailures( }); }; - if (path.empty()) { + if (path.empty() || + path.back().is()) { if (!anchor) return false; @@ -4465,9 +4466,16 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, // let's defer it until later proper check. if (!(desugar1->is() && desugar2->is())) { - // If the types are obviously equivalent, we're done. - if (desugar1->isEqual(desugar2) && !isa(desugar2)) { - return getTypeMatchSuccess(); + if (desugar1->isEqual(desugar2)) { + if (kind == ConstraintKind::Conversion && + !flags.contains(TMF_ApplyingFix)) { + if (RemoveUnnecessaryCoercion::attempt(*this, type1, type2, + getConstraintLocator(locator))) { + return getTypeMatchFailure(locator); + } + } + if (!isa(desugar2)) + return getTypeMatchSuccess(); } } @@ -4554,9 +4562,10 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, if (auto *iot = type1->getAs()) { if (!rep2->getImpl().canBindToLValue()) return getTypeMatchFailure(locator); - assignFixedType(rep2, LValueType::get(iot->getObjectType())); + assignFixedType(rep2, LValueType::get(iot->getObjectType()), + getConstraintLocator(locator)); } else { - assignFixedType(rep2, type1); + assignFixedType(rep2, type1, getConstraintLocator(locator)); } return getTypeMatchSuccess(); } else if (typeVar1 && !typeVar2) { @@ -4569,9 +4578,10 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, if (auto *lvt = type2->getAs()) { if (!rep1->getImpl().canBindToInOut()) return getTypeMatchFailure(locator); - assignFixedType(rep1, InOutType::get(lvt->getObjectType())); + assignFixedType(rep1, InOutType::get(lvt->getObjectType()), + getConstraintLocator(locator)); } else { - assignFixedType(rep1, type2); + assignFixedType(rep1, type2, getConstraintLocator(locator)); } return getTypeMatchSuccess(); } if (typeVar1 && typeVar2) { @@ -4603,6 +4613,12 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, return matchTypesBindTypeVar(typeVar1, type2, kind, flags, locator, formUnsolvedResult); } + if (!typeVar2) { + // If type1 is a type varaible and type2 type is a fixed type, + // record this as the potential fixed type locator source. + recordTypeVariableBindingLocator(typeVar1, + getConstraintLocator(locator)); + } } // If the left-hand side of a 'sequence element' constraint @@ -10112,6 +10128,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::SpecifyClosureParameterType: case FixKind::SpecifyClosureReturnType: case FixKind::AddQualifierToAccessTopLevelName: + case FixKind::RemoveUnnecessaryCoercion: llvm_unreachable("handled elsewhere"); } @@ -10497,11 +10514,20 @@ void ConstraintSystem::addExplicitConversionConstraint( SmallVector constraints; auto locatorPtr = getConstraintLocator(locator); + ConstraintLocator *coerceLocator = locatorPtr; + + if (allowFixes && shouldAttemptFixes()) { + auto *anchor = locator.getAnchor(); + if (isa(anchor) && !anchor->isImplicit()) { + coerceLocator = + getConstraintLocator(anchor, LocatorPathElt::ExplicitTypeCoercion()); + } + } // Coercion (the common case). Constraint *coerceConstraint = Constraint::create(*this, ConstraintKind::Conversion, - fromType, toType, locatorPtr); + fromType, toType, coerceLocator); coerceConstraint->setFavored(); constraints.push_back(coerceConstraint); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 1214740c8d1d5..ca78c2ecb0cf8 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -155,6 +155,7 @@ bool ConstraintSystem::typeVarOccursInType(TypeVariableType *typeVar, } void ConstraintSystem::assignFixedType(TypeVariableType *typeVar, Type type, + ConstraintLocator *locator, bool updateState) { assert(!type->hasError() && "Should not be assigning a type involving ErrorType!"); @@ -198,6 +199,9 @@ void ConstraintSystem::assignFixedType(TypeVariableType *typeVar, Type type, } } + // Recording fixed type source locator for type variable. + recordTypeVariableBindingLocator(typeVar, locator); + // Notify the constraint graph. CG.bindTypeVariable(typeVar, type); addTypeVariableConstraintsToWorkList(typeVar); @@ -3830,6 +3834,11 @@ void constraints::simplifyLocator(ASTNode &anchor, path = path.slice(1); continue; } + + case ConstraintLocator::ExplicitTypeCoercion: { + path = path.slice(1); + continue; + } case ConstraintLocator::TernaryBranch: { auto branch = path[0].castTo(); diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index bc95ed45c0b55..1ca5996952ef4 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -2089,6 +2089,9 @@ class ConstraintSystem { SmallVector>, 4> OpenedTypes; + /// Intended to track information about type variable source binding locator. + llvm::DenseMap TypeVariableBindings; + /// The list of all generic requirements fixed along the current /// solver path. using FixedRequirement = @@ -2122,6 +2125,18 @@ class ConstraintSystem { /// A cache that stores the @dynamicCallable required methods implemented by /// types. llvm::DenseMap DynamicCallableCache; + + /// Records the current binding source locator for a given type variable in the system. + void recordTypeVariableBindingLocator(const TypeVariableType *typeVar, + const ConstraintLocator *sourceLocator) { + TypeVariableBindings[typeVar] = sourceLocator; + } + + /// Gets the current binding source locator for a given type variable in the system. + const ConstraintLocator * + getTypeVariableBindingLocator(const TypeVariableType *typeVar) { + return TypeVariableBindings[typeVar]; + } private: /// Describe the candidate expression for partial solving. @@ -3542,11 +3557,13 @@ class ConstraintSystem { /// /// \param type The fixed type to which the type variable will be bound. /// + /// \param locator The locator from where this fixed type comes from. + /// /// \param updateState Whether to update the state based on this binding. - /// False when we're only assigning a type as part of reconstructing + /// False when we're only assigning a type as part of reconstructing /// a complete solution from partial solutions. void assignFixedType(TypeVariableType *typeVar, Type type, - bool updateState = true); + ConstraintLocator *locator, bool updateState = true); /// Determine if the type in question is an Array and, if so, provide the /// element type of the array. @@ -5595,7 +5612,7 @@ class TypeVariableBinding { } bool attempt(ConstraintSystem &cs) const; - + void print(llvm::raw_ostream &Out, SourceManager *) const { PrintOptions PO; PO.PrintTypesForDebugging = true; From cd2d6ce710ae5deddc3b8f4b77c4316d214d2b0c Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:40:55 -0300 Subject: [PATCH 05/24] [CSSolver] Clean up type variable bindings in end of solver scope --- lib/Sema/CSSolver.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 8f0afc7b18b81..28c7cf58a2df1 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -90,7 +90,8 @@ Solution ConstraintSystem::finalize() { break; case FreeTypeVariableBinding::UnresolvedType: - assignFixedType(tv, ctx.TheUnresolvedType); + assignFixedType(tv, ctx.TheUnresolvedType, + tv->getImpl().getLocator()); break; } } @@ -204,8 +205,11 @@ void ConstraintSystem::applySolution(const Solution &solution) { // If we don't already have a fixed type for this type variable, // assign the fixed type from the solution. - if (!getFixedType(binding.first) && !binding.second->hasTypeVariable()) - assignFixedType(binding.first, binding.second, /*updateState=*/false); + if (!getFixedType(binding.first) && !binding.second->hasTypeVariable()) { + auto typeVar = binding.first; + assignFixedType(typeVar, binding.second, typeVar->getImpl().getLocator(), + /*updateState=*/false); + } } // Register overload choices. @@ -493,8 +497,11 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs) ConstraintSystem::SolverScope::~SolverScope() { // Erase the end of various lists. - while (cs.TypeVariables.size() > numTypeVariables) - cs.TypeVariables.pop_back(); + while (cs.TypeVariables.size() > numTypeVariables) { + auto typeVariable = cs.TypeVariables.pop_back_val(); + // Clear type variable source binding recorded in the current scope. + cs.TypeVariableBindings.erase(typeVariable); + } truncate(cs.ResolvedOverloads, numResolvedOverloads); From 9e0ff0a86433e2cbf6e76526f31325aa5a423a06 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:42:20 -0300 Subject: [PATCH 06/24] [Frontend] Creating compiler flag to disable the redundant coercion warning --- include/swift/Basic/LangOptions.h | 4 ++++ include/swift/Option/FrontendOptions.td | 13 ++++++++----- lib/Frontend/CompilerInvocation.cpp | 3 +++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 6531ecdf0e5c8..97a6b7a1a7dd6 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -303,6 +303,10 @@ namespace swift { /// If set to true, the diagnosis engine can assume the emitted diagnostics /// will be used in editor. This usually leads to more aggressive fixit. bool DiagnosticsEditorMode = false; + + /// If set to true, disable redundant coercions e.g. Double(1) as Double + /// warning diagnostics. + bool DisableRedundantCoercionWarning = false; /// Whether to enable Swift 3 @objc inference, e.g., for members of /// Objective-C-derived classes and 'dynamic' members. diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 5bd693d2ffe7d..712e7d50796d6 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -667,7 +667,7 @@ def prebuilt_module_cache_path_EQ : Alias; def force_public_linkage : Flag<["-"], "force-public-linkage">, - HelpText<"Force public linkage for private symbols. Used by LLDB.">; + HelpText<"Force public linkage for private symbols. Used by LLDB.">; def dump_api_path : Separate<["-"], "dump-api-path">, HelpText<"The path to output swift interface files for the compiled source files">; @@ -676,14 +676,17 @@ def group_info_path : Separate<["-"], "group-info-path">, HelpText<"The path to collect the group information of the compiled module">; def diagnostics_editor_mode : Flag<["-"], "diagnostics-editor-mode">, -HelpText<"Diagnostics will be used in editor">; + HelpText<"Diagnostics will be used in editor">; + +def disable_redundant_coercion_warning : Flag<["-"], "disable-redundant-coercion-warning">, + HelpText<"Disable redundant coercion warning diagnostic">; def validate_tbd_against_ir_EQ: Joined<["-"], "validate-tbd-against-ir=">, - HelpText<"Compare the symbols in the IR against the TBD file that would be generated.">, - MetaVarName<"">; + HelpText<"Compare the symbols in the IR against the TBD file that would be generated.">, + MetaVarName<"">; def bypass_batch_mode_checks: Flag<["-"], "bypass-batch-mode-checks">, - HelpText<"Bypass checks for batch-mode errors.">; + HelpText<"Bypass checks for batch-mode errors.">; def enable_verify_exclusivity : Flag<["-"], "enable-verify-exclusivity">, HelpText<"Enable verification of access markers used to enforce exclusivity.">; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index f9c3828c19c67..fc39f99ab8c7c 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -381,6 +381,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.DiagnosticsEditorMode |= Args.hasArg(OPT_diagnostics_editor_mode, OPT_serialize_diagnostics_path); + + Opts.DisableRedundantCoercionWarning |= + Args.hasArg(OPT_disable_redundant_coercion_warning); Opts.EnableExperimentalStaticAssert |= Args.hasArg(OPT_enable_experimental_static_assert); From b0e2928a457dac266c967806266c1ffcd1edaf7c Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:43:05 -0300 Subject: [PATCH 07/24] [stdlib] Fixing remaining redundant coercions in stdlib --- stdlib/public/core/MigrationSupport.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/public/core/MigrationSupport.swift b/stdlib/public/core/MigrationSupport.swift index 16124058138bc..48383292ce7ba 100644 --- a/stdlib/public/core/MigrationSupport.swift +++ b/stdlib/public/core/MigrationSupport.swift @@ -344,7 +344,7 @@ extension Collection { } @available(swift, deprecated: 4.0, obsoleted: 5.0, message: "all index distances are now of type Int") public func distance(from start: Index, to end: Index) -> T { - return numericCast(distance(from: start, to: end) as Int) + return numericCast(distance(from: start, to: end)) } } From f8d4bd40fd254c441669901d971af92fcc812e88 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:45:09 -0300 Subject: [PATCH 08/24] [tests] Adding disable flag to invocations under the tests/ClangImporter --- test/ClangImporter/CoreServices_test.swift | 2 +- test/ClangImporter/Darwin_test.swift | 2 +- .../MixedSource/mixed-target-using-header-swift4.swift | 4 ++-- .../MixedSource/mixed-target-using-header.swift | 4 ++-- .../MixedSource/mixed-target-using-module.swift | 6 +++--- test/ClangImporter/Security_test.swift | 2 +- test/ClangImporter/attr-swift_private.swift | 4 ++-- test/ClangImporter/cf.swift | 2 +- test/ClangImporter/cfuncs_parse.swift | 2 +- test/ClangImporter/ctypes_parse.swift | 2 +- test/ClangImporter/ctypes_parse_objc.swift | 2 +- test/ClangImporter/foreign_errors.swift | 4 ++-- test/ClangImporter/macros.swift | 2 +- test/ClangImporter/objc_bridging.swift | 2 +- test/ClangImporter/objc_bridging_generics.swift | 2 +- test/ClangImporter/objc_failable_inits.swift | 2 +- test/ClangImporter/objc_parse.swift | 2 +- 17 files changed, 23 insertions(+), 23 deletions(-) diff --git a/test/ClangImporter/CoreServices_test.swift b/test/ClangImporter/CoreServices_test.swift index 5a82dbc00d254..3e80588b52c44 100644 --- a/test/ClangImporter/CoreServices_test.swift +++ b/test/ClangImporter/CoreServices_test.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift %clang-importer-sdk +// RUN: %target-typecheck-verify-swift %clang-importer-sdk -disable-redundant-coercion-warning // REQUIRES: objc_interop diff --git a/test/ClangImporter/Darwin_test.swift b/test/ClangImporter/Darwin_test.swift index 90606a91106c8..ad05a68addd72 100644 --- a/test/ClangImporter/Darwin_test.swift +++ b/test/ClangImporter/Darwin_test.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift %clang-importer-sdk +// RUN: %target-typecheck-verify-swift %clang-importer-sdk -disable-redundant-coercion-warning // REQUIRES: objc_interop diff --git a/test/ClangImporter/MixedSource/mixed-target-using-header-swift4.swift b/test/ClangImporter/MixedSource/mixed-target-using-header-swift4.swift index 2ec8a513730fa..6179644186ecb 100644 --- a/test/ClangImporter/MixedSource/mixed-target-using-header-swift4.swift +++ b/test/ClangImporter/MixedSource/mixed-target-using-header-swift4.swift @@ -1,3 +1,3 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -typecheck -primary-file %S/mixed-target-using-header.swift %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -verify -swift-version 4 -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -emit-sil -primary-file %S/mixed-target-using-header.swift %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -o /dev/null -D SILGEN -swift-version 4 +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -typecheck -primary-file %S/mixed-target-using-header.swift %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning -verify -swift-version 4 +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -emit-sil -primary-file %S/mixed-target-using-header.swift %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning -o /dev/null -D SILGEN -swift-version 4 diff --git a/test/ClangImporter/MixedSource/mixed-target-using-header.swift b/test/ClangImporter/MixedSource/mixed-target-using-header.swift index 0192f7b69385a..7067fd980d6fe 100644 --- a/test/ClangImporter/MixedSource/mixed-target-using-header.swift +++ b/test/ClangImporter/MixedSource/mixed-target-using-header.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -typecheck -primary-file %s %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -verify -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -emit-sil -primary-file %s %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -o /dev/null -D SILGEN +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -typecheck -primary-file %s %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning -verify +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -enable-objc-interop -import-objc-header %S/Inputs/mixed-target/header.h -emit-sil -primary-file %s %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning -o /dev/null -D SILGEN func test(_ foo : FooProto) { _ = foo.bar as CInt diff --git a/test/ClangImporter/MixedSource/mixed-target-using-module.swift b/test/ClangImporter/MixedSource/mixed-target-using-module.swift index 0c007f6dd7895..eafc59fe502d0 100644 --- a/test/ClangImporter/MixedSource/mixed-target-using-module.swift +++ b/test/ClangImporter/MixedSource/mixed-target-using-module.swift @@ -1,6 +1,6 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name Mixed -import-underlying-module -typecheck %s -verify -enable-objc-interop -disable-objc-attr-requires-foundation-module -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name Mixed -import-underlying-module -enable-objc-interop -emit-ir %S/../../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-AUTOLINK %s -// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name WrongName -import-underlying-module -typecheck %s -enable-objc-interop -disable-objc-attr-requires-foundation-module 2>&1 | %FileCheck -check-prefix=CHECK-WRONG-NAME %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name Mixed -import-underlying-module -typecheck %s -verify -enable-objc-interop -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name Mixed -import-underlying-module -enable-objc-interop -emit-ir -disable-redundant-coercion-warning %S/../../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-AUTOLINK %s +// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -F %S/Inputs/mixed-target/ -module-name WrongName -import-underlying-module -typecheck %s -enable-objc-interop -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning 2>&1 | %FileCheck -check-prefix=CHECK-WRONG-NAME %s // CHECK-AUTOLINK: !llvm.linker.options = !{ // CHECK-AUTOLINK-NOT: !"-framework" diff --git a/test/ClangImporter/Security_test.swift b/test/ClangImporter/Security_test.swift index e2ca596fb9a25..77a2db0f17eb3 100644 --- a/test/ClangImporter/Security_test.swift +++ b/test/ClangImporter/Security_test.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -verify +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -verify -disable-redundant-coercion-warning // REQUIRES: objc_interop diff --git a/test/ClangImporter/attr-swift_private.swift b/test/ClangImporter/attr-swift_private.swift index 252f8c74d513c..a90ca30872677 100644 --- a/test/ClangImporter/attr-swift_private.swift +++ b/test/ClangImporter/attr-swift_private.swift @@ -1,8 +1,8 @@ // RUN: %empty-directory(%t) // RUN: %build-clang-importer-objc-overlays -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -I %S/Inputs/custom-modules -typecheck %s -verify -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -I %S/Inputs/custom-modules -emit-ir %s -D IRGEN | %FileCheck %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -I %S/Inputs/custom-modules -typecheck %s -verify -disable-redundant-coercion-warning +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -I %S/Inputs/custom-modules -emit-ir -disable-redundant-coercion-warning %s -D IRGEN | %FileCheck %s // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk-nosource -I %t) -I %S/Inputs/custom-modules -print-module -source-filename="%s" -module-to-print SwiftPrivateAttr > %t.txt // RUN: %FileCheck -check-prefix=GENERATED-NEGATIVE %s < %t.txt diff --git a/test/ClangImporter/cf.swift b/test/ClangImporter/cf.swift index 31244d953a9e7..e2d589b4cb1b6 100644 --- a/test/ClangImporter/cf.swift +++ b/test/ClangImporter/cf.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -typecheck -verify -import-cf-types -I %S/Inputs/custom-modules %s +// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning -typecheck -verify -import-cf-types -I %S/Inputs/custom-modules %s // REQUIRES: objc_interop diff --git a/test/ClangImporter/cfuncs_parse.swift b/test/ClangImporter/cfuncs_parse.swift index 746dce15787b3..2fc39eed541fc 100644 --- a/test/ClangImporter/cfuncs_parse.swift +++ b/test/ClangImporter/cfuncs_parse.swift @@ -1,5 +1,5 @@ // XFAIL: CPU=powerpc64le -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -I %S/Inputs %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -disable-redundant-coercion-warning -typecheck -verify -I %S/Inputs %s import cfuncs diff --git a/test/ClangImporter/ctypes_parse.swift b/test/ClangImporter/ctypes_parse.swift index 9cf79bf690379..44405cd179930 100644 --- a/test/ClangImporter/ctypes_parse.swift +++ b/test/ClangImporter/ctypes_parse.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift %clang-importer-sdk +// RUN: %target-typecheck-verify-swift %clang-importer-sdk -disable-redundant-coercion-warning import ctypes diff --git a/test/ClangImporter/ctypes_parse_objc.swift b/test/ClangImporter/ctypes_parse_objc.swift index 23208a2c43d11..c0db83f012537 100644 --- a/test/ClangImporter/ctypes_parse_objc.swift +++ b/test/ClangImporter/ctypes_parse_objc.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift %clang-importer-sdk -enable-objc-interop +// RUN: %target-typecheck-verify-swift %clang-importer-sdk -enable-objc-interop -disable-redundant-coercion-warning import ctypes import CoreGraphics diff --git a/test/ClangImporter/foreign_errors.swift b/test/ClangImporter/foreign_errors.swift index 0588f59eb681a..3c432a6882d50 100644 --- a/test/ClangImporter/foreign_errors.swift +++ b/test/ClangImporter/foreign_errors.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -parse-as-library -verify %s -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-sil -O -parse-as-library -DEMIT_SIL %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -parse-as-library -disable-redundant-coercion-warning -verify %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-sil -O -parse-as-library -disable-redundant-coercion-warning -DEMIT_SIL %s // REQUIRES: objc_interop diff --git a/test/ClangImporter/macros.swift b/test/ClangImporter/macros.swift index 9063cae9590a9..a301d8706cf87 100644 --- a/test/ClangImporter/macros.swift +++ b/test/ClangImporter/macros.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -typecheck -verify %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -disable-redundant-coercion-warning -typecheck -verify %s @_exported import macros diff --git a/test/ClangImporter/objc_bridging.swift b/test/ClangImporter/objc_bridging.swift index a42ed6a5eb759..cdb3a704bef43 100644 --- a/test/ClangImporter/objc_bridging.swift +++ b/test/ClangImporter/objc_bridging.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -verify %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -disable-redundant-coercion-warning -typecheck -parse-as-library -verify %s // REQUIRES: objc_interop diff --git a/test/ClangImporter/objc_bridging_generics.swift b/test/ClangImporter/objc_bridging_generics.swift index 8de2c4b6be402..a3d3e2648d2b8 100644 --- a/test/ClangImporter/objc_bridging_generics.swift +++ b/test/ClangImporter/objc_bridging_generics.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -verify -swift-version 4 -I %S/Inputs/custom-modules %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -disable-redundant-coercion-warning -typecheck -parse-as-library -verify -swift-version 4 -I %S/Inputs/custom-modules %s // REQUIRES: objc_interop diff --git a/test/ClangImporter/objc_failable_inits.swift b/test/ClangImporter/objc_failable_inits.swift index b4d64beae4446..cdbc2ee24004e 100644 --- a/test/ClangImporter/objc_failable_inits.swift +++ b/test/ClangImporter/objc_failable_inits.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -verify +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -disable-redundant-coercion-warning -typecheck %s -verify // REQUIRES: objc_interop diff --git a/test/ClangImporter/objc_parse.swift b/test/ClangImporter/objc_parse.swift index a39a815378b99..c06ea383914b2 100644 --- a/test/ClangImporter/objc_parse.swift +++ b/test/ClangImporter/objc_parse.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-sil -I %S/Inputs/custom-modules %s -verify +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -disable-redundant-coercion-warning -emit-sil -I %S/Inputs/custom-modules %s -verify // REQUIRES: objc_interop From aa9abfc26c0a1ae87c850dbbae2cfbcc5e894851 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:45:51 -0300 Subject: [PATCH 09/24] [tests] Fixing tests under test/Constraints --- test/Constraints/bridging.swift | 6 +++--- test/Constraints/casts.swift | 2 +- test/Constraints/construction.swift | 5 ++--- test/Constraints/diagnostics.swift | 2 +- test/Constraints/function.swift | 2 +- test/Constraints/invalid_logicvalue_coercion.swift | 2 +- test/Constraints/iuo.swift | 8 ++++---- test/Constraints/protocols.swift | 10 +++++----- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift index 5dcb206a1fc0d..0912206866047 100644 --- a/test/Constraints/bridging.swift +++ b/test/Constraints/bridging.swift @@ -286,9 +286,9 @@ func rdar19836341(_ ns: NSString?, vns: NSString?) { // Swift compiler sometimes suggests changing "as!" to "as?!" func rdar20029786(_ ns: NSString?) { - var s: String = ns ?? "str" as String as String // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{19-19=(}} {{50-50=) as String}} + var s: String = ns ?? "str" as String as String // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{19-19=(}} {{50-50=) as String}} expected-warning {{redundant cast to 'String' has no effect}} {{41-51=}} // expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'NSString'}} {{50-50= as NSString}} - var s2 = ns ?? "str" as String as String // expected-error {{cannot convert value of type 'String' to expected argument type 'NSString'}}{{43-43= as NSString}} + var s2 = ns ?? "str" as String as String // expected-error {{cannot convert value of type 'String' to expected argument type 'NSString'}}{{43-43= as NSString}} expected-warning {{redundant cast to 'String' has no effect}} {{34-44=}} let s3: NSString? = "str" as String? // expected-error {{cannot convert value of type 'String?' to specified type 'NSString?'}}{{39-39= as NSString?}} @@ -342,7 +342,7 @@ func forceUniversalBridgeToAnyObject(a: T, b: U, c: An z = d as AnyObject z = e as AnyObject z = f as AnyObject - z = g as AnyObject + z = g as AnyObject // expected-warning {{redundant cast to 'AnyObject' has no effect}} {{9-22=}} z = h as AnyObject z = a // expected-error{{value of type 'T' expected to be an instance of a class or class-constrained type in assignment}} diff --git a/test/Constraints/casts.swift b/test/Constraints/casts.swift index 0ea574583a5b8..8db16a63ab9f3 100644 --- a/test/Constraints/casts.swift +++ b/test/Constraints/casts.swift @@ -180,7 +180,7 @@ var c2f2: C2<[Float]>? = b as! C3 // -var f: (Float) -> Float = { $0 as Float } +var f: (Float) -> Float = { $0 as Float } // expected-warning {{redundant cast to 'Float' has no effect}} {{32-41=}} var f2: (B) -> Bool = { $0 is D } func metatype_casts(_ b: B.Type, t:T.Type, u: U.Type) { diff --git a/test/Constraints/construction.swift b/test/Constraints/construction.swift index 82f660ed6a7bb..06f14c25aecda 100644 --- a/test/Constraints/construction.swift +++ b/test/Constraints/construction.swift @@ -95,13 +95,12 @@ _ = b as! Derived // NOTE: Int and other integer-literal convertible types // are special cased in the library. Int(i) // expected-warning{{unused}} -_ = i as Int +_ = i as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{7-14=}} Z(z) // expected-error{{no exact matches in call to initializer}} - Z.init(z) // expected-error {{no exact matches in call to initializer}} -_ = z as Z +_ = z as Z // expected-warning {{redundant cast to 'Z' has no effect}} {{7-12=}} // Construction from inouts. struct FooRef { } diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index bff33fe7caa73..51227a5825d3f 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -307,7 +307,7 @@ _ = 4(1) // expected-error {{cannot call value of non-function type 'Int'}} // Incongruous `unexpected trailing closure` error in `init` function which is cast and called without trailing closure. func rdar21784170() { let initial = (1.0 as Double, 2.0 as Double) - (Array.init as (Double...) -> Array)(initial as (Double, Double)) // expected-error {{cannot convert value of type '(Double, Double)' to expected argument type 'Double'}} + (Array.init as (Double...) -> Array)(initial as (Double, Double)) // expected-error {{cannot convert value of type '(Double, Double)' to expected argument type 'Double'}} // expected-warning {{redundant cast to '(Double, Double)' has no effect}} {{56-75=}} } // Diagnose passing an array in lieu of variadic parameters diff --git a/test/Constraints/function.swift b/test/Constraints/function.swift index 429b4dc865ee4..1344e13948036 100644 --- a/test/Constraints/function.swift +++ b/test/Constraints/function.swift @@ -174,7 +174,7 @@ func testWeirdFnExprs(_ fn: () -> Int, _ cond: Bool, _ any: Any, genericArg: // expected-error@-1 {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}} let wrapped = Wrapper<(@escaping () -> Int) -> Void>({ x in }) - (wrapped[keyPath: \.value] as (@escaping () -> Int) -> Void)(fn) + (wrapped[keyPath: \.value] as (@escaping () -> Int) -> Void)(fn) // expected-warning {{redundant cast to '(@escaping () -> Int) -> Void' has no effect}} {{30-62=}} // expected-error@-1 {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}} (cond ? returnsTakesEscapingFn() : returnsTakesEscapingFn())(fn) diff --git a/test/Constraints/invalid_logicvalue_coercion.swift b/test/Constraints/invalid_logicvalue_coercion.swift index f703295130a12..1456f601f0a69 100644 --- a/test/Constraints/invalid_logicvalue_coercion.swift +++ b/test/Constraints/invalid_logicvalue_coercion.swift @@ -2,7 +2,7 @@ class C {} var c = C() -if c as C { // expected-error{{cannot convert value of type 'C' to expected condition type 'Bool'}} +if c as C { // expected-error{{cannot convert value of type 'C' to expected condition type 'Bool'}} expected-warning {{redundant cast to 'C' has no effect}} {{6-11=}} } if ({1} as () -> Int) { // expected-error{{cannot convert value of type '() -> Int' to expected condition type 'Bool'}} diff --git a/test/Constraints/iuo.swift b/test/Constraints/iuo.swift index 8b700751160c5..610cf97cf5f1d 100644 --- a/test/Constraints/iuo.swift +++ b/test/Constraints/iuo.swift @@ -158,13 +158,13 @@ extension P { } func cast(_ t: T) { - let _: (T) -> (Bool) -> T? = id(T.iuoResult as (T) -> (Bool) -> T?) - let _: (Bool) -> T? = id(T.iuoResult(t) as (Bool) -> T?) + let _: (T) -> (Bool) -> T? = id(T.iuoResult as (T) -> (Bool) -> T?) // expected-warning {{redundant cast to '(T) -> (Bool) -> T?' has no effect}} {{47-69=}} + let _: (Bool) -> T? = id(T.iuoResult(t) as (Bool) -> T?) // expected-warning {{redundant cast to '(Bool) -> T?' has no effect}} {{43-58=}} let _: T! = id(T.iuoResult(t)(true)) - let _: (Bool) -> T? = id(t.iuoResult as (Bool) -> T?) + let _: (Bool) -> T? = id(t.iuoResult as (Bool) -> T?) // expected-warning {{redundant cast to '(Bool) -> T?' has no effect}} {{40-55=}} let _: T! = id(t.iuoResult(true)) let _: T = id(t.iuoResult(true)) - let _: (Bool) -> T? = id(T.iuoResultStatic as (Bool) -> T?) + let _: (Bool) -> T? = id(T.iuoResultStatic as (Bool) -> T?) // expected-warning {{redundant cast to '(Bool) -> T?' has no effect}} {{46-61=}} let _: T! = id(T.iuoResultStatic(true)) } diff --git a/test/Constraints/protocols.swift b/test/Constraints/protocols.swift index eef0fe619afe3..48da0253607e3 100644 --- a/test/Constraints/protocols.swift +++ b/test/Constraints/protocols.swift @@ -329,11 +329,11 @@ func testClonableArchetype(_ t: T) { let _: (Bool) -> T? = id(t.extMaybeClone) let _: T? = id(t.extMaybeClone(true)) - let _: (T) -> (Bool) -> T? = id(T.extProbablyClone as (T) -> (Bool) -> T?) - let _: (Bool) -> T? = id(T.extProbablyClone(t) as (Bool) -> T?) + let _: (T) -> (Bool) -> T? = id(T.extProbablyClone as (T) -> (Bool) -> T?) // expected-warning {{redundant cast to '(T) -> (Bool) -> T?' has no effect}} {{54-76=}} + let _: (Bool) -> T? = id(T.extProbablyClone(t) as (Bool) -> T?) // expected-warning {{redundant cast to '(Bool) -> T?' has no effect}} {{50-65=}} let _: T! = id(T.extProbablyClone(t)(true)) - let _: (Bool) -> T? = id(t.extProbablyClone as (Bool) -> T?) + let _: (Bool) -> T? = id(t.extProbablyClone as (Bool) -> T?) // expected-warning {{redundant cast to '(Bool) -> T?' has no effect}} {{47-62=}} let _: T! = id(t.extProbablyClone(true)) // Static member of extension returning Self) @@ -343,7 +343,7 @@ func testClonableArchetype(_ t: T) { let _: (Bool) -> T? = id(T.returnSelfOptionalStatic) let _: T? = id(T.returnSelfOptionalStatic(false)) - let _: (Bool) -> T? = id(T.returnSelfIUOStatic as (Bool) -> T?) + let _: (Bool) -> T? = id(T.returnSelfIUOStatic as (Bool) -> T?) // expected-warning {{redundant cast to '(Bool) -> T?' has no effect}} {{50-65=}} let _: T! = id(T.returnSelfIUOStatic(true)) } @@ -367,7 +367,7 @@ func testClonableExistential(_ v: Clonable, _ vv: Clonable.Type) { let _: (Bool) -> Clonable? = id(vv.returnSelfOptionalStatic) let _: Clonable? = id(vv.returnSelfOptionalStatic(false)) - let _: (Bool) -> Clonable? = id(vv.returnSelfIUOStatic as (Bool) -> Clonable?) + let _: (Bool) -> Clonable? = id(vv.returnSelfIUOStatic as (Bool) -> Clonable?) // expected-warning {{redundant cast to '(Bool) -> Clonable?' has no effect}} {{58-80=}} let _: Clonable! = id(vv.returnSelfIUOStatic(true)) let _ = v.badClonerFn() // expected-error {{member 'badClonerFn' cannot be used on value of protocol type 'Clonable'; use a generic constraint instead}} From 1f2e8488f95b3c05c248148b6706cf64993018b7 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:48:03 -0300 Subject: [PATCH 10/24] [tests] Fixing tests under test/Generics, test/Interpreter and test/stdlib --- test/Generics/generic_types.swift | 6 +++--- test/Generics/inheritance.swift | 2 +- test/Interpreter/SDK/misc_osx.swift | 3 ++- test/stdlib/StringDiagnostics.swift | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/Generics/generic_types.swift b/test/Generics/generic_types.swift index b0f44a96adbf3..1f83da793f400 100644 --- a/test/Generics/generic_types.swift +++ b/test/Generics/generic_types.swift @@ -73,7 +73,7 @@ func getFirst(_ r: R) -> R.Element { } func testGetFirst(ir: Range) { - _ = getFirst(ir.makeIterator()) as Int + _ = getFirst(ir.makeIterator()) as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{35-42=}} } struct XT { @@ -191,11 +191,11 @@ var xarray : XArray = [1, 2, 3] // Type parameters can be referenced only via unqualified name lookup struct XParam { // expected-note{{'XParam' declared here}} func foo(_ x: T) { - _ = x as T + _ = x as T // expected-warning {{redundant cast to 'T' has no effect}} {{11-16=}} } static func bar(_ x: T) { - _ = x as T + _ = x as T // expected-warning {{redundant cast to 'T' has no effect}} {{11-16=}} } } diff --git a/test/Generics/inheritance.swift b/test/Generics/inheritance.swift index ebfd77736f1d5..6fe6ba77ebe56 100644 --- a/test/Generics/inheritance.swift +++ b/test/Generics/inheritance.swift @@ -51,7 +51,7 @@ class Y : X<[T]> { func testGenericInherit() { let yi : Y - _ = yi.f() as [Int] + _ = yi.f() as [Int] // expected-warning {{redundant cast to '[Int]' has no effect}} {{14-23=}} } diff --git a/test/Interpreter/SDK/misc_osx.swift b/test/Interpreter/SDK/misc_osx.swift index 15383cf784077..cabfe529fd333 100644 --- a/test/Interpreter/SDK/misc_osx.swift +++ b/test/Interpreter/SDK/misc_osx.swift @@ -6,7 +6,8 @@ import CoreServices func testFSEventStreamRef(stream: FSEventStreamRef) { // FIXME: These should be distinct types, constructible from one another. - _ = stream as ConstFSEventStreamRef // works by coincidence because both are currently OpaquePointer + // works by coincidence because both are currently OpaquePointer + _ = stream as ConstFSEventStreamRef // expected-warning {{redundant cast from 'FSEventStreamRef' (aka 'OpaquePointer') to 'ConstFSEventStreamRef' (aka 'OpaquePointer') has no effect}} {{14-39=}} _ = ConstFSEventStreamRef(stream) // expected-error {{no exact matches in call to initializer}} // This is not a CF object. diff --git a/test/stdlib/StringDiagnostics.swift b/test/stdlib/StringDiagnostics.swift index c3fde8ff884f5..0bb92245caca9 100644 --- a/test/stdlib/StringDiagnostics.swift +++ b/test/stdlib/StringDiagnostics.swift @@ -27,7 +27,7 @@ func testNonAmbiguousStringComparisons() { let s2 = "b" var x = false // expected-warning {{variable 'x' was written to, but never read}} x = s1 > s2 - x = s1 as String > s2 + x = s1 as String > s2 // expected-warning {{redundant cast to 'String' has no effect}} {{10-20=}} } func testAmbiguousStringComparisons(s: String) { From 867e9bba9e33e4f1a1c95d979926798ad483b171 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:48:50 -0300 Subject: [PATCH 11/24] [tests] Fixing tests under test/Sema and test/decl --- test/Sema/diag_unintended_optional_behavior.swift | 2 +- test/Sema/diag_unowned_immediate_deallocation.swift | 2 +- test/Sema/suppress-argument-labels-in-types.swift | 12 ++++++------ test/decl/class/classes.swift | 4 ++-- test/decl/protocol/req/optional.swift | 8 ++++---- test/decl/var/variables.swift | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/Sema/diag_unintended_optional_behavior.swift b/test/Sema/diag_unintended_optional_behavior.swift index e2cc7cb16c908..b65406e89168c 100644 --- a/test/Sema/diag_unintended_optional_behavior.swift +++ b/test/Sema/diag_unintended_optional_behavior.swift @@ -212,7 +212,7 @@ func warnOptionalInStringInterpolationSegment(_ o : Int?) { // expected-note@-2 {{use 'String(describing:)' to silence this warning}} {{51-51=String(describing: }} {{67-67=)}} // expected-note@-3 {{provide a default value to avoid this warning}} {{67-67= ?? <#default value#>}} - print("Always some, Always some, Always some: \(o as Int?)") // No warning + print("Always some, Always some, Always some: \(o as Int?)") // expected-warning {{redundant cast to 'Int?' has no effect}} {{53-60=}} print("Always some, Always some, Always some: \(o.debugDescription)") // No warning. let oST = Optional(SpecialType()) diff --git a/test/Sema/diag_unowned_immediate_deallocation.swift b/test/Sema/diag_unowned_immediate_deallocation.swift index fcda88dd0923a..6f4b755157ca4 100644 --- a/test/Sema/diag_unowned_immediate_deallocation.swift +++ b/test/Sema/diag_unowned_immediate_deallocation.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift -module-name ModuleName +// RUN: %target-typecheck-verify-swift -module-name ModuleName -disable-redundant-coercion-warning protocol ClassProtocol : class { init() diff --git a/test/Sema/suppress-argument-labels-in-types.swift b/test/Sema/suppress-argument-labels-in-types.swift index 7945ea146fe89..2a3c289bd31b4 100644 --- a/test/Sema/suppress-argument-labels-in-types.swift +++ b/test/Sema/suppress-argument-labels-in-types.swift @@ -207,18 +207,18 @@ let _ = min(Int(3), Float(2.5)) // expected-error{{conflicting arguments to gene // SR-11429 func testIntermediateCoercions() { - _ = (f1 as (Int, Int) -> Int)(a: 0, b: 1) // expected-error {{extraneous argument labels 'a:b:' in call}} - _ = (f1 as (Int, Int) -> Int)(0, 1) + _ = (f1 as (Int, Int) -> Int)(a: 0, b: 1) // expected-error {{extraneous argument labels 'a:b:' in call}} expected-warning {{redundant cast to '(Int, Int) -> Int' has no effect}} + _ = (f1 as (Int, Int) -> Int)(0, 1) // expected-warning {{redundant cast to '(Int, Int) -> Int' has no effect}} typealias Magic = T - _ = (f1 as Magic)(a: 0, b: 1) // expected-error {{extraneous argument labels 'a:b:' in call}} - _ = (f1 as Magic)(0, 1) + _ = (f1 as Magic)(a: 0, b: 1) // expected-error {{extraneous argument labels 'a:b:' in call}} expected-warning {{redundant cast to 'Magic' has no effect}} {{11-19=}} + _ = (f1 as Magic)(0, 1) // expected-warning {{redundant cast to 'Magic' has no effect}} {{11-19=}} _ = (f4 as (Int, Int) -> Int)(0, 0) _ = (f4 as (Double, Double) -> Double)(0, 0) func iuoReturning() -> Int! {} - _ = (iuoReturning as () -> Int?)() - _ = (iuoReturning as Magic)() + _ = (iuoReturning as () -> Int?)() // expected-warning {{redundant cast to '() -> Int?' has no effect}} + _ = (iuoReturning as Magic)() // expected-warning {{redundant cast to 'Magic' has no effect}} {{21-29=}} _ = (iuoReturning as () -> Int)() // expected-error {{cannot convert value of type '() -> Int?' to type '() -> Int' in coercion}} } diff --git a/test/decl/class/classes.swift b/test/decl/class/classes.swift index 879e6093a9195..8e03c6a841310 100644 --- a/test/decl/class/classes.swift +++ b/test/decl/class/classes.swift @@ -43,8 +43,8 @@ extension A { } func f() { let x = B() - _ = x.f() as () - _ = x[10] as Int + _ = x.f() as () // expected-warning {{redundant cast to '()' has no effect}} {{13-19=}} + _ = x[10] as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{13-20=}} } class C { diff --git a/test/decl/protocol/req/optional.swift b/test/decl/protocol/req/optional.swift index ba512dd7a4e6d..7ec837fc7fb99 100644 --- a/test/decl/protocol/req/optional.swift +++ b/test/decl/protocol/req/optional.swift @@ -144,7 +144,7 @@ func optionalPropertyGeneric(_ t: T) { // ... and that we can use it let i = propertyRef! - _ = i as Int + _ = i as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{9-16=}} } // Optional subscript references in generics. @@ -157,7 +157,7 @@ func optionalSubscriptGeneric(_ t: T) { // ... and that we can use it let i = subscriptRef! - _ = i as ObjCClass? + _ = i as ObjCClass? // expected-warning {{redundant cast to 'ObjCClass?' has no effect}} {{9-23=}} } // Optional method references in existentials. @@ -182,7 +182,7 @@ func optionalPropertyExistential(_ t: P1) { // ... and that we can use it let i = propertyRef! - _ = i as Int + _ = i as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{9-16=}} } // Optional subscript references in existentials. @@ -195,7 +195,7 @@ func optionalSubscriptExistential(_ t: P1) { // ... and that we can use it let i = subscriptRef! - _ = i as ObjCClass? + _ = i as ObjCClass? // expected-warning {{redundant cast to 'ObjCClass?' has no effect}} {{9-23=}} } // ----------------------------------------------------------------------- diff --git a/test/decl/var/variables.swift b/test/decl/var/variables.swift index f2b5d0190c4b1..91b4ec4ab1080 100644 --- a/test/decl/var/variables.swift +++ b/test/decl/var/variables.swift @@ -67,7 +67,7 @@ var arrayOfEmptyTuples = [""].map { print($0) } // expected-warning {{variable ' var maybeEmpty = Optional(arrayOfEmptyTuples) // expected-warning {{variable 'maybeEmpty' inferred to have type '[()]?'}} \ // expected-note {{add an explicit type annotation to silence this warning}} {{15-15=: [()]?}} -var shouldWarnWithoutSugar = (arrayOfEmptyTuples as Array<()>) // expected-warning {{variable 'shouldWarnWithoutSugar' inferred to have type 'Array<()>'}} \ +var shouldWarnWithoutSugar = (arrayOfEmptyTuples as Array<()>) // expected-warning {{redundant cast to 'Array<()>' has no effect}} {{50-62=}} expected-warning {{variable 'shouldWarnWithoutSugar' inferred to have type 'Array<()>'}} \ // expected-note {{add an explicit type annotation to silence this warning}} {{27-27=: Array<()>}} class SomeClass {} From 37407836e8ca37dc457c2755c6b07fdab0331cc2 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Mon, 16 Dec 2019 19:50:08 -0300 Subject: [PATCH 12/24] [tests] Fixing tests under test/type, test/expr and test/Parse --- test/Parse/omit_return.swift | 2 +- test/expr/cast/array_downcast.swift | 2 +- test/expr/cast/as_coerce.swift | 181 ++++++++++++++++++++++- test/expr/postfix/dot/dot_keywords.swift | 2 +- test/expr/primary/selector/fixits.swift | 15 +- test/type/infer/local_variables.swift | 2 +- test/type/subclass_composition.swift | 10 +- 7 files changed, 196 insertions(+), 18 deletions(-) diff --git a/test/Parse/omit_return.swift b/test/Parse/omit_return.swift index 870dbfc78d39d..29a8c5d763e01 100644 --- a/test/Parse/omit_return.swift +++ b/test/Parse/omit_return.swift @@ -510,7 +510,7 @@ func ff_implicitIsExpr(t: T) -> Bool { } func ff_implicitCoerceExpr() -> T.Type { - T.self as T.Type + T.self as T.Type // expected-warning {{redundant cast to 'T.Type' has no effect}} {{12-22=}} } func ff_implicitConditionalCheckedCastExprAs(t: T) -> Int? { diff --git a/test/expr/cast/array_downcast.swift b/test/expr/cast/array_downcast.swift index fddea8a4742fd..d787404ccd4a4 100644 --- a/test/expr/cast/array_downcast.swift +++ b/test/expr/cast/array_downcast.swift @@ -24,7 +24,7 @@ var ta = [t] va = ta -var va2: ([V])? = va as [V] +var va2: ([V])? = va as [V] // expected-warning {{redundant cast to '[V]' has no effect}} {{22-29=}} var v2: V = va2![0] var ua2: ([U])? = va as? [U] diff --git a/test/expr/cast/as_coerce.swift b/test/expr/cast/as_coerce.swift index 962c656322ca1..bf63604d4b8df 100644 --- a/test/expr/cast/as_coerce.swift +++ b/test/expr/cast/as_coerce.swift @@ -81,7 +81,7 @@ c3 as C4 // expected-error {{'C3' is not convertible to 'C4'; did you mean to us // Various incorrect diagnostics for explicit type conversions 1 as Double as Float // expected-error{{cannot convert value of type 'Double' to type 'Float' in coercion}} 1 as Int as String // expected-error{{cannot convert value of type 'Int' to type 'String' in coercion}} -Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}} +Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}} expected-warning {{redundant cast to 'Double' has no effect}} {{11-21=}} ["awd"] as [Int] // expected-error{{cannot convert value of type 'String' to expected element type 'Int'}} ([1, 2, 1.0], 1) as ([String], Int) // expected-error@-1 2 {{cannot convert value of type 'Int' to expected element type 'String'}} @@ -135,3 +135,182 @@ _ = sr6022 as! AnyObject // expected-warning {{forced cast from '() -> Any' to ' _ = sr6022 as? AnyObject // expected-warning {{conditional cast from '() -> Any' to 'AnyObject' always succeeds}} _ = sr6022_1 as! Any // expected-warning {{forced cast from '() -> ()' to 'Any' always succeeds; did you mean to use 'as'?}} _ = sr6022_1 as? Any // expected-warning {{conditional cast from '() -> ()' to 'Any' always succeeds}} + +// SR-11295 +let sr11295a = "Hello" +_ = sr11295a as String // expected-warning {{redundant cast to 'String' has no effect}} {{14-24=}} + +let sr11295b = 1 +_ = sr11295b as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{14-21=}} + +typealias Type = String + +let sr11295c: Type = "Hello Typealias" +_ = sr11295c as String // expected-warning {{redundant cast to 'String' has no effect}} {{14-24=}} + +let sr11295d = "Hello Typealias" +_ = sr11295d as Type // expected-warning {{redundant cast to 'Type' (aka 'String') has no effect}} {{14-22=}} + +_ = "Hello" as String // Ok +_ = 1 as Int64 // Ok +_ = [] as Set // Ok + +class SR11295A {} +class SR11295B: SR11295A {} + +var sr11295ap = SR11295A() +var sr11295bc = SR11295B() + +_ = sr11295bc as SR11295A // Ok + +_ = 1 as Double as Double // expected-warning {{redundant cast to 'Double' has no effect}} {{17-27=}} +_ = Double(1) as Double // expected-warning {{redundant cast to 'Double' has no effect}} {{15-25=}} +_ = Int(1) as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{12-19=}} + +typealias Double1 = Double +typealias Double2 = Double + +let sr11295ta1: Double1 = 1.0 +_ = sr11295ta1 as Double2 // expected-warning {{redundant cast from 'Double1' (aka 'Double') to 'Double2' (aka 'Double') has no effect}} {{16-27=}} +_ = sr11295ta1 as Double1 // expected-warning {{redundant cast to 'Double1' (aka 'Double') has no effect}} {{16-27=}} + +func ff11295_0(_ t: T) -> T { return t } +func ff11295_1(_ i: Int) -> Int { return i } + +// Function call expressions +_ = ff11295_0(1 as Int) as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{25-32=}} +_ = ff11295_1(1) as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{18-25=}} + +func ff11295_3(i: Int) { + let a: [Int] = [] + _ = a.count - ((i + 1) as Int) // Ok +} + +struct SR11295C { + var i: Int +} +struct SR11295D { + var t: T + + func f() -> T { return t } +} +enum SR11295_E: Int { + case a +} + +// Coerce members +_ = SR11295C(i: 1).i as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{22-29=}} +_ = SR11295D(t: 1).t as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{27-34=}} +_ = SR11295D(t: 1 as Int).t as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{29-36=}} +_ = SR11295D(t: 1).t as Int // Ok +_ = SR11295D(t: 1).t as UInt // Ok +_ = SR11295_E.a.rawValue as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{26-33=}} +_ = SR11295D(t: 1 as Int).f() as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{31-38=}} +_ = SR11295D(t: 1).f() as Int // Ok + +// Overload decl expr +func f11295_Overload(a: Int, b: Int) -> Int { } +func f11295_Overload(c: Double, d: Double) -> Double { } + +_ = (f11295_Overload as (Int, Int) -> Int)(0, 0) +_ = (f11295_Overload as (Double, Double) -> Double)(0, 0) + +_ = (1 - 2 / 3 * 6) as UInt +_ = 1/4 as Float > 3/2 as Float // Ok +_ = 1/4 as Int > 3/2 as Int // Ok + +// Special cases where the coerced expression type is inferred by context. + +var f11295: (Float) -> Float = { $0 as Float } // expected-warning {{redundant cast to 'Float' has no effect}} {{37-46=}} +var f11295_1 = { $0 as Float } // Ok + +func ff11295() -> (Int) -> Int { + return { $0 as Int } // expected-warning {{redundant cast to 'Int' has no effect}} {{15-22=}} +} + +func f11295t_2(f: @escaping ((A) -> R, A) -> R) {} + +f11295t_2 { (f, n) in + n < 2 ? n : 0 // Ok +} + +f11295t_2 { (f, n) in + n < 2 ? n as Int: 0 // Ok +} + +f11295t_2 { (_, n) in + _ = n as Int // Ok +} + +f11295t_2 { (f, n: Int) in + n < 2 ? n as Int : 0 // expected-warning {{redundant cast to 'Int' has no effect}} {{13-20=}} +} + +f11295t_2 { (_, n) in + _ = SR11295D(t: n as Int).t as Int // expected-warning {{redundant cast to 'Int' has no effect}} {{31-38=}} +} + +f11295t_2 { (_, n) in + _ = SR11295D(t: n).t as Int // Ok +} + +func ff11295_g(_ v: T) { + let _ = { v as T } // expected-warning {{redundant cast to 'T' has no effect}} {{15-20=}} +} + +func ff11295_g1(_ v: Int) { + let _ = { v as Int } // expected-warning {{redundant cast to 'Int' has no effect}} {{15-22=}} +} + +func ff11295_g2(_ v: T) { + let _ = { $0 as T } // Ok +} + +func ff11295_g2(_ v: T) -> (T) -> T { + let _ : (T) -> T = { $0 as T } // expected-warning {{redundant cast to 'T' has no effect}} {{27-32=}} + return { $0 as T } // expected-warning {{redundant cast to 'T' has no effect}} {{15-20=}} +} + +func ff11295_g3(_ v: Int) { + let _ = { $0 as Int } // Ok +} + +func ff11295_g4(_ v: T) { + let c = v as T // expected-warning {{redundant cast to 'T' has no effect}} {{13-18=}} + let _ = { c as T } // expected-warning {{redundant cast to 'T' has no effect}} {{15-20=}} +} + +func ff11295_g5(_ v: T) { + // Nested closures + let _ = { { { $0 as T } } } // Ok + let _ = { { { v as T } } } // expected-warning {{redundant cast to 'T' has no effect}} {{19-24=}} +} + +func ff11295_6(_ i: Int) -> Int { i } +func ff11295_g6(_ i: T) -> T { i } + +let _ = { ff11295_g6($0 as Int) } // Ok + +let _ = { ff11295_6($0) } // Ok + +let _ = { ff11295_6($0 as Int) } // Ok + +// A similar test case comming from validation-test/Sema/type_checker_perf/fast/rdar17077404.swift +func f11295_3( + f: @escaping ((A) -> R, A) -> R +) -> ((A) -> R) { + return { (a: A) -> R in + let r: R! + return r + } +} + +_ = f11295_3 { + (f, n) in + f(n as Int) as Int // OK +} + +_ = f11295_3 { + (f, n) in + n < 2 ? n as Int : f(n - 1) + f(n - 2) // OK +} diff --git a/test/expr/postfix/dot/dot_keywords.swift b/test/expr/postfix/dot/dot_keywords.swift index ba2821fcb52e6..dfd789958be23 100644 --- a/test/expr/postfix/dot/dot_keywords.swift +++ b/test/expr/postfix/dot/dot_keywords.swift @@ -68,7 +68,7 @@ class ClassWithDeinitFunc { let instanceWithDeinitFunc = ClassWithDeinitFunc() instanceWithDeinitFunc.deinit() _ = instanceWithDeinitFunc.deinit(a:) -_ = instanceWithDeinitFunc.deinit as () -> Void +_ = instanceWithDeinitFunc.deinit as () -> Void // expected-warning {{redundant cast to '() -> Void' has no effect}} {{35-49=}} SR3043Derived.deinit() // expected-error {{deinitializers cannot be accessed}} class ClassWithDeinitMember { diff --git a/test/expr/primary/selector/fixits.swift b/test/expr/primary/selector/fixits.swift index 162fb667b9afe..fbacc15c11eaf 100644 --- a/test/expr/primary/selector/fixits.swift +++ b/test/expr/primary/selector/fixits.swift @@ -4,24 +4,24 @@ // RUN: %empty-directory(%t.overlays) // FIXME: BEGIN -enable-source-import hackaround -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/ObjectiveC.swift -disable-objc-attr-requires-foundation-module -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/CoreGraphics.swift -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/Foundation.swift +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/ObjectiveC.swift -disable-objc-attr-requires-foundation-module -disable-redundant-coercion-warning +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/CoreGraphics.swift -disable-redundant-coercion-warning +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %clang-importer-sdk-path/swift-modules/Foundation.swift -disable-redundant-coercion-warning // FIXME: END -enable-source-import hackaround -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %S/Inputs/fixits_helper.swift -module-name Helper +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -o %t.overlays %S/Inputs/fixits_helper.swift -module-name Helper -disable-redundant-coercion-warning // Make sure we get the right diagnostics. -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -typecheck %s -verify +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -disable-redundant-coercion-warning -typecheck %s -verify // Copy the source, apply the Fix-Its, and compile it again, making // sure that we've cleaned up all of the deprecation warnings. // RUN: %empty-directory(%t.sources) // RUN: %empty-directory(%t.remapping) // RUN: cp %s %t.sources/fixits.swift -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -typecheck %t.sources/fixits.swift -fixit-all -emit-fixits-path %t.remapping/fixits.remap +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -disable-redundant-coercion-warning -typecheck %t.sources/fixits.swift -fixit-all -emit-fixits-path %t.remapping/fixits.remap // RUN: %{python} %utils/apply-fixit-edits.py %t.remapping -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -typecheck %t.sources/fixits.swift 2> %t.result +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t.overlays) -disable-redundant-coercion-warning -typecheck %t.sources/fixits.swift 2> %t.result // RUN: %FileCheck %s < %t.result // RUN: grep -c "warning:" %t.result | grep 3 @@ -55,7 +55,6 @@ func testDeprecatedStringLiteralSelector() { // We don't need coercion here because we get the right selector // from the static method. _ = "staticOrNonStatic:" as Selector // expected-warning{{use of string literal for Objective-C selectors is deprecated; use '#selector' instead}}{{7-39=#selector(Bar.staticOrNonStatic(_:))}} - // We need coercion here because we asked for a selector from an // instance method with the same name as (but a different selector // from) a static method. diff --git a/test/type/infer/local_variables.swift b/test/type/infer/local_variables.swift index 35bd6f60aa8dc..b7859b2496d4b 100644 --- a/test/type/infer/local_variables.swift +++ b/test/type/infer/local_variables.swift @@ -30,6 +30,6 @@ func infer_generic_args() { // Function types let f : (Dictionary) -> Array = dict_to_array - _ = f(d) as [(String, Int)] + _ = f(d) as [(String, Int)] // expected-warning {{redundant cast to '[(String, Int)]' has no effect}} {{12-31=}} } diff --git a/test/type/subclass_composition.swift b/test/type/subclass_composition.swift index a7c52f539bf58..4a393e85969af 100644 --- a/test/type/subclass_composition.swift +++ b/test/type/subclass_composition.swift @@ -125,8 +125,8 @@ func basicSubtyping( let _: Derived & AnyObject = derived let _ = base as Base & P1 - let _ = base as Base & AnyObject - let _ = derived as Derived & AnyObject + let _ = base as Base & AnyObject // expected-warning {{redundant cast to 'Base' has no effect}} {{16-41=}} + let _ = derived as Derived & AnyObject // expected-warning {{redundant cast to 'Derived' has no effect}} {{19-42=}} let _ = base as? Base & P1 // expected-warning {{always succeeds}} let _ = base as? Base & AnyObject // expected-warning {{always succeeds}} @@ -169,7 +169,7 @@ func basicSubtyping( let _ = baseAndP1 as Base let _ = derivedAndP3 as Base let _ = derivedAndP2 as Derived - let _ = derivedAndAnyObject as Derived + let _ = derivedAndAnyObject as Derived // expected-warning {{redundant cast to 'Derived' has no effect}} {{31-42=}} let _ = baseAndP1 as? Base // expected-warning {{always succeeds}} let _ = derivedAndP3 as? Base // expected-warning {{always succeeds}} @@ -342,8 +342,8 @@ func metatypeSubtyping( let _ = baseIntAndP2 as Base.Type let _ = baseIntAndP2AndAnyObject as Base.Type - let _ = derivedAndAnyObject as Derived.Type - let _ = baseIntAndP2AndAnyObject as BaseAndP2.Type + let _ = derivedAndAnyObject as Derived.Type // expected-warning {{redundant cast to 'Derived.Type' has no effect}} {{31-47=}} + let _ = baseIntAndP2AndAnyObject as BaseAndP2.Type // expected-warning {{redundant cast to 'BaseAndP2.Type' (aka '(Base & P2).Type') has no effect}} {{36-59=}} let _ = baseIntAndP2 as? Base.Type // expected-warning {{always succeeds}} let _ = baseIntAndP2AndAnyObject as? Base.Type // expected-warning {{always succeeds}} From 4e512a9c7e7aa4475deb94c6160a20ec80e2e697 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Tue, 24 Dec 2019 10:53:39 -0300 Subject: [PATCH 13/24] [CSFix] Getting the source locator from the representative --- lib/Sema/CSFix.cpp | 3 ++- lib/Sema/CSSimplify.cpp | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index c271db333ba58..784f91bb6fa91 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1199,7 +1199,8 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, if (cs.hasFreeTypeVariables()) return false; - if (auto *typeSourceLocator = cs.getTypeVariableBindingLocator(typeVariable)) { + auto representative = cs.getRepresentative(typeVariable); + if (auto *typeSourceLocator = cs.getTypeVariableBindingLocator(representative)) { // If the type variable binding source locator is the same the // contextual type equality is coming from this coercion. if (typeSourceLocator == cs.getConstraintLocator(locator)) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index a2daf9c6f4403..6478fe5343153 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4613,12 +4613,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, return matchTypesBindTypeVar(typeVar1, type2, kind, flags, locator, formUnsolvedResult); } - if (!typeVar2) { - // If type1 is a type varaible and type2 type is a fixed type, - // record this as the potential fixed type locator source. - recordTypeVariableBindingLocator(typeVar1, - getConstraintLocator(locator)); - } } // If the left-hand side of a 'sequence element' constraint From 3c778a44168df4409f66981e9295748f51bdaefc Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Thu, 26 Dec 2019 06:24:24 -0300 Subject: [PATCH 14/24] [test] Add explicit coercion test for tuple element expr/cast/as_coerce --- test/expr/cast/as_coerce.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/expr/cast/as_coerce.swift b/test/expr/cast/as_coerce.swift index bf63604d4b8df..96c417c391c7d 100644 --- a/test/expr/cast/as_coerce.swift +++ b/test/expr/cast/as_coerce.swift @@ -217,7 +217,17 @@ _ = (f11295_Overload as (Double, Double) -> Double)(0, 0) _ = (1 - 2 / 3 * 6) as UInt _ = 1/4 as Float > 3/2 as Float // Ok -_ = 1/4 as Int > 3/2 as Int // Ok +_ = 1/4 as Int > 3/2 as Int // Ok + +// Coerce tuple elements +func f11295_Tuple(_ a: (Int, Int)){} +func f11295_TupleGeneric(_ a: (T, T)){} + +let _: (Int, Int) = (1 as Int, 1) // Ok +_ = (1 as Int, 1) // Ok + +f11295_Tuple((1 as Int, 1)) // Ok +f11295_TupleGeneric((1 as Int, 1)) // Ok // Special cases where the coerced expression type is inferred by context. From 3f39531e51bd56472f14383fd15dc6837c9d0e3f Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Thu, 26 Dec 2019 06:34:15 -0300 Subject: [PATCH 15/24] [CSFix] Skipping the RemoveUnnecessaryCoercion if representative type source points to a tuple element. --- lib/Sema/CSFix.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 784f91bb6fa91..eedf1adada67b 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1198,13 +1198,19 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, // Only diagnose if we have all type variables resolved in the system. if (cs.hasFreeTypeVariables()) return false; - + auto representative = cs.getRepresentative(typeVariable); - if (auto *typeSourceLocator = cs.getTypeVariableBindingLocator(representative)) { + if (auto *typeSourceLocator = + cs.getTypeVariableBindingLocator(representative)) { // If the type variable binding source locator is the same the // contextual type equality is coming from this coercion. if (typeSourceLocator == cs.getConstraintLocator(locator)) return false; + + // Not warn if locator points to a TupleElement to avoid + // incorrect warnings. + if (typeSourceLocator->isLastElement()) + return false; } } From 60ab6dbd03fb7833ccfa37671e3b2dd9320db601 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sun, 29 Dec 2019 21:39:56 -0300 Subject: [PATCH 16/24] [tests] Adding function overload test cases --- test/expr/cast/as_coerce.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/expr/cast/as_coerce.swift b/test/expr/cast/as_coerce.swift index 96c417c391c7d..eee79384c9302 100644 --- a/test/expr/cast/as_coerce.swift +++ b/test/expr/cast/as_coerce.swift @@ -215,10 +215,17 @@ func f11295_Overload(c: Double, d: Double) -> Double { } _ = (f11295_Overload as (Int, Int) -> Int)(0, 0) _ = (f11295_Overload as (Double, Double) -> Double)(0, 0) -_ = (1 - 2 / 3 * 6) as UInt +_ = (1 - 2 / 3 * 6) as UInt // OK _ = 1/4 as Float > 3/2 as Float // Ok _ = 1/4 as Int > 3/2 as Int // Ok +// Function overload +func f11295_overload() -> Int { 0 } +func f11295_overload() -> Double { 0.0 } + +_ = f11295_overload() as Int // OK +_ = f11295_overload() as Double // OK + // Coerce tuple elements func f11295_Tuple(_ a: (Int, Int)){} func f11295_TupleGeneric(_ a: (T, T)){} From 933075db4fec92f59ae7f665d124973da8d74cbd Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Thu, 2 Jan 2020 20:30:31 -0300 Subject: [PATCH 17/24] [CSFix] Add check to dont diagnose if has SubExpressionDiagnostics flag --- lib/Sema/CSFix.cpp | 9 +++++---- test/expr/cast/as_coerce.swift | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index eedf1adada67b..d9f05eaf427ac 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1150,6 +1150,11 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, if (ctx.LangOpts.DisableRedundantCoercionWarning) return false; + // Don't diagnose if this is coming from a CSDiag typecheck subExpr diagnostics. + // We can remove this once CSDiag is gone. + if (cs.Options.contains(ConstraintSystemFlags::SubExpressionDiagnostics)) + return false; + auto last = locator.last(); bool isExplicitCoercion = last && last->is(); @@ -1168,10 +1173,6 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, if (!fromType->isEqual(castType) && !castType->hasTypeVariable()) return false; - // Fixed type was already applied to the subEpxr. - if (expr->getSubExpr()->getType()) - return false; - auto toTypeRepr = expr->getCastTypeLoc().getTypeRepr(); // Don't emit this diagnostic for Implicitly unwrapped optional types diff --git a/test/expr/cast/as_coerce.swift b/test/expr/cast/as_coerce.swift index eee79384c9302..3930f1b4617c3 100644 --- a/test/expr/cast/as_coerce.swift +++ b/test/expr/cast/as_coerce.swift @@ -81,7 +81,7 @@ c3 as C4 // expected-error {{'C3' is not convertible to 'C4'; did you mean to us // Various incorrect diagnostics for explicit type conversions 1 as Double as Float // expected-error{{cannot convert value of type 'Double' to type 'Float' in coercion}} 1 as Int as String // expected-error{{cannot convert value of type 'Int' to type 'String' in coercion}} -Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}} expected-warning {{redundant cast to 'Double' has no effect}} {{11-21=}} +Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}} ["awd"] as [Int] // expected-error{{cannot convert value of type 'String' to expected element type 'Int'}} ([1, 2, 1.0], 1) as ([String], Int) // expected-error@-1 2 {{cannot convert value of type 'Int' to expected element type 'String'}} From 4fc26b7d9ade474c3a8d867d97377e475f9b34d2 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Thu, 23 Jan 2020 17:13:57 -0300 Subject: [PATCH 18/24] [Diagnostics] Improving logic and removing old checks on RemoveUnnecessaryCoercion fix and adjusting some tests --- lib/Sema/CSDiagnostics.cpp | 21 ++++++++++++--------- lib/Sema/CSFix.cpp | 13 ++----------- lib/Sema/CSSimplify.cpp | 12 +++++------- lib/Sema/CSSolver.cpp | 5 ++--- lib/Sema/ConstraintSystem.cpp | 8 +++++--- test/expr/cast/as_coerce.swift | 2 +- test/expr/cast/dictionary_bridge.swift | 2 +- test/expr/cast/dictionary_coerce.swift | 2 +- test/expr/cast/objc_coerce_array.swift | 2 +- 9 files changed, 30 insertions(+), 37 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 787b7df62e3a6..51127912d0d55 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -753,6 +753,11 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { break; } + case ConstraintLocator::ExplicitTypeCoercion: { + diagnostic = diag::cannot_convert_coerce; + break; + } + default: break; } @@ -2069,7 +2074,8 @@ bool ContextualFailure::diagnoseAsError() { diagnostic = diag::cannot_convert_condition_value; break; } - + + case ConstraintLocator::ExplicitTypeCoercion: case ConstraintLocator::InstanceType: { if (diagnoseCoercionToUnrelatedType()) return true; @@ -5556,16 +5562,13 @@ bool UnnecessaryCoercionFailure::diagnoseAsError() { diag::unnecessary_same_typealias_type_coercion, getFromType(), castType) .fixItRemove(sourceRange); - } else { - emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion, - castType) - .fixItRemove(sourceRange); + return true; } - } else { - emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion, - castType) - .fixItRemove(sourceRange); } + + emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion, + castType) + .fixItRemove(sourceRange); return true; } diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index d9f05eaf427ac..bd88039284ef2 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1165,12 +1165,12 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, // Check to ensure the from and to types are equal the cast type. // This is required to handle cases where the conversion is done - // using compiler intrinsics e.g. _HasCustomAnyHashableRepresentation + // using compiler intrinsics of _HasCustomAnyHashableRepresentation // to AnyHashable where if we coerce a generic type that conforms to // this protocol to AnyHashable we match equal types here, but the // explicit coercion is still required. auto castType = cs.getType(expr->getCastTypeLoc()); - if (!fromType->isEqual(castType) && !castType->hasTypeVariable()) + if (!fromType->isEqual(castType) && cs.isAnyHashableType(castType)) return false; auto toTypeRepr = expr->getCastTypeLoc().getTypeRepr(); @@ -1196,10 +1196,6 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, auto coercedType = cs.getType(expr->getSubExpr()); if (auto *typeVariable = coercedType->getAs()) { - // Only diagnose if we have all type variables resolved in the system. - if (cs.hasFreeTypeVariables()) - return false; - auto representative = cs.getRepresentative(typeVariable); if (auto *typeSourceLocator = cs.getTypeVariableBindingLocator(representative)) { @@ -1207,11 +1203,6 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, // contextual type equality is coming from this coercion. if (typeSourceLocator == cs.getConstraintLocator(locator)) return false; - - // Not warn if locator points to a TupleElement to avoid - // incorrect warnings. - if (typeSourceLocator->isLastElement()) - return false; } } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 6478fe5343153..99656f02e12fe 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -10510,14 +10510,12 @@ void ConstraintSystem::addExplicitConversionConstraint( auto locatorPtr = getConstraintLocator(locator); ConstraintLocator *coerceLocator = locatorPtr; - if (allowFixes && shouldAttemptFixes()) { - auto *anchor = locator.getAnchor(); - if (isa(anchor) && !anchor->isImplicit()) { - coerceLocator = - getConstraintLocator(anchor, LocatorPathElt::ExplicitTypeCoercion()); - } + auto *anchor = locator.getAnchor(); + if (anchor && isa(anchor) && !anchor->isImplicit()) { + coerceLocator = + getConstraintLocator(anchor, LocatorPathElt::ExplicitTypeCoercion()); } - + // Coercion (the common case). Constraint *coerceConstraint = Constraint::create(*this, ConstraintKind::Conversion, diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 28c7cf58a2df1..728209014df90 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -91,7 +91,7 @@ Solution ConstraintSystem::finalize() { case FreeTypeVariableBinding::UnresolvedType: assignFixedType(tv, ctx.TheUnresolvedType, - tv->getImpl().getLocator()); + /*locator*/nullptr); break; } } @@ -206,8 +206,7 @@ void ConstraintSystem::applySolution(const Solution &solution) { // If we don't already have a fixed type for this type variable, // assign the fixed type from the solution. if (!getFixedType(binding.first) && !binding.second->hasTypeVariable()) { - auto typeVar = binding.first; - assignFixedType(typeVar, binding.second, typeVar->getImpl().getLocator(), + assignFixedType(binding.first, binding.second, /*locator*/nullptr, /*updateState=*/false); } } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index ca78c2ecb0cf8..479137b7bac62 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -198,9 +198,11 @@ void ConstraintSystem::assignFixedType(TypeVariableType *typeVar, Type type, } } } - - // Recording fixed type source locator for type variable. - recordTypeVariableBindingLocator(typeVar, locator); + + if (locator) { + // Recording fixed type source locator for type variable. + recordTypeVariableBindingLocator(typeVar, locator); + } // Notify the constraint graph. CG.bindTypeVariable(typeVar, type); diff --git a/test/expr/cast/as_coerce.swift b/test/expr/cast/as_coerce.swift index 3930f1b4617c3..eee79384c9302 100644 --- a/test/expr/cast/as_coerce.swift +++ b/test/expr/cast/as_coerce.swift @@ -81,7 +81,7 @@ c3 as C4 // expected-error {{'C3' is not convertible to 'C4'; did you mean to us // Various incorrect diagnostics for explicit type conversions 1 as Double as Float // expected-error{{cannot convert value of type 'Double' to type 'Float' in coercion}} 1 as Int as String // expected-error{{cannot convert value of type 'Int' to type 'String' in coercion}} -Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}} +Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}} expected-warning {{redundant cast to 'Double' has no effect}} {{11-21=}} ["awd"] as [Int] // expected-error{{cannot convert value of type 'String' to expected element type 'Int'}} ([1, 2, 1.0], 1) as ([String], Int) // expected-error@-1 2 {{cannot convert value of type 'Int' to expected element type 'String'}} diff --git a/test/expr/cast/dictionary_bridge.swift b/test/expr/cast/dictionary_bridge.swift index a2e7b4010fc94..bdd0d129bdd3e 100644 --- a/test/expr/cast/dictionary_bridge.swift +++ b/test/expr/cast/dictionary_bridge.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-redundant-coercion-warning // REQUIRES: objc_interop diff --git a/test/expr/cast/dictionary_coerce.swift b/test/expr/cast/dictionary_coerce.swift index 0573ba4726594..49d20e70efb50 100644 --- a/test/expr/cast/dictionary_coerce.swift +++ b/test/expr/cast/dictionary_coerce.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-redundant-coercion-warning class C : Hashable { var x = 0 diff --git a/test/expr/cast/objc_coerce_array.swift b/test/expr/cast/objc_coerce_array.swift index 22f3c5eb0aadb..6e604110a818a 100644 --- a/test/expr/cast/objc_coerce_array.swift +++ b/test/expr/cast/objc_coerce_array.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -verify %s +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -verify %s -disable-redundant-coercion-warning // REQUIRES: objc_interop import Foundation From 49ef402005be5cd68ab5e56fc738a7c6782f9c11 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Tue, 4 Feb 2020 23:50:16 -0300 Subject: [PATCH 19/24] [tests] Adding few more test cases for redundant coercion warning --- test/expr/cast/as_coerce.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/expr/cast/as_coerce.swift b/test/expr/cast/as_coerce.swift index eee79384c9302..1fc45583c44b9 100644 --- a/test/expr/cast/as_coerce.swift +++ b/test/expr/cast/as_coerce.swift @@ -226,6 +226,15 @@ func f11295_overload() -> Double { 0.0 } _ = f11295_overload() as Int // OK _ = f11295_overload() as Double // OK +// Param overload with generics +func f11295_param_overload(_ a: Int) {} +func f11295_param_overload(_ a: Double) {} + +func fNum() -> N { 0 } + +f11295_param_overload(fNum() as Int) // Ok +f11295_param_overload(fNum() as Double) // Ok + // Coerce tuple elements func f11295_Tuple(_ a: (Int, Int)){} func f11295_TupleGeneric(_ a: (T, T)){} From d2d32a2a345462718f446332bb368e5bab757c4e Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sun, 23 Feb 2020 18:57:20 -0300 Subject: [PATCH 20/24] [CSFix] Remove CSDiag flag on RemoveUnnecessaryCoercion::attempt --- lib/Sema/CSFix.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index bd88039284ef2..0df42b66f2a0f 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1149,12 +1149,7 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, auto &ctx = cs.getASTContext(); if (ctx.LangOpts.DisableRedundantCoercionWarning) return false; - - // Don't diagnose if this is coming from a CSDiag typecheck subExpr diagnostics. - // We can remove this once CSDiag is gone. - if (cs.Options.contains(ConstraintSystemFlags::SubExpressionDiagnostics)) - return false; - + auto last = locator.last(); bool isExplicitCoercion = last && last->is(); From f66405c10659d3de9e8c9524644c3ed86b457b15 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Thu, 19 Mar 2020 23:38:09 -0300 Subject: [PATCH 21/24] [Diagnostics] Adjust RemoveUnnecessaryCoercion and UnnecessaryCoercionFailure to use solution on diagnose() --- lib/Sema/CSDiagnostics.h | 4 ++-- lib/Sema/CSFix.cpp | 5 ++--- lib/Sema/CSFix.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 85bf872ea8c96..bb65e44b49d68 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -1804,10 +1804,10 @@ class UnnecessaryCoercionFailure final : public ContextualFailure { public: - UnnecessaryCoercionFailure(ConstraintSystem &cs, + UnnecessaryCoercionFailure(const Solution &solution, Type fromType, Type toType, ConstraintLocator *locator) - : ContextualFailure(cs, fromType, toType, locator) {} + : ContextualFailure(solution, fromType, toType, locator) {} bool diagnoseAsError() override; }; diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 0df42b66f2a0f..37d1394262fd7 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1136,9 +1136,8 @@ IgnoreContextualType *IgnoreContextualType::create(ConstraintSystem &cs, IgnoreContextualType(cs, resultTy, specifiedTy, locator); } -bool RemoveUnnecessaryCoercion::diagnose(bool asNote) const { - auto &cs = getConstraintSystem(); - UnnecessaryCoercionFailure failure(cs, getFromType(), getToType(), +bool RemoveUnnecessaryCoercion::diagnose(const Solution &solution, bool asNote) const { + UnnecessaryCoercionFailure failure(solution, getFromType(), getToType(), getLocator()); return failure.diagnose(asNote); } diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index f933d64691725..81a6444a181aa 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -1577,7 +1577,7 @@ class RemoveUnnecessaryCoercion : public ContextualMismatch { return "remove unnecessary explicit type coercion"; } - bool diagnose(bool asNote = false) const override; + bool diagnose(const Solution &solution, bool asNote = false) const override; static bool attempt(ConstraintSystem &cs, Type fromType, Type toType, ConstraintLocatorBuilder locator); From 2a85acb4c6aca6c0feb5cff6e4a3b3c8791f0ae3 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Fri, 20 Mar 2020 00:53:51 -0300 Subject: [PATCH 22/24] [ConstraintLocator] Adjust isCoerce() to check for LocatorPathElt::ExplicitTypeCoercion path --- lib/Sema/ConstraintLocator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index ec87b03ae2caf..25862c96426e6 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -197,7 +197,8 @@ bool ConstraintLocator::isForAssignment() const { } bool ConstraintLocator::isForCoercion() const { - return directlyAt(); + return isLastElement() || + directlyAt(); } bool ConstraintLocator::isForOptionalTry() const { From 3225f62f703ddf2b93ead3ffc3645d6b8ca6104a Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Sat, 25 Apr 2020 22:11:47 -0300 Subject: [PATCH 23/24] [Diagnostics] Adjust to get expr from type node anchor --- lib/Sema/CSDiagnostics.cpp | 7 +++---- lib/Sema/CSFix.cpp | 2 +- lib/Sema/CSSimplify.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 51127912d0d55..0bd3bc7acbc67 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -5547,7 +5547,7 @@ bool ThrowingFunctionConversionFailure::diagnoseAsError() { } bool UnnecessaryCoercionFailure::diagnoseAsError() { - auto expr = cast(getAnchor()); + auto expr = getAsExpr(getAnchor()); auto sourceRange = SourceRange(expr->getLoc(), expr->getCastTypeLoc().getSourceRange().End); auto castType = expr->getCastTypeLoc().getType(); @@ -5558,15 +5558,14 @@ bool UnnecessaryCoercionFailure::diagnoseAsError() { auto toTypeAlias = cast(getToType().getPointer()); // If the typealias are different, we need a warning mentioning both types. if (fromTypeAlias->getDecl() != toTypeAlias->getDecl()) { - emitDiagnostic(expr->getLoc(), - diag::unnecessary_same_typealias_type_coercion, + emitDiagnostic(diag::unnecessary_same_typealias_type_coercion, getFromType(), castType) .fixItRemove(sourceRange); return true; } } - emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion, + emitDiagnostic(diag::unnecessary_same_type_coercion, castType) .fixItRemove(sourceRange); return true; diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 37d1394262fd7..a0c5428e8d5e5 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1155,7 +1155,7 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, if (!isExplicitCoercion) return false; - auto expr = cast(locator.getAnchor()); + auto expr = getAsExpr(locator.getAnchor()); // Check to ensure the from and to types are equal the cast type. // This is required to handle cases where the conversion is done diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 99656f02e12fe..51111c2480388 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -10510,7 +10510,7 @@ void ConstraintSystem::addExplicitConversionConstraint( auto locatorPtr = getConstraintLocator(locator); ConstraintLocator *coerceLocator = locatorPtr; - auto *anchor = locator.getAnchor(); + auto *anchor = getAsExpr(locator.getAnchor()); if (anchor && isa(anchor) && !anchor->isImplicit()) { coerceLocator = getConstraintLocator(anchor, LocatorPathElt::ExplicitTypeCoercion()); From b22b1b8be7ad65f9d2db9ae416e612efaa9bc636 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Wed, 19 Aug 2020 09:57:29 -0300 Subject: [PATCH 24/24] [Sema] Fixing compilation errors caused by removed APIs --- lib/Sema/CSDiagnostics.cpp | 4 ++-- lib/Sema/CSFix.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 0bd3bc7acbc67..d7b33fefcdaac 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -5549,8 +5549,8 @@ bool ThrowingFunctionConversionFailure::diagnoseAsError() { bool UnnecessaryCoercionFailure::diagnoseAsError() { auto expr = getAsExpr(getAnchor()); auto sourceRange = - SourceRange(expr->getLoc(), expr->getCastTypeLoc().getSourceRange().End); - auto castType = expr->getCastTypeLoc().getType(); + SourceRange(expr->getLoc(), expr->getCastTypeRepr()->getSourceRange().End); + auto castType = getType(expr->getCastTypeRepr()); if (isa(getFromType().getPointer()) && isa(getToType().getPointer())) { diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index a0c5428e8d5e5..3064e05d23b00 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1163,11 +1163,11 @@ bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType, // to AnyHashable where if we coerce a generic type that conforms to // this protocol to AnyHashable we match equal types here, but the // explicit coercion is still required. - auto castType = cs.getType(expr->getCastTypeLoc()); + auto castType = cs.getType(expr->getCastTypeRepr()); if (!fromType->isEqual(castType) && cs.isAnyHashableType(castType)) return false; - auto toTypeRepr = expr->getCastTypeLoc().getTypeRepr(); + auto toTypeRepr = expr->getCastTypeRepr(); // Don't emit this diagnostic for Implicitly unwrapped optional types // e.g. i as Int!