This is an archive of the discontinued LLVM Phabricator instance.

[Sema][CodeCompletion] Fix return type of C++ destructors in code completion
AbandonedPublic

Authored by jkorous on Sep 20 2018, 8:37 AM.

Details

Summary

Destructors don't have return type "void", they don't have any return type at all.

Diff Detail

Repository
rC Clang

Event Timeline

jkorous created this revision.Sep 20 2018, 8:37 AM

When you're *calling* a destructor, I believe the expression does have type void. Are we sure this is incorrect?

Calling a destructor is really unusual though. IIRC we decided to just not show them in clangd in member context (maybe this is broken or was never implemented, though).

You might be right - I am assuming here that we want consistent behaviour between constructors and destructors.

IIUC ctors are currently skipped in code completions (in most cases) but they also don't have any type associated while result of their call definitely has some type.

Currently we are showing destructors in code completion in clangd (with detail "void") - that's actually how I noticed this.

I would assume that canonical type in function/method code completion is "it's type" not "type of result of it's call". WDYT?

jkorous added a comment.EditedSep 20 2018, 9:09 AM

Sorry my bad. You are right, we aren't showing destructors in clangd for normal classes. The case where I noticed is kind of a corner case with template class.

{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
---
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"template<class T> struct foo {}; template<> struct foo<bool> {}; foo<long>::~"}}}
---
{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":0,"character":76}}}
{
  "detail": "void",
  "filterText": "~foo",
  "insertText": "~foo",
  "insertTextFormat": 1,
  "kind": 2,
  "label": " ~foo()",
  "sortText": "3f2ccccc~foo",
  "textEdit": {
    "newText": "~foo",
    "range": {
      "end": {
        "character": 76,
        "line": 0
      },
      "start": {
        "character": 76,
        "line": 0
      }
    }
  }
},

You might be right - I am assuming here that we want consistent behaviour between constructors and destructors.

IIUC ctors are currently skipped in code completions (in most cases) but they also don't have any type associated while result of their call definitely has some type.

Tricky.

MyClass() has a type, and should probably have return type MyClass, though it's pretty clear from the name (one could make the same argument about destructors).
Note that the "return type matches" ranking heuristics will trigger on these types so it's not just presentational, I think we should be including the types for constructors.

But class Derived : MyClass { Derived : MyClass() {} }; doesn't have a type (it's not an expression).

And MyClass::MyClass() has a type, but it's probably more likely that the user is going for a plain MyClass::MyClass (e.g. in a class-scoped using decl) which doesn't have a useful type.

Currently we are showing destructors in code completion in clangd (with detail "void") - that's actually how I noticed this.

I would assume that canonical type in function/method code completion is "it's type" not "type of result of it's call". WDYT?

I don't think so, for better or worse it's result of it's call. Or rather: type of the expression that we guess the user's going to form, or that we suggest.
Again, this seems to give the best code completion presentation, and also best ranking results (when the expected type of the context is known)

Sorry my bad. You are right, we aren't showing destructors in clangd for normal classes. The case where I noticed is kind of a corner case with template class.

{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
---
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"template<class T> struct foo {}; template<> struct foo<bool> {}; foo<long>::~"}}}
---
{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":0,"character":76}}}
{
  "detail": "void",
  "filterText": "~foo",
  "insertText": "~foo",
  "insertTextFormat": 1,
  "kind": 2,
  "label": " ~foo()",
  "sortText": "3f2ccccc~foo",
  "textEdit": {
    "newText": "~foo",
    "range": {
      "end": {
        "character": 76,
        "line": 0
      },
      "start": {
        "character": 76,
        "line": 0
      }
    }
  }
},

Indeed, this looks like a bug to me.

jkorous abandoned this revision.Sep 21 2018, 7:06 AM

Allright, I will remove destructor from clangd completion results which solves this particular issue.

Also good point about return type being used in ranking - I incorrectly assumed it's just a presentational matter.