모호한 참조

모호한 참조 (Ambiguous Reference)

식별자 하나가 둘 이상의 정의를 가리킬 수 있어 컴파일러가 어느 쪽을 쓸지 못 정할 때 나오는 에러예요.

출처: Scala 3 Reference

본문

식별자가 둘 이상의 서로 다른 정의를 가리킬 수 있고, 컴파일러가 그중 하나를 결정하지 못할 때 이 에러가 발생해요.

이름 바인딩의 여러 종류에는 우선순위가 있고, 높은 것부터 낮은 것까지 순서는 이래요.

  1. 포함하는 스코프(enclosing scope) 안의 정의
  2. 상속된 정의와 패키지의 최상위 정의(top-level definition)
  3. 특정 이름을 import 하면서 도입된 이름
  4. 와일드카드(wildcard) import 로 도입된 이름
  5. 다른 파일에 있는 패키지의 정의

정의는 import 보다 우선한다는 점, 그리고 안쪽 스코프의 바인딩이 바깥쪽 스코프의 더 높은 우선순위 바인딩을 가릴(shadow) 수 없다는 점을 기억해 두세요.

예시

import scala.collection.immutable.Seq
import scala.collection.mutable.Seq

val items = Seq(1, 2, 3)

에러 메시지

-- [E049] Reference Error: example.scala:4:12 ----------------------------------
4 |val items = Seq(1, 2, 3)
  |            ^^^
  |  Reference to Seq is ambiguous.
  |  It is both imported by name by import scala.collection.immutable.Seq
  |  and imported by name subsequently by import scala.collection.mutable.Seq
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | The identifier Seq is ambiguous because two name bindings of equal precedence
  | were introduced in the same scope.
  |
  | The precedence of the different kinds of name bindings, from highest to lowest, is:
  |  - Definitions in an enclosing scope
  |  - Inherited definitions and top-level definitions in packages
  |  - Names introduced by import of a specific name
  |  - Names introduced by wildcard import
  |  - Definitions from packages in other files
  | Note:
  |  - As a rule, definitions take precedence over imports.
  |  - Definitions in an enclosing scope take precedence over inherited definitions,
  |    which can result in ambiguities in nested classes.
  |  - When importing, you can avoid naming conflicts by renaming:
  |    import scala.{Seq => SeqTick}
   -----------------------------------------------------------------------------

해결 방법

// Use a rename to avoid the conflict
import scala.collection.immutable.Seq
import scala.collection.mutable.{Seq as MutableSeq}

val items = Seq(1, 2, 3)
val mutableItems = MutableSeq(1, 2, 3)
import scala.collection.{immutable, mutable}
// Or use qualified names
val items = immutable.Seq(1, 2, 3)
val mutableItems = mutable.Seq(1, 2, 3)
// Or import only what you need
import scala.collection.immutable.Seq

val items = Seq(1, 2, 3)

더 알아보기

  • 우선순위가 같은 두 바인딩이 같은 스코프에 함께 들어오면 그 이름은 모호하다고 판단돼요.
  • 이름을 바꿔 import 하거나(rename), 패키지 정규화된 이름(qualified name)을 쓰면 충돌을 피할 수 있어요.