@@ -1944,12 +1944,22 @@ class Typer extends Namer
19441944 val quotedPt = if (exprPt.exists) exprPt.argTypesHi.head else defn.AnyType
19451945 val quoted1 = typedExpr(quoted, quotedPt)(quoteContext.addMode(Mode .QuotedPattern ))
19461946 val (shape, splices) = splitQuotePattern(quoted1)
1947+ val typeBindings = splices.collect {
1948+ case t if t.tpe.derivesFrom(defn.QuotedTypeClass ) =>
1949+ t.tpe.widen.argTypesHi.head.typeSymbol
1950+ }
1951+ val inQuoteTypeBinding = typeBindings.map { sym =>
1952+ ctx.newSymbol(sym.owner, (sym.name + " $$$" ).toTypeName, // TODO remove $$$, just there for debugging
1953+ EmptyFlags , sym.info, coord = sym.coord)
1954+ }
1955+ val shape2 =
1956+ seq(inQuoteTypeBinding.map(TypeDef ), shape.subst(typeBindings, inQuoteTypeBinding))
19471957 val patType = defn.tupleType(splices.tpes.map(_.widen))
19481958 val splicePat = typed(untpd.Tuple (splices.map(untpd.TypedSplice (_))).withSpan(quoted.span), patType)
19491959 UnApply (
19501960 fun = ref(defn.InternalQuotedMatcher_unapplyR ).appliedToType(patType),
19511961 implicits =
1952- ref(defn.InternalQuoted_exprQuoteR ).appliedToType(shape.tpe).appliedTo(shape ) ::
1962+ ref(defn.InternalQuoted_exprQuoteR ).appliedToType(shape.tpe).appliedTo(shape2 ) ::
19531963 implicitArgTree(defn.TastyReflectionType , tree.span) :: Nil ,
19541964 patterns = splicePat :: Nil ,
19551965 proto = pt)
@@ -2002,8 +2012,11 @@ class Typer extends Namer
20022012 }
20032013
20042014 /** A hole the shape pattern of a quoted.Matcher.unapply, representing a splice */
2005- def patternHole (splice : Tree )(implicit ctx : Context ): Tree =
2006- ref(defn.InternalQuoted_patternHoleR ).appliedToType(splice.tpe).withSpan(splice.span)
2015+ def patternHole (splice : Tree )(implicit ctx : Context ): Tree = {
2016+ val Splice (pat) = splice
2017+ if (pat.tpe.derivesFrom(defn.QuotedTypeClass )) AppliedTypeTree (ref(defn.InternalQuoted_patternTypeHole ), TypeTree (splice.tpe) :: Nil ).withSpan(splice.span)
2018+ else ref(defn.InternalQuoted_patternHoleR ).appliedToType(splice.tpe).withSpan(splice.span)
2019+ }
20072020
20082021 /** Translate `${ t: Expr[T] }` into expression `t.splice` while tracking the quotation level in the context */
20092022 def typedSplice (tree : untpd.Splice , pt : Type )(implicit ctx : Context ): Tree = track(" typedSplice" ) {
@@ -2042,9 +2055,34 @@ class Typer extends Namer
20422055
20432056 /** Translate ${ t: Type[T] }` into type `t.splice` while tracking the quotation level in the context */
20442057 def typedTypSplice (tree : untpd.TypSplice , pt : Type )(implicit ctx : Context ): Tree = track(" typedTypSplice" ) {
2058+ // TODO factor out comon code with typedSplice
20452059 ctx.compilationUnit.needsStaging = true
20462060 checkSpliceOutsideQuote(tree)
2047- typedSelect(untpd.Select (tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span)
2061+ tree.expr match {
2062+ case untpd.Quote (innerExpr) =>
2063+ ctx.warning(" Canceled quote directly inside a splice. ${ '{ XYZ } } is equivalent to XYZ." , tree.sourcePos)
2064+ typed(innerExpr, pt)
2065+ case expr =>
2066+ if (ctx.mode.is(Mode .QuotedPattern ) && level == 1 ) {
2067+ if (isFullyDefined(pt, ForceDegree .all)) {
2068+ ctx.error(i " Type must be fully defined. \n Consider annotating the splice using a type ascription: \n ( $tree: XYZ). " , tree.expr.sourcePos)
2069+ tree.withType(UnspecifiedErrorType )
2070+ } else {
2071+ val bindingBounds = TypeBounds .apply(defn.NothingType , defn.AnyType )
2072+ val sym = ctx.newPatternBoundSymbol(" ttt" .toTypeName, bindingBounds, expr.span)
2073+ val bind = Bind (sym, untpd.Ident (nme.WILDCARD ).withType(bindingBounds)).withSpan(expr.span)
2074+
2075+ def spliceOwner (ctx : Context ): Symbol =
2076+ if (ctx.mode.is(Mode .QuotedPattern )) spliceOwner(ctx.outer) else ctx.owner
2077+ val pat = typedPattern(tree.expr, defn.QuotedTypeType .appliedTo(sym.typeRef))(
2078+ spliceContext.retractMode(Mode .QuotedPattern ).withOwner(spliceOwner(ctx)))
2079+ Splice (Typed (pat, AppliedTypeTree (TypeTree (defn.QuotedTypeType ), bind :: Nil )))
2080+ }
2081+
2082+ } else {
2083+ typedSelect(untpd.Select (tree.expr, tpnme.splice), pt)(spliceContext).withSpan(tree.span)
2084+ }
2085+ }
20482086 }
20492087
20502088 private def checkSpliceOutsideQuote (tree : untpd.Tree )(implicit ctx : Context ): Unit = {
0 commit comments