|
| 1 | +package dotty.tools |
| 2 | +package dotc |
| 3 | +package transform |
| 4 | + |
| 5 | +import core.* |
| 6 | +import Symbols.*, Contexts.*, Types.*, ContextOps.*, Decorators.*, SymDenotations.* |
| 7 | +import Flags.* |
| 8 | +import Phases.Phase |
| 9 | +import DenotTransformers.IdentityDenotTransformer |
| 10 | +import ast.* |
| 11 | +import typer.ProtoTypes.* |
| 12 | +import config.Printers.recheckr |
| 13 | + |
| 14 | +class Recheck extends Phase, IdentityDenotTransformer: |
| 15 | + thisPhase => |
| 16 | + |
| 17 | + import ast.tpd.* |
| 18 | + |
| 19 | + def preRecheckPhase = this.prev.asInstanceOf[PreRecheck] |
| 20 | + |
| 21 | + def run(using Context): Unit = |
| 22 | + val refiner = newRechecker() |
| 23 | + val unit = ctx.compilationUnit |
| 24 | + recheckr.println(i"recheck types of $unit") |
| 25 | + newRechecker().check() |
| 26 | + |
| 27 | + def newRechecker()(using Context): Rechecker = Rechecker(ctx) |
| 28 | + |
| 29 | + class Rechecker(ictx: Context): |
| 30 | + val ta = ictx.typeAssigner |
| 31 | + |
| 32 | + extension (sym: Symbol) def updateInfo(newInfo: Type)(using Context): Unit = |
| 33 | + sym.copySymDenotation().installAfter(thisPhase) // reset |
| 34 | + sym.copySymDenotation( |
| 35 | + info = newInfo, |
| 36 | + initFlags = |
| 37 | + if newInfo.isInstanceOf[LazyType] then sym.flags &~ Touched |
| 38 | + else sym.flags |
| 39 | + ).installAfter(preRecheckPhase) |
| 40 | + |
| 41 | + def recheckIdent(tree: Ident)(using Context): Type = |
| 42 | + ta.ensureAccessible(tree.symbol.namedType, superAccess = false, tree.srcPos) |
| 43 | + |
| 44 | + def recheckSelect(tree: Select, pt: Type)(using Context): Type = tree match |
| 45 | + case Select(qual, name) => |
| 46 | + val superAccess = qual.isInstanceOf[Super] |
| 47 | + val qualType = recheck(qual, WildcardType) |
| 48 | + val pre = ta.maybeSkolemizePrefix(qualType, name) |
| 49 | + val mbr = qualType.findMember(name, pre) |
| 50 | + assert(ta.reallyExists(mbr)) |
| 51 | + val rawType = qualType.select(name, mbr) |
| 52 | + ta.accessibleType(rawType, superAccess) |
| 53 | + |
| 54 | + def recheckBind(tree: Bind, pt: Type)(using Context): Type = tree match |
| 55 | + case Bind(name, body) => |
| 56 | + val bodyType = recheck(body, pt) |
| 57 | + tree.symbol.updateInfo(pt & bodyType) |
| 58 | + tree.tpe |
| 59 | + |
| 60 | + def recheckLabeled(tree: Labeled)(using Context): Type = tree match |
| 61 | + case Labeled(bind, expr) => |
| 62 | + recheck(bind, WildcardType) |
| 63 | + val info = bind.symbol.info |
| 64 | + recheck(expr, info) |
| 65 | + info |
| 66 | + |
| 67 | + def recheckValDef(tree: ValDef, sym: Symbol)(using Context): Type = ??? |
| 68 | + def recheckDefDef(tree: DefDef, sym: Symbol)(using Context): Type = ??? |
| 69 | + def recheckTypeDef(tree: TypeDef, sym: Symbol)(using Context): Type = ??? |
| 70 | + def recheckClassDef(tree: TypeDef, sym: ClassSymbol)(using Context): Type = ??? |
| 71 | + |
| 72 | + def recheckApply(tree: Apply, pt: Type)(using Context): Type = ??? |
| 73 | + def recheckThis(tree: This)(using Context): Type = ??? |
| 74 | + def recheckTypeApply(tree: TypeApply, pt: Type)(using Context): Type = ??? |
| 75 | + def recheckLiteral(tree: Literal)(using Context): Type = ??? |
| 76 | + def recheckNew(tree: New, pt: Type)(using Context): Type = ??? |
| 77 | + def recheckTyped(tree: Typed, pt: Type)(using Context): Type = ??? |
| 78 | + def recheckAssign(tree: Assign, pt: Type)(using Context): Type = ??? |
| 79 | + def recheckBlock(tree: Block, pt: Type)(using Context): Type = ??? |
| 80 | + def recheckIf(tree: If, pt: Type)(using Context): Type = ??? |
| 81 | + def recheckClosure(tree: Closure, pt: Type)(using Context): Type = ??? |
| 82 | + def recheckMatch(tree: Match, pt: Type)(using Context): Type = ??? |
| 83 | + def recheckReturn(tree: Return)(using Context): Type = ??? |
| 84 | + def recheckWhileDo(tree: WhileDo)(using Context): Type = ??? |
| 85 | + def recheckTry(tree: Try, pt: Type)(using Context): Type = ??? |
| 86 | + def recheckSuper(tree: Super, pt: Type)(using Context): Type = ??? |
| 87 | + def recheckSeqLiteral(tree: SeqLiteral, pt: Type)(using Context): Type = ??? |
| 88 | + def recheckInlined(tree: Inlined, pt: Type)(using Context): Type = ??? |
| 89 | + def recheckTypeTree(tree: TypeTree, pt: Type)(using Context): Type = ??? |
| 90 | + def recheckPackageDef(tree: PackageDef)(using Context): Type = ??? |
| 91 | + |
| 92 | + /** Typecheck tree without adapting it, returning a recheck tree. |
| 93 | + * @param initTree the unrecheck tree |
| 94 | + * @param pt the expected result type |
| 95 | + * @param locked the set of type variables of the current typer state that cannot be interpolated |
| 96 | + * at the present time |
| 97 | + */ |
| 98 | + def recheck(tree: Tree, pt: Type)(using Context): Type = |
| 99 | + |
| 100 | + def recheckNamed(tree: NameTree, pt: Type)(using Context): Type = |
| 101 | + val sym = tree.symbol |
| 102 | + tree match |
| 103 | + case tree: Ident => recheckIdent(tree) |
| 104 | + case tree: Select => recheckSelect(tree, pt) |
| 105 | + case tree: Bind => recheckBind(tree, pt) |
| 106 | + case tree: ValDef => |
| 107 | + if tree.isEmpty then NoType |
| 108 | + else recheckValDef(tree, sym)(using ctx.localContext(tree, sym)) |
| 109 | + case tree: DefDef => |
| 110 | + recheckDefDef(tree, sym)(using ctx.localContext(tree, sym)) |
| 111 | + case tree: TypeDef => |
| 112 | + if tree.isClassDef then |
| 113 | + recheckClassDef(tree, sym.asClass)(using ctx.localContext(tree, sym)) |
| 114 | + else |
| 115 | + recheckTypeDef(tree, sym)(using ctx.localContext(tree, sym).setNewScope) |
| 116 | + case tree: Labeled => recheckLabeled(tree) |
| 117 | + |
| 118 | + def recheckUnnamed(tree: Tree, pt: Type): Type = tree match |
| 119 | + case tree: Apply => recheckApply(tree, pt) |
| 120 | + case tree: This => recheckThis(tree) |
| 121 | + case tree: TypeApply => recheckTypeApply(tree, pt) |
| 122 | + case tree: Literal => recheckLiteral(tree) |
| 123 | + case tree: New => recheckNew(tree, pt) |
| 124 | + case tree: Typed => recheckTyped(tree, pt) |
| 125 | + case tree: Assign => recheckAssign(tree, pt) |
| 126 | + case tree: Block => recheckBlock(tree, pt)(using ctx.fresh.setNewScope) |
| 127 | + case tree: If => recheckIf(tree, pt) |
| 128 | + case tree: Closure => recheckClosure(tree, pt) |
| 129 | + case tree: Match => recheckMatch(tree, pt) |
| 130 | + case tree: Return => recheckReturn(tree) |
| 131 | + case tree: WhileDo => recheckWhileDo(tree) |
| 132 | + case tree: Try => recheckTry(tree, pt) |
| 133 | + case tree: Super => recheckSuper(tree, pt) |
| 134 | + case tree: SeqLiteral => recheckSeqLiteral(tree, pt) |
| 135 | + case tree: Inlined => recheckInlined(tree, pt) |
| 136 | + case tree: TypeTree => recheckTypeTree(tree, pt) |
| 137 | + case tree: PackageDef => recheckPackageDef(tree) |
| 138 | + |
| 139 | + try |
| 140 | + val result = tree match |
| 141 | + case tree: NameTree => recheckNamed(tree, pt) |
| 142 | + case tree => recheckUnnamed(tree, pt) |
| 143 | + checkConforms(result, pt, tree) |
| 144 | + result |
| 145 | + catch case ex: Exception => |
| 146 | + println(i"error while rechecking $tree") |
| 147 | + throw ex |
| 148 | + end recheck |
| 149 | + |
| 150 | + def checkConforms(tpe: Type, pt: Type, tree: Tree)(using Context): Unit = tree match |
| 151 | + case tree: DefTree => |
| 152 | + case _ => ??? |
| 153 | + |
| 154 | + def check()(using Context): Unit = |
| 155 | + val unit = ictx.compilationUnit |
| 156 | + recheck(unit.tpdTree, WildcardType) |
| 157 | + |
| 158 | + end Rechecker |
| 159 | +end Recheck |
0 commit comments