Skip to content

SI-6879 improves Context.freshName#3401

Merged
xeno-by merged 2 commits intoscala:masterfrom
xeno-by:topic/fresh
Jan 22, 2014
Merged

SI-6879 improves Context.freshName#3401
xeno-by merged 2 commits intoscala:masterfrom
xeno-by:topic/fresh

Conversation

@xeno-by
Copy link
Copy Markdown
Contributor

@xeno-by xeno-by commented Jan 22, 2014

Instead of per-compilation unit unique counters, the freshName API now
uses a per-Global counter. Fresh names now also contain dollars to exclude
clashes with supported user-defined names (the ones without dollar signs).

This doesn’t fix the bug, because per-Global counters get created anew
every time a new Global is instantiated, and that provides some potential
for name clashes even for def macros, but at least it completely excludes
clashes in typical situations.

@xeno-by
Copy link
Copy Markdown
Contributor Author

xeno-by commented Jan 22, 2014

review @retronym /cc @densh

@ghost ghost assigned retronym Jan 22, 2014
@retronym
Copy link
Copy Markdown
Member

Does this apply to the full compiler, or just fresh names in macros? I'd be concerned about the former; I expect this could create (more) instability in mangled names in, for example, protected accessors. (Just using that example as I saw a use of freshname there recently while working on 8642a50.)

@xeno-by
Copy link
Copy Markdown
Contributor Author

xeno-by commented Jan 22, 2014

The only client of globalFreshNameCreator is scala.reflect.macros.Names, so this is only going to affect macros.

@densh
Copy link
Copy Markdown
Contributor

densh commented Jan 22, 2014

To be more precise: this will affect macros and quasiquotes at runtime but should not affect compiler.

@retronym
Copy link
Copy Markdown
Member

Looks sensible.

LGTM

Instead of per-compilation unit unique counters, the freshName API now
uses a per-Global counter. Fresh names now also contain dollars to exclude
clashes with supported user-defined names (the ones without dollar signs).

This doesn’t fix the bug, because per-Global counters get created anew
every time a new Global is instantiated, and that provides some potential
for name clashes even for def macros, but at least it completely excludes
clashes in typical situations.
xeno-by added a commit that referenced this pull request Jan 22, 2014
SI-6879 improves Context.freshName
@xeno-by xeno-by merged commit f22ddce into scala:master Jan 22, 2014
@xeno-by xeno-by deleted the topic/fresh branch January 24, 2014 16:43
@retronym
Copy link
Copy Markdown
Member

retronym commented Jan 17, 2018

@xeno-by / @densh This change conflicts with my current work to make scalac output stable (e.g. same output regardless of order of source files or regardless of separate compilation of subsets of the source files.)

Neither scala/bug#6879 nor https://groups.google.com/forum/#!topic/scala-internals/aE81MVdIhCk provides me with a motivating example to show that fresh-counters-per-compilation-unit is too fine-grained for macros. Surely this would only be an issue if snippets of code expanded by macros/quasiquotes in different compilation units were inlined together, untypechecked, then retypechecked. Is that use case actually possible?

My proposal is to to make all typer-generate fresh names (including macro and quasiquote) use a counter scoped at the closest enclosing "source method".

retronym added a commit to retronym/scala that referenced this pull request Feb 2, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiqotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations witin the typer phase (in which
    out-of-order typechecking is a factor) to use a finder grained fresh
    name creator. How fine grained? A fresh name generated as some position `p`
    shares the fresh name generator scoped at the closest method or class that
    encloses that the outermost enclosing tree at the same position.
    This definition is designed to give a shared fresh name creator for all
    fresh names generated in `macro1(macro2())`, even if the fresh names are
    requiested from with a Typer in the macro enclosed by a synthetic method.
  - Chances macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real world cases where the new scheme actaully causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request Feb 2, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request Mar 1, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request Mar 1, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request Mar 12, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request Mar 18, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request Mar 22, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request May 4, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request May 12, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request May 28, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request May 29, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request May 29, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request May 29, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request May 29, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).
retronym added a commit to retronym/scala that referenced this pull request Sep 12, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).

(cherry picked from commit 69d60cb)
adriaanm pushed a commit to retronym/scala that referenced this pull request Oct 16, 2018
Fresh names are created using a FreshNameCreator, which appends
an increasing number to the given prefix.

```
scala> val fresh = new scala.reflect.internal.util.FreshNameCreator()
fresh: scala.reflect.internal.util.FreshNameCreator = scala.reflect.internal.util.FreshNameCreator@42b84286

scala> List("foo$", "bar$", "foo$").map(fresh.newName(_))
res1: List[String] = List(foo$1, bar$1, foo$2)
```

Each compilation unit had its own fresh name creator, which is used
in the regular compiler. Macros and quasiquotes make use of a global
creator (at least, as of scala#3401).

Both of these are too broadly scoped to help achieve deterministic
fresh names: if sources are recompiled in a different order or separately
recompiled, the fresh name counters can be different. Methods in a given
compilation unit are not necessarily typechecked in a linear fashion;
they might be typechecked ahead of time to provide an inferred type
to a caller.

This commit:

  - Changes all known fresh name creations within the typer phase (in which
    out-of-order typechecking is a factor) to use a fineer grained fresh
    name creator. How fine grained? A fresh name generated as some position
    `p` shares the fresh name generator scoped at the closest method or
    class that encloses that the outermost enclosing tree at the same
    position. This definition is designed to give a shared fresh name
    creator for all fresh names generated in `macro1(macro2())`, even if
    the fresh names are requiested from with a Typer in the macro enclosed
    by a synthetic method.
  - Changes macro fresh names to use the same fresh naming scheme as the regular
    typechecker. An opt-out compiler option allows the old behaviour, but I'm
    interested to find real-world cases where the new scheme actually causes
    a problem

In addition, a small change is made to lambda lift to lift local methods in the
order that they are encountered during traversal, rather than sorting them
based on `Symbol.isLess` (which include `Symbol.id`, an order-of-typechecking
dependent value).

(cherry picked from commit 69d60cb)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants