Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[SR-12369] Invalid conversions allowed when using ?? #54803

Closed
hamishknight opened this issue Mar 14, 2020 · 3 comments
Closed

[SR-12369] Invalid conversions allowed when using ?? #54803

hamishknight opened this issue Mar 14, 2020 · 3 comments
Assignees
Labels
accepts invalid Bug: Accepts invalid bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis

Comments

@hamishknight
Copy link
Collaborator

Previous ID SR-12369
Radar None
Original Reporter @hamishknight
Type Bug
Status Closed
Resolution Done
Environment

Swift version 5.2-dev (LLVM a8c5c17, Swift 3a1ce04d31)
Target: x86_64-apple-darwin18.5.0

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, AcceptsInvalid, TypeChecker
Assignee @hamishknight
Priority Medium

md5: d29192a365bb056a838214da0da4a972

Issue Description:

We correctly prevent the following bridging conversions:

import Foundation

let x = 0 as NSString // error: Cannot convert value of type 'Int' to type 'NSString' in coercion
let y = "" as NSNumber // Cannot convert value of type 'String' to type 'NSNumber' in coercion

But we appear to allow them if the ?? operator is used:

let x = (0 ?? 0) as NSString // Compiles
let y = ("" ?? "") as NSNumber // Also compiles

In an asserts build these hit an assertion in SILGen:

Assertion failed: (inputSubstType->isExactSuperclassOf(outputSubstType) && "should be inheritance relationship between input and output"), function transform, file /Users/hamishknight/Desktop/swift-dev/swift/lib/SILGen/SILGenPoly.cpp, line 498.
Stack dump:
0.  Program arguments: ./swift -frontend -emit-sil /Users/hamishknight/Desktop/Stochastic Projects/newnew/newnew/main.swift -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -debug-diagnostic-names -disable-objc-attr-requires-foundation-module
1.  Swift version 5.2-dev (LLVM a8c5c172cc, Swift 3a1ce04d31)
2.  While evaluating request SILGenWholeModuleRequest(SIL Generation for module main)
0  swift                    0x000000010c383405 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1  swift                    0x000000010c3823b8 llvm::sys::RunSignalHandlers() + 248
2  swift                    0x000000010c3839fc SignalHandler(int) + 268
3  libsystem_platform.dylib 0x00007fff79171b5d _sigtramp + 29
4  swift                    0x000000010eca2ba8 cmark_strbuf__initbuf + 180875
5  libsystem_c.dylib        0x00007fff790316a6 abort + 127
6  libsystem_c.dylib        0x00007fff78ffa20d basename_r + 0
7  swift                    0x000000010c525693 (anonymous namespace)::Transform::transform(swift::Lowering::ManagedValue, swift::Lowering::AbstractionPattern, swift::CanType, swift::Lowering::AbstractionPattern, swift::CanType, swift::SILType, swift::Lowering::SGFContext) (.cold.93) + 35
8  swift                    0x0000000108347743 (anonymous namespace)::Transform::transform(swift::Lowering::ManagedValue, swift::Lowering::AbstractionPattern, swift::CanType, swift::Lowering::AbstractionPattern, swift::CanType, swift::SILType, swift::Lowering::SGFContext) + 12883
9  swift                    0x0000000108343a86 swift::Lowering::SILGenFunction::emitTransformedValue(swift::SILLocation, swift::Lowering::ManagedValue, swift::Lowering::AbstractionPattern, swift::CanType, swift::Lowering::AbstractionPattern, swift::CanType, swift::SILType, swift::Lowering::SGFContext) + 118
10 swift                    0x00000001082b6fd4 emitUnabstractedCast(swift::Lowering::SILGenFunction&, swift::SILLocation, swift::Lowering::ManagedValue, swift::CanType, swift::CanType) + 372
11 swift                    0x00000001082b4267 emitNativeToCBridgedValue(swift::Lowering::SILGenFunction&, swift::SILLocation, swift::Lowering::ManagedValue, swift::CanType, swift::CanType, swift::SILType, swift::Lowering::SGFContext) + 5815
12 swift                    0x00000001082d41f1 swift::Lowering::Conversion::emit(swift::Lowering::SILGenFunction&, swift::SILLocation, swift::Lowering::ManagedValue, swift::Lowering::SGFContext) const + 545
13 swift                    0x00000001082d3f1e swift::Lowering::ConvertingInitialization::finishEmission(swift::Lowering::SILGenFunction&, swift::SILLocation, swift::Lowering::ManagedValue) + 94
14 swift                    0x00000001082d3d85 swift::Lowering::SILGenFunction::emitConvertedRValue(swift::SILLocation, swift::Lowering::Conversion const&, swift::Lowering::SGFContext, llvm::function_ref<swift::Lowering::ManagedValue (swift::Lowering::SILGenFunction&, swift::SILLocation, swift::Lowering::SGFContext)>) + 405
15 swift                    0x00000001082d3bd8 swift::Lowering::SILGenFunction::emitConvertedRValue(swift::Expr*, swift::Lowering::Conversion const&, swift::Lowering::SGFContext) + 104
16 swift                    0x00000001083032d8 tryEmitAsBridgingConversion(swift::Lowering::SILGenFunction&, swift::Expr*, bool, swift::Lowering::SGFContext) + 440
17 swift                    0x00000001082f7025 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 9685
18 swift                    0x00000001082e78ef swift::Lowering::SILGenFunction::emitExprInto(swift::Expr*, swift::Lowering::Initialization*, llvm::Optional<swift::SILLocation>) + 303
19 swift                    0x00000001082d8a5f swift::Lowering::SILGenFunction::emitPatternBinding(swift::PatternBindingDecl*, unsigned int) + 335
20 swift                    0x00000001082d8b3d swift::Lowering::SILGenFunction::visitPatternBindingDecl(swift::PatternBindingDecl*) + 45
21 swift                    0x0000000108287c12 swift::Lowering::SILGenModule::visitTopLevelCodeDecl(swift::TopLevelCodeDecl*) + 498
22 swift                    0x000000010828827a (anonymous namespace)::SILGenModuleRAII::emitSourceFile(swift::SourceFile*) + 874
23 swift                    0x0000000108289244 swift::SILGenWholeModuleRequest::evaluate(swift::Evaluator&, swift::SILGenDescriptor) const + 180
24 swift                    0x0000000108358ec1 swift::SimpleRequest<swift::SILGenWholeModuleRequest, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> > (swift::SILGenDescriptor), (swift::CacheKind)0>::evaluateRequest(swift::SILGenWholeModuleRequest const&, swift::Evaluator&) + 33
25 swift                    0x000000010828c667 llvm::Expected<swift::SILGenWholeModuleRequest::OutputType> swift::Evaluator::getResultUncached<swift::SILGenWholeModuleRequest>(swift::SILGenWholeModuleRequest const&) + 343
26 swift                    0x00000001082893c4 swift::performSILGeneration(swift::ModuleDecl*, swift::Lowering::TypeConverter&, swift::SILOptions const&) + 116
27 swift                    0x0000000107f16d2d performCompile(swift::CompilerInstance&, swift::CompilerInvocation const&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*) + 8717
28 swift                    0x0000000107f13b41 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3553
29 swift                    0x0000000107ea6b8d main + 861
30 libdyld.dylib            0x00007fff78f8c3d5 start + 1
31 libdyld.dylib            0x0000000000000008 start + 18446603338486594612
fish: './swift -frontend -emit-sil /Us…' terminated by signal SIGABRT (Abort)

And in a non-asserts build we miscompile.

This also extends to other conversions, such as:

func foo(_ x: String) -> Int {
  return (x ?? "") as Int
}

which also miscompiles in a no-asserts build.

It looks like we're not correctly exploring a type variable's fixed bindings in ConstraintGraph::gatherConstraints.

Unfortunately my attempt to fix this caused the test case for rdar://problem/54274245 to no longer compile:

func rdar54274245(_ arr: [Any]?) {
  _ = (arr ?? []) as [NSObject]
}

But this is because we now correctly re-activate the bridging constraint, which then fails.

The equivalent conversion without ?? already doesn't compile today:

func foo(_ arr: [Any]) {
  _ = arr as [NSObject] // error: cannot convert value of type '[Any]' to type '[NSObject]' in coercion
}
@LucianoPAlmeida
Copy link
Collaborator

@hamishknight Are you working on this? If not I can take a look 🙂

@hamishknight
Copy link
Collaborator Author

@LucianoPAlmeida I came up with a fix (which is to always make sure we visit the type variable's fixed bindings in gatherConstraints – currently we can incorrectly bail if we already visited the type variable as an adjacency), but unfortunately that causes a source compatibility regression for the (arr ?? []) as [NSObject] example. I'm planning on asking what we can do about this on Monday, but in the mean time you're more than welcome to take a look if you want 🙂

@hamishknight
Copy link
Collaborator Author

Fixed by #30886

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepts invalid Bug: Accepts invalid bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

2 participants