00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <assert.h>
00039 #include <stdint.h>
00040 #include <stdlib.h>
00041 #include <dirent.h>
00042 #include <fstream>
00043 #include <iostream>
00044 #include <sstream>
00045 #include <string>
00046 #include <libsherpa/UExcept.hxx>
00047
00048 #include "Options.hxx"
00049 #include "UocInfo.hxx"
00050 #include "AST.hxx"
00051 #include "Type.hxx"
00052 #include "TypeInfer.hxx"
00053 #include "TypeScheme.hxx"
00054 #include "TypeMut.hxx"
00055 #include "Typeclass.hxx"
00056 #include "inter-pass.hxx"
00057 #include "Unify.hxx"
00058 #include "WorkList.hxx"
00059 #include "Unify.hxx"
00060
00061 using namespace boost;
00062 using namespace sherpa;
00063
00064 static bool
00065 typeError(std::ostream& errStream, const LexLoc &errLoc,
00066 shared_ptr<Type> t1, shared_ptr<Type> t2)
00067 {
00068 errStream << errLoc << ": Type Error. "
00069 << "Expected " << t1->asString(GC_NULL)
00070 << ", Obtained " << t2->asString(GC_NULL)
00071 << std::endl;
00072
00073 if (errStream == std::cerr)
00074 errStream << "Real Error!" << std::endl;
00075
00076
00077 return false;
00078 }
00079
00080
00081 bool
00082 unifyPrim(std::ostream& errStream,
00083 shared_ptr<Trail> trail, const LexLoc &errLoc,
00084 shared_ptr<Type> tau, const std::string ptype)
00085 {
00086 bool errFree = true;
00087
00088 shared_ptr<Type> primType = Type::make(Type::LookupTypeTag(ptype));
00089 CHKERR(errFree, unify(errStream, trail, errLoc, primType, tau, UFLG_NO_FLAGS));
00090 return errFree;
00091 }
00092
00093 static bool
00094 Unify(std::ostream& errStream,
00095 shared_ptr<Trail> trail,
00096 const LexLoc &errLoc,
00097 shared_ptr<Type> ft, shared_ptr<Type> st,
00098 UnifyFlags uflags);
00099
00100
00101 static bool
00102 UnifyDecl(std::ostream& errStream,
00103 shared_ptr<Trail> trail,
00104 const LexLoc &errLoc,
00105 shared_ptr<Type> t1, shared_ptr<Type> t2,
00106 UnifyFlags uflags)
00107 {
00108 bool errFree = true;
00109
00110 DEBUG(UNIFY) std::cout << "UnifyDecl "
00111 << t1->asString(Options::debugTvP)
00112 << " ==? "
00113 << t2->asString(Options::debugTvP)
00114 << std::endl;
00115
00116 assert(t1->defAst == t2->defAst);
00117 assert(t1->typeTag != ty_uconv || t1->typeTag != ty_uconr);
00118 assert(t1->typeTag != ty_uvalv || t1->typeTag != ty_uvalr);
00119
00120 if (t1->typeArgs.size() != t2->typeArgs.size())
00121 return typeError(errStream, errLoc, t1, t2);
00122
00123 for (size_t i=0; i<t1->typeArgs.size(); i++)
00124 CHKERR(errFree, Unify(errStream, trail, errLoc, t1->TypeArg(i),
00125 t2->TypeArg(i), uflags));
00126
00127 return errFree;
00128 }
00129
00130
00131 static bool
00132 UnifyStructUnion(std::ostream& errStream,
00133 shared_ptr<Trail> trail,
00134 const LexLoc &errLoc,
00135 shared_ptr<Type> t1, shared_ptr<Type> t2,
00136 UnifyFlags uflags)
00137 {
00138 bool errFree = true;
00139
00140 DEBUG(UNIFY) std::cout << "UnifyStructUnion "
00141 << t1->asString(Options::debugTvP)
00142 << " ==? "
00143 << t2->asString(Options::debugTvP)
00144 << std::endl;
00145
00146 if (t1->isULeg() || t2->isULeg()) {
00147 if (t1->myContainer != t2->myContainer)
00148 return typeError(errStream, errLoc, t1, t2);
00149 }
00150 else {
00151 if (t1->defAst != t2->defAst)
00152 return typeError(errStream, errLoc, t1, t2);
00153
00154 if (t1->components.size() == 0 || t2->components.size() == 0)
00155 return UnifyDecl(errStream, trail, errLoc, t1, t2, uflags);
00156 }
00157
00158 size_t n = trail->snapshot();
00159 trail->link(t1, t2);
00160
00161 assert(t1->typeArgs.size() == t2->typeArgs.size());
00162 for (size_t i=0; i<t1->typeArgs.size(); i++)
00163 CHKERR(errFree, Unify(errStream, trail, errLoc, t1->TypeArg(i),
00164 t2->TypeArg(i), uflags));
00165
00166 if (!errFree)
00167 trail->rollBack(n);
00168
00169 return errFree;
00170 }
00171
00172 #ifdef DEAD_CODE
00173
00174 static bool
00175 UnifyMbCt(std::ostream& errStream, shared_ptr<Trail> trail,
00176 shared_ptr<Type> mb, shared_ptr<Type> ct)
00177 {
00178 mb = mb->getType();
00179 ct = ct->getType();
00180 shared_ptr<Type> var = mb->Var()->getType();
00181 shared_ptr<Type> core = mb->Core()->getType();
00182
00183 trail->subst(var, ct);
00184
00185 return true;
00186 }
00187 #endif
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 static bool
00199 UnifyFnArgs(std::ostream& errStream, shared_ptr<Trail> trail,
00200 const LexLoc &errLoc,
00201 shared_ptr<Type> errt1, shared_ptr<Type> errt2,
00202 shared_ptr<Type> t1, shared_ptr<Type> t2,
00203 UnifyFlags uflags)
00204 {
00205 bool errFree = true;
00206 t1 = t1->getType();
00207 t2 = t2->getType();
00208 assert(t1->typeTag == ty_fnarg);
00209 assert(t2->typeTag == ty_fnarg);
00210
00211 if (t1->components.size() != t2->components.size())
00212 return typeError(errStream, errLoc, errt1, errt2);
00213
00214 for (size_t i=0; i< t1->components.size(); i++) {
00215
00216 if ((t1->CompFlags(i) & COMP_MAYBE_BYREF) &&
00217 ((t2->CompFlags(i) & COMP_MAYBE_BYREF) == 0)) {
00218 t1->CompFlags(i) &= ~COMP_MAYBE_BYREF;
00219 t1->CompFlags(i) |= t2->CompFlags(i) & COMP_BYREF;
00220 }
00221 else if ((t2->CompFlags(i) & COMP_MAYBE_BYREF) &&
00222 ((t1->CompFlags(i) & COMP_MAYBE_BYREF) == 0)) {
00223 t2->CompFlags(i) &= ~COMP_MAYBE_BYREF;
00224 t2->CompFlags(i) |= t1->CompFlags(i) & COMP_BYREF;
00225 }
00226 else if (t1->CompFlags(i) != t2->CompFlags(i)) {
00227 errFree = typeError(errStream, errLoc, errt1, errt2);
00228 break;
00229 }
00230
00231 CHKERR(errFree, Unify(errStream, trail, errLoc,
00232 t1->CompType(i),
00233 t2->CompType(i), uflags));
00234 }
00235
00236 return errFree;
00237 }
00238
00239
00240
00241 static bool
00242 PropagateMutability(std::ostream& errStream,
00243 shared_ptr<Trail> trail,
00244 const LexLoc &errLoc,
00245 shared_ptr<Type> t)
00246 {
00247 bool errFree = true;
00248 CHKERR(errFree, t->propagateMutability(trail));
00249 if(!errFree)
00250 errStream << errLoc << ": Unsound Mutable type: "
00251 << t->asString()
00252 << std::endl;
00253
00254
00255
00256
00257 return errFree;
00258 }
00259
00260 static bool
00261 Unify(std::ostream& errStream,
00262 shared_ptr<Trail> trail,
00263 const LexLoc &errLoc,
00264 shared_ptr<Type> ft, shared_ptr<Type> st,
00265 UnifyFlags uflags)
00266 {
00267 shared_ptr<Type> t1 = ft->getType();
00268 shared_ptr<Type> t2 = st->getType();
00269 bool errFree = true;
00270
00271 DEBUG(UNIFY) std::cerr << "Unifier: "
00272 << ft->asString(Options::debugTvP)
00273 << " ==? "
00274 << st->asString(Options::debugTvP)
00275 << std::endl;
00276
00277 if (t1->uniqueID == t2->uniqueID)
00278 return true;
00279
00280 bool unifyingSameType = (t1->typeTag == t2->typeTag);
00281
00282 switch(unifyingSameType) {
00283 case false:
00284 {
00285 if (t1->isUType(false) && t2->isUType(false) &&
00286 t1->isRefType() == t2->isRefType()) {
00287 CHKERR(errFree, UnifyStructUnion(errStream, trail, errLoc,
00288 t1, t2, uflags));
00289 break;
00290 }
00291
00292 if (uflags & UFLG_UNIFY_STRICT) {
00293 errFree = typeError(errStream, errLoc, t1, t2);
00294 break;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 if(t1->isTvar() || t2->isTvar()) {
00305 shared_ptr<Type> var = t1->isTvar() ? t1 : t2;
00306 shared_ptr<Type> other = t1->isTvar() ? t2 : t1;
00307
00308
00309
00310
00311
00312
00313
00314
00315 if(!var->isUnifiableVar()) {
00316 errStream << errLoc << " Rigid variable "
00317 << var->asString() << " cannot be unified with "
00318 << other->asString() << std::endl;
00319 errFree = false;
00320
00321 if (errStream == std::cerr)
00322 errStream << "Real Error!" << std::endl;
00323
00324
00325 break;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 if(!other->boundInType(var)) {
00344 trail->subst(var, other);
00345 break;
00346 }
00347
00348 }
00349
00350
00351
00352
00353 if (t1->isMbFull() || t2->isMbFull()) {
00354 shared_ptr<Type> mb = t1->isMbFull() ? t1 : t2;
00355 shared_ptr<Type> other = t1->isMbFull() ? t2 : t1;
00356
00357 if(!mb->isUnifiableVar()) {
00358 errStream << errLoc << "Rigid type "
00359 << mb->asString() << " cannot be unified with "
00360 << other->asString() << std::endl;
00361 errFree = false;
00362 break;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 if(t2->isMutable() && t2->Base()->isTvar()) {
00387 CHKERR(errFree, Unify(errStream, trail, errLoc, mb->Var(),
00388 Type::make(ty_mutable, newTvar()), uflags));
00389
00390 trail->link(other, mb);
00391 }
00392 else {
00393 CHKERR(errFree, Unify(errStream, trail, errLoc,
00394 mb->minMutConstless(),
00395 other->minMutConstless(), uflags));
00396
00397 CHKERR(errFree, Unify(errStream, trail, errLoc,
00398 mb->Var(), other, uflags));
00399 }
00400
00401
00402 if(errFree && (other->isMutable() || mb->Var()->isMutable()))
00403 CHKERR(errFree, PropagateMutability(errStream, trail,
00404 errLoc, mb));
00405
00406 break;
00407 }
00408
00409 if (t1->isMbTop() || t2->isMbTop()) {
00410 shared_ptr<Type> mb = t1->isMbTop() ? t1 : t2;
00411 shared_ptr<Type> other = t1->isMbTop() ? t2 : t1;
00412
00413 if(!mb->isUnifiableVar()) {
00414 errStream << errLoc << "Rigid type "
00415 << mb->asString() << " cannot be unified with "
00416 << other->asString() << std::endl;
00417 errFree = false;
00418 break;
00419 }
00420
00421 CHKERR(errFree, Unify(errStream, trail, errLoc,
00422 mb->minimizeTopMutability(),
00423 other->minimizeTopMutability(), uflags));
00424
00425 CHKERR(errFree, Unify(errStream, trail, errLoc,
00426 mb->Var(), other, uflags));
00427 break;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 if(t1->isMutType() || t2->isMutType()) {
00441 shared_ptr<Type> mut = t1->isMutType() ? t1 : t2;
00442 shared_ptr<Type> other = t1->isMutType() ? t2 : t1;
00443
00444 assert(!other->isMutType() &&
00445 !other->isMaybe());
00446
00447 if(other->typeTag == ty_array || other->typeTag == ty_structv) {
00448 CHKERR(errFree, Unify(errStream, trail, errLoc,
00449 mut, Mutable(other), uflags));
00450 break;
00451 }
00452 }
00453
00454
00455
00456
00457 if(t1->isConst() || t2->isConst()) {
00458 shared_ptr<Type> constType = t1->isConst() ? t1 : t2;
00459 shared_ptr<Type> other = t1->isConst() ? t2 : t1;
00460
00461 if(other->isEffectivelyConst()) {
00462 CHKERR(errFree,
00463 Unify(errStream, trail, errLoc,
00464 constType->Base()->minMutConstless(),
00465 other->minMutConstless(), uflags));
00466 break;
00467 }
00468 }
00469
00470 errFree = typeError(errStream, errLoc, t1, t2);
00471 break;
00472 }
00473 case true:
00474 {
00475 switch(t1->typeTag) {
00476 case ty_unit:
00477 case ty_bool:
00478 case ty_char:
00479 case ty_string:
00480 case ty_int8:
00481 case ty_int16:
00482 case ty_int32:
00483 case ty_int64:
00484 case ty_uint8:
00485 case ty_uint16:
00486 case ty_uint32:
00487 case ty_uint64:
00488 case ty_word:
00489 case ty_float:
00490 case ty_double:
00491 case ty_quad:
00492 break;
00493
00494 case ty_tvar:
00495 {
00496 if (uflags & UFLG_UNIFY_STRICT_TVAR) {
00497 errFree = typeError(errStream, errLoc, t1, t2);
00498 break;
00499 }
00500
00501 if ((t1->flags & TY_RIGID) && (t2->flags & TY_RIGID) &&
00502 ((uflags & UFLG_UN_IGN_RIGIDITY) == 0)) {
00503 errFree = typeError(errStream, errLoc, t1, t2);
00504 break;
00505 }
00506
00507
00508 if (t1->flags & TY_RIGID)
00509 trail->subst(t2, t1);
00510 else
00511 trail->subst(t1, t2);
00512
00513 break;
00514 }
00515
00516 case ty_dummy:
00517 {
00518 break;
00519 }
00520
00521 #ifdef KEEP_BF
00522 case ty_bitfield:
00523 {
00524 CHKERR(errFree, Unify(errStream, trail, errLoc,
00525 t1->CompType(0),
00526 t2->CompType(0), uflags));
00527
00528 if (!errFree)
00529 break;
00530
00531 if (t1->Isize == t2->Isize)
00532 break;
00533
00534 errStream << errLoc << ": "
00535 << "Incompatibility in integer types "
00536 << t1->asString() << " and " << t2->asString()
00537 << "." << std::endl;
00538
00539 errFree = false;
00540 break;
00541 }
00542 #endif
00543
00544 case ty_tyfn:
00545 case ty_fn:
00546 case ty_method:
00547 {
00548 shared_ptr<Type> t1Args = t1->Args();
00549 shared_ptr<Type> t2Args = t2->Args();
00550 CHKERR(errFree, UnifyFnArgs(errStream, trail, errLoc,
00551 t1, t2, t1Args, t2Args, uflags));
00552
00553 CHKERR(errFree,
00554 Unify(errStream, trail, errLoc, t1->Ret(),
00555 t2->Ret(), uflags));
00556 break;
00557 }
00558
00559 case ty_fnarg:
00560 {
00561 CHKERR(errFree, UnifyFnArgs(errStream, trail, errLoc,
00562 t1, t2, t1, t2, uflags));
00563 break;
00564 }
00565
00566 case ty_structv:
00567 case ty_structr:
00568 case ty_unionv:
00569 case ty_unionr:
00570 case ty_uconr:
00571 case ty_uconv:
00572 case ty_uvalr:
00573 case ty_uvalv:
00574 {
00575 CHKERR(errFree,
00576 UnifyStructUnion(errStream, trail, errLoc, t1, t2, uflags));
00577 break;
00578 }
00579
00580 case ty_letGather:
00581 {
00582 if (t1->components.size() != t2->components.size()) {
00583 errFree = typeError(errStream, errLoc, t1, t2);
00584 break;
00585 }
00586
00587 for (size_t i=0; i<t1->components.size(); i++)
00588 CHKERR(errFree,
00589 Unify(errStream, trail, errLoc, t1->CompType(i),
00590 t2->CompType(i), uflags));
00591
00592 break;
00593 }
00594
00595 case ty_array:
00596 {
00597 CHKERR(errFree,
00598 Unify(errStream, trail, errLoc, t1->Base(),
00599 t2->Base(), uflags));
00600
00601
00602
00603 if (t1->arrLen->len == t2->arrLen->len)
00604 break;
00605
00606
00607 if (t1->arrLen->len == 0) {
00608 t1->arrLen->len = t2->arrLen->len;
00609 break;
00610 }
00611 else if (t2->arrLen->len == 0) {
00612 t2->arrLen->len = t1->arrLen->len;
00613 break;
00614 }
00615 else {
00616 errStream << errLoc
00617 << ": Array lengths do not match. "
00618 << t1->arrLen->len
00619 << " vs "
00620 << t2->arrLen->len
00621 << std::endl;
00622 errFree = false;
00623 }
00624
00625 break;
00626 }
00627
00628
00629
00630
00631 case ty_vector:
00632 {
00633 CHKERR(errFree,
00634 Unify(errStream, trail, errLoc, t1->Base(),
00635 t2->Base(), uflags));
00636 break;
00637 }
00638
00639 case ty_mbTop:
00640 {
00641 CHKERR(errFree,
00642 Unify(errStream, trail, errLoc,
00643 t1->Core()->minimizeTopMutability(),
00644 t2->Core()->minimizeTopMutability(),
00645 uflags));
00646
00647 if (!errFree)
00648 break;
00649
00650 CHKERR(errFree, Unify(errStream, trail, errLoc,
00651 t1->Var(), t2->Var(), uflags));
00652 break;
00653 }
00654
00655 case ty_mbFull:
00656 {
00657 CHKERR(errFree,
00658 Unify(errStream, trail, errLoc,
00659 t1->Core()->minMutConstless(),
00660 t2->Core()->minMutConstless(),
00661 uflags));
00662
00663 if (!errFree)
00664 break;
00665
00666 shared_ptr<Type> var1 = t1->Var()->getType();
00667 shared_ptr<Type> var2 = t2->Var()->getType();
00668
00669 if(var1->isMutable() && var2->isMutable())
00670 CHKERR(errFree, Unify(errStream, trail, errLoc,
00671 var1->Base(), var2->Base(), uflags));
00672 else
00673 CHKERR(errFree, Unify(errStream, trail, errLoc,
00674 var1, var2, uflags));
00675
00676 if(errFree && t1->Var()->isMutable())
00677 CHKERR(errFree, PropagateMutability(errStream, trail,
00678 errLoc, t1));
00679
00680 break;
00681 }
00682
00683 case ty_mutable:
00684 {
00685 CHKERR(errFree,
00686 Unify(errStream, trail, errLoc, t1->Base(),
00687 t2->Base(), uflags));
00688
00689 if(!errFree)
00690 break;
00691
00692 CHKERR(errFree, PropagateMutability(errStream, trail,
00693 errLoc, t1));
00694 break;
00695 }
00696
00697 case ty_const:
00698 {
00699 CHKERR(errFree,
00700 Unify(errStream, trail, errLoc,
00701 t1->Base()->minMutConstless(),
00702 t2->Base()->minMutConstless(), uflags));
00703 break;
00704 }
00705
00706 case ty_ref:
00707 case ty_byref:
00708 case ty_array_ref:
00709 {
00710 CHKERR(errFree,
00711 Unify(errStream, trail, errLoc, t1->Base(),
00712 t2->Base(), uflags));
00713 break;
00714 }
00715
00716 case ty_exn:
00717 {
00718
00719 break;
00720 }
00721
00722 case ty_typeclass:
00723 {
00724 if (t1->defAst != t2->defAst) {
00725 errFree = typeError(errStream, errLoc, t1, t2);
00726 break;
00727 }
00728
00729 if (t1->typeArgs.size() != t2->typeArgs.size()) {
00730 errFree = typeError(errStream, errLoc, t1, t2);
00731 break;
00732 }
00733
00734 for (size_t i = 0; i < t1->typeArgs.size(); i++) {
00735
00736 CHKERR(errFree, Unify(errStream, trail, errLoc,
00737 t1->TypeArg(i), t2->TypeArg(i),
00738 uflags));
00739 }
00740
00741 break;
00742 }
00743
00744
00745
00746 case ty_pcst:
00747 {
00748 assert(t1->components.size() == t2->components.size());
00749 for (size_t i=0; i < t1->components.size(); i++)
00750 CHKERR(errFree,
00751 Unify(errStream, trail, errLoc, t1->CompType(i),
00752 t2->CompType(i), uflags));
00753 break;
00754 }
00755
00756 case ty_field:
00757 {
00758 if(t1->litValue.s != t2->litValue.s)
00759 errFree = typeError(errStream, errLoc, t1, t2);
00760 break;
00761 }
00762
00763 case ty_kvar:
00764 case ty_kfix:
00765 {
00766
00767
00768 if (t1->uniqueID != t2->uniqueID)
00769 errFree = typeError(errStream, errLoc, t1, t2);
00770 break;
00771 }
00772 }
00773 }
00774 }
00775
00776 DEBUG(UNF_RES) errStream << "\t Result: "
00777 << ft->asString(Options::debugTvP)
00778 << " == "
00779 << st->asString(Options::debugTvP)
00780 << "{" << (errFree?"OK":"ERR") << "}"
00781 << std::endl;
00782
00783 return errFree;
00784 }
00785
00786 bool
00787 acyclic(std::ostream& errStream,
00788 const LexLoc &errLoc,
00789 shared_ptr<Type> typ,
00790 WorkList<shared_ptr<Type> >& worklist,
00791 DoneList<shared_ptr<Type> >& donelist,
00792 bool inref=false)
00793 {
00794 assert(typ);
00795
00796 shared_ptr<Type> t = typ->getType();
00797 bool errFree = true;
00798
00799
00800
00801
00802 if (donelist.contains(t))
00803 return true;
00804
00805 if (worklist.contains(t)) {
00806
00807 if (t->typeTag == ty_structr ||
00808 t->typeTag == ty_unionr ||
00809 t->typeTag == ty_uconr ||
00810 t->typeTag == ty_uvalr)
00811 return true;
00812
00813 if (inref)
00814 return true;
00815
00816 std::cerr << errLoc << ": "
00817 << "Cyclic Type Definitions among the following "
00818 << worklist.size() << " types:" << std::endl;
00819
00820
00821
00822 std::cerr << t->asString(GC_NULL, PO_NO_TRAVERSE)
00823 << std::endl;
00824 for (WorkList<shared_ptr<Type> >::iterator itr = worklist.begin();
00825 itr != worklist.end(); ++itr)
00826 std::cerr << (*itr)->asString(GC_NULL, PO_NO_TRAVERSE)
00827 << std::endl;
00828 fatal();
00829 return false;
00830 }
00831
00832 assert(!worklist.contains(t));
00833 worklist.insert(t);
00834
00835 for (size_t i=0; i < t->components.size(); i++)
00836 CHKERR(errFree, acyclic(errStream, errLoc, t->CompType(i),
00837 worklist, donelist,
00838 (inref || t->typeTag == ty_ref)));
00839
00840
00841
00842
00843
00844
00845
00846 worklist.erase(t);
00847 if (errFree)
00848 donelist.insert(t);
00849
00850
00851
00852
00853 return errFree;
00854 }
00855
00856 bool
00857 unify(std::ostream& errStream,
00858 shared_ptr<Trail> trail,
00859 const LexLoc &errLoc,
00860 shared_ptr<Type> ft, shared_ptr<Type> st,
00861 UnifyFlags uflags)
00862 {
00863 bool errFree = true;
00864
00865 CHKERR(errFree, Unify(errStream, trail, errLoc, ft, st, uflags));
00866
00867 WorkList<shared_ptr<Type> > worklist;
00868 DoneList<shared_ptr<Type> > donelist;
00869 CHKERR(errFree, acyclic(errStream, errLoc, ft, worklist, donelist));
00870 if(errFree)
00871 ft->normalize(trail);
00872
00873 return errFree;
00874 }
00875