@@ -719,6 +719,44 @@ object Checking {
719719 checkValue(tree)
720720 case _ =>
721721 tree
722+
723+ /** Check that experimental language imports in `trees`
724+ * are done only in experimental scopes, or in a top-level
725+ * scope with only @experimental definitions.
726+ */
727+ def checkExperimentalImports (trees : List [Tree ])(using Context ): Unit =
728+
729+ def nonExperimentalStat (trees : List [Tree ]): Tree = trees match
730+ case (_ : Import | EmptyTree ) :: rest =>
731+ nonExperimentalStat(rest)
732+ case (tree @ TypeDef (_, impl : Template )) :: rest if tree.symbol.isPackageObject =>
733+ nonExperimentalStat(impl.body).orElse(nonExperimentalStat(rest))
734+ case (tree : PackageDef ) :: rest =>
735+ nonExperimentalStat(tree.stats).orElse(nonExperimentalStat(rest))
736+ case (tree : MemberDef ) :: rest =>
737+ if tree.symbol.isExperimental || tree.symbol.is(Synthetic ) then
738+ nonExperimentalStat(rest)
739+ else
740+ tree
741+ case tree :: rest =>
742+ tree
743+ case Nil =>
744+ EmptyTree
745+
746+ for case imp @ Import (qual, selectors) <- trees do
747+ languageImport(qual) match
748+ case Some (nme.experimental)
749+ if ! ctx.owner.isInExperimentalScope
750+ && selectors.exists(sel => experimental(sel.name) != scala2macros && experimental(sel.name) != erasedDefinitions) =>
751+ def check (stable : => String ) =
752+ checkExperimentalFeature(" features" , imp.srcPos,
753+ s " \n\n Note: the scope enclosing the import is not considered experimental because it contains the \n non-experimental $stable" )
754+ nonExperimentalStat(trees) match
755+ case EmptyTree =>
756+ case tree : MemberDef => check(i " ${tree.symbol}" )
757+ case tree => check(i " expression ${tree}" )
758+ case _ =>
759+ end checkExperimentalImports
722760}
723761
724762trait Checking {
0 commit comments