2012-09-26 9 views
17

हाल ही में मैंने एक अजीब (मेरे लिए) कंपाइलर त्रुटि संदेश में ठोकर खाई। निम्नलिखित कोड पर विचार करें:कक्षा ए में एक प्रकार का पैरामीटर है, लेकिन टाइप बी में एक

trait Foo { 
    type Res <: Foo 
    type Bar[X <: Res] 
} 

class MyFoo extends Foo { 
    override type Res = MyFoo 
    override type Bar[X <: Res] = List[X] 
} 

type FOO[F <: Foo, R <: Foo, B[_ <: R]] = F { type Res = R; 
               type Bar[X <: R] = B[X] } 

def process[F <: Foo, R <: Foo, B[_ <: R]](f: FOO[F, R, B]) {} 

अब, अगर मैं process विधि मैं स्पष्ट रूप से प्रकार पैरामीटर लिखने की कॉल करना चाहते हैं: यदि मैं लिखना

process[MyFoo, MyFoo, List](new MyFoo) // fine 

:

process(new MyFoo) 

या

process((new MyFoo): FOO[MyFoo, MyFoo, List]) 

मैं निम्न त्रुटि संदेश मिलता है: प्रकार तर्कों की

अनुमानित प्रकार (MyFoo, MyFoo, सूची [X]) प्रकार पैरामीटर की उम्मीद प्रकार (प्रकार एफ, प्रकार आर, ग्रुप बी के अनुरूप नहीं है)। सूची [एक्स] के प्रकार पैरामीटर से मेल नहीं खाते ग्रुप बी की उम्मीद पैरामीटर: वर्ग सूची एक प्रकार पैरामीटर है, लेकिन ग्रुप बी एक

है क्यों संकलक प्रकार (लगा सकते isn't हालांकि मैं स्पष्ट रूप से कहा उन्हें कॉल पैरामीटर पर)? और class List has one type parameter, but type B has one का क्या अर्थ है? कुछ में एक है, लेकिन दूसरे में भी एक है, और यही कारण है कि वे एक साथ फिट नहीं होते ???

+0

पर एक बग भेजना चाहते हैं। मैं स्कैला का उपयोग कर रहा हूं 2.9.3-20120917-121530-db16547873 –

उत्तर

2

में दी गई तो हम करने के लिए देखने के लिए विशेष प्रकार के साथ संगत है स्कैला कंपाइलर, स्रोत हमें समझने में मदद कर सकते हैं कि समस्या क्या है। मैंने कभी स्कैला कंपाइलर में योगदान नहीं दिया है, लेकिन मैंने स्रोतों को बहुत पठनीय पाया है और मैंने पहले ही इसकी जांच की है।

टाइप अनुमान के लिए जिम्मेदार वर्ग scala.tools.nsctypechecker.Infer है जो आप अपनी त्रुटि के एक भाग के लिए स्कैला कंपाइलर स्रोतों को देखकर आसानी से पा सकते हैं। आप बाहर निम्नलिखित टुकड़ा मिल जाएगा:

/** error if arguments not within bounds. */ 
    def checkBounds(pos: Position, pre: Type, owner: Symbol, 
        tparams: List[Symbol], targs: List[Type], prefix: String) = { 
     //@M validate variances & bounds of targs wrt variances & bounds of tparams 
     //@M TODO: better place to check this? 
     //@M TODO: errors for getters & setters are reported separately 
     val kindErrors = checkKindBounds(tparams, targs, pre, owner) 

     if(!kindErrors.isEmpty) { 
     error(pos, 
      prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") + 
      " do not conform to the expected kinds of the type parameters "+ tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." + 
      kindErrors.toList.mkString("\n", ", ", "")) 
     } 

क्यों checkKindBounds(tparams, targs, pre, owner) उन त्रुटियों को देता है तो अब बात समझ रहा है।

: आप नीचे विधि कॉल श्रृंखला जाना, तो आप उस checkKindBounds एक और तरीका

val errors = checkKindBounds0(tparams, targs, pre, owner, true) 

आप समस्या, उच्च kinded प्रकार की सीमा से जाँच से जुड़ा है लाइन 5784 पर, checkKindBoundsHK अंदर देखेंगे फोन देखेंगे

if (!sameLength(hkargs, hkparams)) { 
     if (arg == AnyClass || arg == NothingClass) (Nil, Nil, Nil) // Any and Nothing are kind-overloaded 
     else {error = true; (List((arg, param)), Nil, Nil) } // shortcut: always set error, whether explainTypesOrNot 
     } 

परीक्षा उत्तीर्ण की नहीं है, ऐसा लगता है कि मेरी डीबगर में:

hkargs$1 = {[email protected]}"List()" 
arg$1 = {[email protected]}"class List" 
param$1 = {[email protected]}"type B" 
paramowner$1 = {[email protected]}"method process" 
underHKParams$1 = {[email protected]}"List(type R)" 
withHKArgs$1 = {[email protected]}"List()" 
exceptionResult12 = null 
hkparams$1 = {[email protected]}"List(type R)" 

तो ऐसा लगता है एक उच्च kinded परम, प्रकार आर वहाँ है, लेकिन वहाँ कोई प्रदान करना है की तरह इसके लिए डी मान।

आप वास्तव में checkKindBounds करने के लिए वापस जाओ, तो आप देखते हैं कि स्निपेट के बाद:

val (arityMismatches, varianceMismatches, stricterBounds) = (
     // NOTE: *not* targ.typeSymbol, which normalizes 
     checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO) 
    ) 

arityMismatches एक टपल सूची, बी में शामिल है और अब आप यह भी देख सकते त्रुटि संदेश गलत है: प्रकार तर्कों की

अनुमानित प्रकार (MyFoo, MyFoo, सूची [X]) प्रकार पैरामीटर (प्रकार एफ, प्रकार आर, ग्रुप बी) की उम्मीद प्रकार के अनुरूप नहीं है। सूची [एक्स] के प्रकार पैरामीटर ग्रुप बी की उम्मीद मापदंडों मेल नहीं खाते: कक्षा सूची एक प्रकार पैरामीटर है, लेकिन ग्रुप बी शून्य

है वास्तव में अगर आप निम्न पर लाइन 5859 पर एक ब्रेकपाइंट डाल फोन

checkKindBoundsHK(tparamsHO, targ.typeSymbolDirect, tparam, tparam.owner, tparam.typeParams, tparamsHO) 

आप देख सकते हैं कि

tparam = {[email protected]}"type B" 
targ = {[email protected]}"List[X]" 

निष्कर्ष:

किसी कारण से, जटिल उच्च प्रकार के प्रकार जैसे आपके जैसे व्यवहार से निपटने पर, स्कैला कंपाइलर अनुमान सीमित है। मुझे नहीं पता कि यह कहां से आता है, शायद आप कंपाइलर टीम

0

मुझे केवल स्कैला में प्रकार के अनुमानक की सटीक कार्यप्रणाली की अस्पष्ट समझ है, इसलिए इस विचार को निश्चित उत्तर नहीं मानें।

  1. टाइपिंग में किसी एक प्रकार में एक बार फिर से डालने में समस्याएं होती हैं।

  2. आप कम महत्वपूर्ण चीज़ों की परिभाषा है, जो करने के लिए अनुवाद में एक अस्तित्व प्रकार का उपयोग करें: एक प्रकार वहां मौजूद इस तरह, यकीन नहीं अगर यह MyFoo

संबंधित मुद्दे