2017-10-20 5 views
6

मुझे यकीन नहीं है कि 'हार्ड-असफल' सही शब्द है, लेकिन यहां समस्या है जिसका सामना मैं कर रहा हूं। और यह मुझे काफी कुछ समय साथ ले जाती है छोटी संभव उदाहरण के लिए इस पुन: पेश करने, इसलिए यहाँ यह जाता है:कोटलिन एक अनुमानित (इन-साइट) पैरामीटर को अप-कास्ट हार्ड-असफल कर रहा है

class BaseParameterizedType<T> 

fun <U: BaseParameterizedType<*>> getSpecific(clazz: KClass<in U>) : U { 
    TODO() 
} 

fun example(arg: KClass<out BaseParameterizedType<*>>)) { 
    getSpecific(arg.innerType) 
} 

ठीक है, तो कोड के ऊपर 'यह करें' पर विफल रहता है, लेकिन अगर यह वहाँ है और यदि नहीं था समारोह सामान्य रूप से लौटा, तो यह निश्चित रूप से एक शून्य सूचक अपवाद के साथ विफल रहता है। मैं यह पता लगाने की क्या गलत हो रहा था बहुत कोशिश की, तो मैं (kotlin बाईटकोड से) decompiled जावा कोड में बदल गया:

public static final void example(@NotNull KClass arg) { 
    Intrinsics.checkParameterIsNotNull(arg, "arg"); 
    getSpecific(arg.getInnerType()); 
    throw null; // <-- The problem 
} 

अगर मैं इन रूपों में से किसी को getSpecific(clz: KClass<in U>) : U के समारोह हस्ताक्षर बदलने के लिए:

  1. getSpecific(clz: KClass<out U>) : U
  2. getSpecific(clz: KClass<U>) : U
  3. getSpecific(clz: KClass<in U>) : BaseParameterizedType<*>

या example(arg: KClass<out BaseParameterizedType<*>) या example(arg: KClass<BaseParameterizedType<*>>) को भी समारोह है, तो उत्पन्न कोड है:

public static final void example(@NotNull KClass arg) { 
    Intrinsics.checkParameterIsNotNull(arg, "arg"); 
    getSpecific(arg.getInnerType()); 
} 

अब, चलो कॉल-स्थल पर मान लीजिए, मैं यह करने के लिए बदलने के लिए:

getSpecific(BaseParameterizedType::class) 

तो यह भी नहीं है throw null खंड उत्पन्न करें। तो, मुझे लगता है कि कोटलिन के साथ ऐसा कुछ करने का अनुमान है कि यह कलाकार हमेशा असफल रहेगा या अनुमान लगाने के लिए अनिश्चित जानकारी उपलब्ध है?

तो, हम जानते हैं कि arg.innerTypeKClass<out BaseParameterizedType<*>> है और हम एक साइट KClass<in BaseParameterizedType<*>> को स्वीकार करने में इसका इस्तेमाल करते हैं, तो क्यों UBaseParamterizedType<*>> को अनुमानित नहीं है। यह सचमुच एकमात्र प्रकार है जो कभी मेल खाता है।

उसी समय, मुझे लगता है कि सिर्फ throw null कथन उत्पन्न करना अविश्वसनीय रूप से डीबग करना मुश्किल है। स्टैकट्रैक केवल उस रेखा को इंगित करेगा जहां getSpecific है और अच्छी किस्मत यह पता लगाना है कि शून्य सूचक अपवाद कहाँ से आया था।

उत्तर

4

यह एक ज्ञात प्रकार निष्कर्ष कोने मामले से निपटने जब अनुमानित प्रकार Nothing है के बारे में मुद्दा है (और यह आपके मामले में है):

enter image description here

अनुमान है, क्योंकि एक के इस तरह से बर्ताव करता है अनुमान KClass<in U> और KClass<out BaseParameterizedType<*>> अनुमानों के लिए जबरन प्रयास।

मूल रूप से, एक ही समय में एक out -projected प्रकार का क्या मतलब in Nothing (वास्तविक प्रकार तर्क उपप्रकार के किसी भी हो सकता है क्योंकि, और कुछ भी नहीं सुरक्षित रूप से में पारित किया जा सकता)। तो, KClass<in U> के साथ KClass<out BaseParameterizedType<*>> से मिलान करने के लिए संकलक U := Nothing चुनता है, जिसका अर्थ है कि फ़ंक्शन कॉल Nothing भी लौटाता है।

टिप्पणी: एक Foo<out Any> प्रक्षेपण T := Any साथ Foo<in T> से मेल नहीं कर सकते, क्योंकि Foo<out Any> के लिए भेजे गए मान के वास्तविक प्रकार तर्क हो सकता है, उदाहरण के लिए, Int। फिर, यदि Foo<T> अपने कुछ कार्यों में T स्वीकार करता है, तो उपर्युक्त मिलान आपको Any उदाहरणों को Foo<Int> से अपेक्षा करने की अनुमति नहीं देता है। दरअसल, in Nothingout-प्रोजेक्ट प्रकार की अज्ञात प्रकृति की वजह से उनसे मिलान करने का एकमात्र तरीका बन जाता है।

उसके बाद, एक Nothing -returning समारोह कॉल के लिए, संकलक सम्मिलित करता है कि throw null बाईटकोड यकीन है कि निष्पादन के लिए आगे बढ़ना नहीं करता है (एक Nothing -typed अभिव्यक्ति is supposed to never finish correctly का मूल्यांकन) बनाने के लिए। KT-20849, KT-18789

+0

हाल ही में इस मुद्दे सतह किया? क्योंकि यह कोड का हिस्सा है जो मेरे लिए पूरी तरह से काम कर रहा था, और यह हाल ही में तोड़ दिया। मुझे खेद है कि मैं सटीक कोटलिन संस्करण को पिन-पॉइंट करने में सक्षम नहीं हूं, जहां इसे तोड़ना शुरू हो गया क्योंकि हम संस्करण को अद्यतन करना जारी रखते हैं और यह ऐसा कुछ है जो दुर्भाग्यवश हमारे परीक्षण-मामलों से ढंका नहीं है और यह शायद ही कभी पहुंच गया है कोड। इसलिए यह पता लगाना मुश्किल है कि वास्तव में तोड़ना शुरू हो गया था। –

1

@hotkey उल्लेख बस के रूप में, इसका मतलब है outin Nothing और Nothing null.So फेंक होगा मैं इस तरह कुछ परीक्षण करना: ->

fun main(args: Array<String>) { 
    tryToReturnNothing() 
} 

fun tryToReturnNothing(): Nothing{ 
    TODO() 
} 

उत्पन्न

समस्याएं देखें

public static final void main(@NotNull String[] args) { 
     Intrinsics.checkParameterIsNotNull(args, "args"); 
     tryToReturnNothing(); 
     throw null; // here 
    } 

    @NotNull 
    public static final Void tryToReturnNothing() { 
     throw (Throwable)(new NotImplementedError((String)null, 1, (DefaultConstructorMarker)null)); 
    } 

null के प्रकार को ध्यान में रखते हुएहै, हम Nothing के बजाय Nothing? वापस कर सकते हैं। इसलिए मैं U? में U बदल दें और फिर throw null खंड गायब हो जाते हैं:

fun <U: BaseParameterizedType<*>> getSpecific(clazz: KClass<in U>) : U? { // see here: change U to U? 
    TODO() 
} 

fun example(arg: KClass<out BaseParameterizedType<*>>) { 
    getSpecific(arg) 
} 

उत्पन्न ->

@Nullable 
    public static final BaseParameterizedType getSpecific(@NotNull KClass clazz) { 
     Intrinsics.checkParameterIsNotNull(clazz, "clazz"); 
     throw (Throwable)(new NotImplementedError((String)null, 1, (DefaultConstructorMarker)null)); 
    } 

    public static final void example(@NotNull KClass arg) { 
     Intrinsics.checkParameterIsNotNull(arg, "arg"); 
     getSpecific(arg); 
    } 
संबंधित मुद्दे