Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context / implicit params to synthetics #2

Closed
wants to merge 58 commits into from

Conversation

tanishiking
Copy link
Owner

@tanishiking tanishiking commented Aug 2, 2021

scala#13135
Based on: scala#12885

This PR adds synthetics (for implicit-param and context-param application) to SemanticDB.

Questions

Added synthetics

implicit / context params application

def foo(x: Int)(using Int) = ???
def m(using x: Int) = foo(0)

// synthetics
def m(using x: Int) = foo(0)<<(x)>>
Synthetic(
  <foo(0)>,
  ApplyTree(
    OriginalTree(<foo(0)>),
    List(
      IdTree(<x>),
    )
  )
)

Same with Implicit parameters synthetics in Scala2 https://scalameta.org/docs/semanticdb/specification.html#synthetic-1

anonymous context params

def foo(using Int) = ???
 
// synthetic
def foo(using x$1: Int) = ???
Synthetic(
  <Int>,
  IdTree(<x$1>)
)

(Maybe range should be between using and Int, instead of overlaps with Int).

anonymous given value

given Int = 1

// synthetic
given given_Int: Int = 1
Synthetic(
  <given Int = 1>,
  IdTree(<given_Int>)
)

tanishiking and others added 30 commits June 24, 2021 14:02
To construct symbol table before referring the ParamRef
it's required to traverse the child trees before registering the symbol.
Previously, there were the risks that localIdx receives the symbol
that doens't have `span` because `TypeOps` generates dummy symbols for
refinements in `RefinedType` and `RecType`.
However, with the following commits,
scala@7dd91ad
scala@226e26f
now we never generate dummy symbol in `TypeOps`.
So re-insert the assertion we deleted when copying this method from
`ExtractSemanticDB`.
see: https://github.com/lampepfl/dotty/pull/12885/files#r658150249
For wildcard type `C[_ <: T]`, it's internal type representation will be
`AppliedType(TypeBounds(lo = <Nothing>, hi = <T>))`.

As scalameta for Scala2 does, we'll convert the wildcard type to
`ExistentialType(TypeRef(NoPrefix, C, <local0>), Scope(hardlinks = List(<local0>)))`
where `<local0>` has
- display_name: "_" and,
- signature: type_signature(..., lo = <Nothing>, hi = <T>)

See:
https://github.com/lampepfl/dotty/pull/12885/files#r663797616
https://scalameta.org/docs/semanticdb/specification.html#type-2

Now, when we compile the following Scala program to semanticdb

```scala
class Wildcards {
  def e1: List[_ <: Int] = ???
}
```

The semanticdb's SymbolInformation for `e1` looks like:

From scala3
```
  symbols {
    symbol: "advanced/Wildcards#e1()."
    kind: METHOD
    display_name: "e1"
    language: SCALA
    signature {
      value_signature {
        tpe {
          by_name_type {
            tpe {
              existential_type {
                tpe {
                  type_ref {
                    symbol: "scala/collection/immutable/List#"
                    type_arguments {
                      type_ref {
                        symbol: "local0"
                      }
                    }
                  }
                }
                declarations {
                  hardlinks {
                    symbol: "local0"
                    kind: TYPE
                    display_name: "_"
                    language: SCALA
                    signature {
                      type_signature {
                        type_parameters {
                        }
                        lower_bound {
                          type_ref {
                            symbol: "scala/Nothing#"
                          }
                        }
                        upper_bound {
                          type_ref {
                            symbol: "scala/Int#"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
```

On the other hand, generated from scalameta's metac with scalac 2.13.6

```sh
$ metac --version
Scala compiler version 2.13.6 -- Copyright 2002-2021, LAMP/EPFL and Lightbend, Inc.
```

```
  symbols {
    symbol: "advanced/Wildcards#e()."
    kind: METHOD
    display_name: "e"
    language: SCALA
    signature {
      method_signature {
        type_parameters {
        }
        return_type {
          existential_type {
            tpe {
              type_ref {
                symbol: "scala/package.List#"
                type_arguments {
                  type_ref {
                    symbol: "local0"
                  }
                }
              }
            }
            declarations {
              hardlinks {
                symbol: "local0"
                kind: TYPE
                properties: 4
                display_name: "_"
                language: SCALA
                signature {
                  type_signature {
                    type_parameters {
                    }
                    lower_bound {
                      type_ref {
                        symbol: "scala/Nothing#"
                      }
                    }
                    upper_bound {
                      type_ref {
                        symbol: "scala/Int#"
                      }
                    }
                  }
                }
                access {
                  public_access {
                  }
                }
              }
            }
          }
        }
      }
    }
    access {
      public_access {
      }
    }
  }
```
For example:
`def foo(x: T)(y: T): T` and for `<y>.owner.info` would be like
`MethodType(...<x>, resType = MethodType(...<y>, resType = <T>))`.
(Let's say the outer `MethodType` "outer", and `MethodType` who is
`resType` of outer "inner")

Before this commit, we register <y> to the symbol table with
`(<y>, outer)`, which should be `(<y>, inner)`.

For such a nested method signature, we have to find the "actual" binder
for parameters and register them to the symbol table.
When the prefix of SingleType is Type.Emtpy, we had been printing them
as `<?>.sym.type`, but it should be `sym.type`
Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com>
Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com>
@tanishiking tanishiking deleted the synthetics-context-params branch August 11, 2021 06:39
tanishiking pushed a commit that referenced this pull request Sep 21, 2023
Update docs canthrow.md remove bad type alias at line 70
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.

1 participant