@@ -413,36 +413,67 @@ object Inlines:
413413 return Intrinsics .codeOf(arg, call.srcPos)
414414 case _ =>
415415
416- // Special handling of `constValue[T]`, `constValueOpt[T], and summonInline[T]`
416+ // Special handling of `constValue[T]`, `constValueOpt[T]`, `constValueTuple[T]`, ` summonInline[T]` and `summonAll [T]`
417417 if callTypeArgs.length == 1 then
418- if (inlinedMethod == defn.Compiletime_constValue ) {
419- val constVal = tryConstValue
418+
419+ def constValueOrError (tpe : Type ): Tree =
420+ val constVal = tryConstValue(tpe)
420421 if constVal.isEmpty then
421- val msg = NotConstant (" cannot take constValue" , callTypeArgs.head. tpe)
422- return ref(defn.Predef_undefined ).withSpan(call .span).withType(ErrorType (msg))
422+ val msg = NotConstant (" cannot take constValue" , tpe)
423+ ref(defn.Predef_undefined ).withSpan(callTypeArgs.head .span).withType(ErrorType (msg))
423424 else
424- return constVal
425+ constVal
426+
427+ def searchImplicitOrError (tpe : Type ): Tree =
428+ val evTyper = new Typer (ctx.nestingLevel + 1 )
429+ val evCtx = ctx.fresh.setTyper(evTyper)
430+ inContext(evCtx) {
431+ val evidence = evTyper.inferImplicitArg(tpe, callTypeArgs.head.span)
432+ evidence.tpe match
433+ case fail : Implicits .SearchFailureType =>
434+ errorTree(call, evTyper.missingArgMsg(evidence, tpe, " " ))
435+ case _ =>
436+ evidence
437+ }
438+
439+ def unrollTupleTypes (tpe : Type ): Option [List [Type ]] = tpe.dealias match
440+ case AppliedType (tycon, args) if defn.isTupleClass(tycon.typeSymbol) =>
441+ Some (args)
442+ case AppliedType (tycon, head :: tail :: Nil ) if tycon.isRef(defn.PairClass ) =>
443+ unrollTupleTypes(tail).map(head :: _)
444+ case tpe : TermRef if tpe.symbol == defn.EmptyTupleModule =>
445+ Some (Nil )
446+ case _ =>
447+ None
448+
449+ if (inlinedMethod == defn.Compiletime_constValue ) {
450+ return constValueOrError(callTypeArgs.head.tpe)
425451 }
426452 else if (inlinedMethod == defn.Compiletime_constValueOpt ) {
427- val constVal = tryConstValue
453+ val constVal = tryConstValue(callTypeArgs.head.tpe)
428454 return (
429455 if (constVal.isEmpty) ref(defn.NoneModule .termRef)
430456 else New (defn.SomeClass .typeRef.appliedTo(constVal.tpe), constVal :: Nil )
431457 )
432458 }
459+ else if (inlinedMethod == defn.Compiletime_constValueTuple ) {
460+ unrollTupleTypes(callTypeArgs.head.tpe) match
461+ case Some (types) =>
462+ val constants = types.map(constValueOrError)
463+ return Typed (tpd.tupleTree(constants), TypeTree (callTypeArgs.head.tpe)).withSpan(call.span)
464+ case _ =>
465+ return errorTree(call, em " Tuple element types must be known at compile time " )
466+ }
433467 else if (inlinedMethod == defn.Compiletime_summonInline ) {
434- def searchImplicit (tpt : Tree ) =
435- val evTyper = new Typer (ctx.nestingLevel + 1 )
436- val evCtx = ctx.fresh.setTyper(evTyper)
437- inContext(evCtx) {
438- val evidence = evTyper.inferImplicitArg(tpt.tpe, tpt.span)
439- evidence.tpe match
440- case fail : Implicits .SearchFailureType =>
441- errorTree(call, evTyper.missingArgMsg(evidence, tpt.tpe, " " ))
442- case _ =>
443- evidence
444- }
445- return searchImplicit(callTypeArgs.head)
468+ return searchImplicitOrError(callTypeArgs.head.tpe)
469+ }
470+ else if (inlinedMethod == defn.Compiletime_summonAll ) {
471+ unrollTupleTypes(callTypeArgs.head.tpe) match
472+ case Some (types) =>
473+ val implicits = types.map(searchImplicitOrError)
474+ return Typed (tpd.tupleTree(implicits), TypeTree (callTypeArgs.head.tpe)).withSpan(call.span)
475+ case _ =>
476+ return errorTree(call, em " Tuple element types must be known at compile time " )
446477 }
447478 end if
448479
0 commit comments