Unexpected Expr type


#1

Hi swift devs,

I'm working on SR-4464 to learn how to contribute to Swift. I think I
have the solution, but I'm getting unexpected results.

I'm using the swift repl within Xcode for testing. Here's my test code.

var name = "name"
name = (name)

In TypeChecker::diagnoseSelfAssignment in CSDiag.cpp, the src of the
AssignExpr is a plain Expr *, but I would expect it to be a ParenExpr
*. Could someone help me figure out what's happening?

Thanks,
Halen


(Jordan Rose) #2

Hi, Halen. Welcome to the compiler. :slight_smile: What you're seeing is that we don't usually use C++'s normal RTTI <https://en.wikipedia.org/wiki/Run-time_type_information> mechanism, but instead go with a "Kind" field that's checked by the custom 'cast', 'dyn_cast', and 'isa' functions. (More information in the LLVM Programmer's Manual <http://llvm.org/docs/ProgrammersManual.html#the-isa-cast-and-dyn-cast-templates>.) The debugger doesn't know about this, so it just always shows the base class to be conservative. If you're debugging, you can call dump() to see what kind of Expr it really is, and then cast the pointer down to the right type as needed. In your actual code, you can check `isa<ParenExpr>(src)`, or `dyn_cast<ParenExpr>(src)` if you then need to manipulate the ParenExpr.

Hope that helps,
Jordan

···

On Apr 6, 2017, at 15:30, Halen Wooten via swift-dev <swift-dev@swift.org> wrote:

Hi swift devs,

I'm working on SR-4464 to learn how to contribute to Swift. I think I
have the solution, but I'm getting unexpected results.

I'm using the swift repl within Xcode for testing. Here's my test code.

var name = "name"
name = (name)

In TypeChecker::diagnoseSelfAssignment in CSDiag.cpp, the src of the
AssignExpr is a plain Expr *, but I would expect it to be a ParenExpr
*. Could someone help me figure out what's happening?

Thanks,
Halen
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


#3

Hi Jordan,

Thanks for your reply. I tried the `dyn_cast<ParenExpr>(src)`, but it
gives me null. Here's what I've added:

bool TypeChecker::diagnoseSelfAssignment(const Expr *E) {

  ...

  auto src = AE->getSrc();
  auto parenSrc = dyn_cast<ParenExpr>(src);
  if (parenSrc)
    return false;

...

}

···

On Thu, Apr 6, 2017 at 6:49 PM, Jordan Rose <jordan_rose@apple.com> wrote:

Hi, Halen. Welcome to the compiler. :slight_smile: What you're seeing is that we don't
usually use C++'s normal RTTI mechanism, but instead go with a "Kind" field
that's checked by the custom 'cast', 'dyn_cast', and 'isa' functions. (More
information in the LLVM Programmer's Manual.) The debugger doesn't know
about this, so it just always shows the base class to be conservative. If
you're debugging, you can call dump() to see what kind of Expr it really is,
and then cast the pointer down to the right type as needed. In your actual
code, you can check `isa<ParenExpr>(src)`, or `dyn_cast<ParenExpr>(src)` if
you then need to manipulate the ParenExpr.

Hope that helps,
Jordan

On Apr 6, 2017, at 15:30, Halen Wooten via swift-dev <swift-dev@swift.org> > wrote:

Hi swift devs,

I'm working on SR-4464 to learn how to contribute to Swift. I think I
have the solution, but I'm getting unexpected results.

I'm using the swift repl within Xcode for testing. Here's my test code.

var name = "name"
name = (name)

In TypeChecker::diagnoseSelfAssignment in CSDiag.cpp, the src of the
AssignExpr is a plain Expr *, but I would expect it to be a ParenExpr
*. Could someone help me figure out what's happening?

Thanks,
Halen
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


(Slava Pestov) #4

Here’s what the AST looks like in this case — there is a ParenExpr but it’s inside a LoadExpr — we’re semantically loading the largest sub-expression that’s an lvalue, which here is ‘(x)’ not ‘x’:

      (assign_expr
        (declref_expr type='@lvalue Int' accessKind=write location=x.swift:3:1 range=[x.swift:3:1 - line:3:1] decl=x.(file).v@x.swift:1:5 direct_to_storage function_ref=unapplied specialized=no)
        (load_expr implicit type='(Int)' location=x.swift:3:6 range=[x.swift:3:5 - line:3:7]
          (paren_expr type='(@lvalue Int)' accessKind=read location=x.swift:3:6 range=[x.swift:3:5 - line:3:7]
            (declref_expr type='@lvalue Int' accessKind=read location=x.swift:3:6 range=[x.swift:3:6 - line:3:6] decl=x.(file).v@x.swift:1:5 direct_to_storage function_ref=unapplied specialized=no)))))))

Slava

···

On Apr 6, 2017, at 4:02 PM, Halen Wooten via swift-dev <swift-dev@swift.org> wrote:

Hi Jordan,

Thanks for your reply. I tried the `dyn_cast<ParenExpr>(src)`, but it
gives me null. Here's what I've added:

bool TypeChecker::diagnoseSelfAssignment(const Expr *E) {

...

auto src = AE->getSrc();
auto parenSrc = dyn_cast<ParenExpr>(src);
if (parenSrc)
   return false;

...

}

On Thu, Apr 6, 2017 at 6:49 PM, Jordan Rose <jordan_rose@apple.com> wrote:

Hi, Halen. Welcome to the compiler. :slight_smile: What you're seeing is that we don't
usually use C++'s normal RTTI mechanism, but instead go with a "Kind" field
that's checked by the custom 'cast', 'dyn_cast', and 'isa' functions. (More
information in the LLVM Programmer's Manual.) The debugger doesn't know
about this, so it just always shows the base class to be conservative. If
you're debugging, you can call dump() to see what kind of Expr it really is,
and then cast the pointer down to the right type as needed. In your actual
code, you can check `isa<ParenExpr>(src)`, or `dyn_cast<ParenExpr>(src)` if
you then need to manipulate the ParenExpr.

Hope that helps,
Jordan

On Apr 6, 2017, at 15:30, Halen Wooten via swift-dev <swift-dev@swift.org> >> wrote:

Hi swift devs,

I'm working on SR-4464 to learn how to contribute to Swift. I think I
have the solution, but I'm getting unexpected results.

I'm using the swift repl within Xcode for testing. Here's my test code.

var name = "name"
name = (name)

In TypeChecker::diagnoseSelfAssignment in CSDiag.cpp, the src of the
AssignExpr is a plain Expr *, but I would expect it to be a ParenExpr
*. Could someone help me figure out what's happening?

Thanks,
Halen
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


#5

Ah, that makes sense.

Thanks so much to you both for helping out. Hopefully I'll have a PR
ready before too long!

···

On Thu, Apr 6, 2017 at 7:11 PM, Halen Wooten <halen@hpwooten.com> wrote:

Ah, that makes sense.

Thanks so much to you both for helping out. Hopefully I'll have a PR
ready before too long!

Halen

On Thu, Apr 6, 2017 at 7:05 PM, Slava Pestov <spestov@apple.com> wrote:

Here’s what the AST looks like in this case — there is a ParenExpr but it’s inside a LoadExpr — we’re semantically loading the largest sub-expression that’s an lvalue, which here is ‘(x)’ not ‘x’:

      (assign_expr
        (declref_expr type='@lvalue Int' accessKind=write location=x.swift:3:1 range=[x.swift:3:1 - line:3:1] decl=x.(file).v@x.swift:1:5 direct_to_storage function_ref=unapplied specialized=no)
        (load_expr implicit type='(Int)' location=x.swift:3:6 range=[x.swift:3:5 - line:3:7]
          (paren_expr type='(@lvalue Int)' accessKind=read location=x.swift:3:6 range=[x.swift:3:5 - line:3:7]
            (declref_expr type='@lvalue Int' accessKind=read location=x.swift:3:6 range=[x.swift:3:6 - line:3:6] decl=x.(file).v@x.swift:1:5 direct_to_storage function_ref=unapplied specialized=no)))))))

Slava

On Apr 6, 2017, at 4:02 PM, Halen Wooten via swift-dev <swift-dev@swift.org> wrote:

Hi Jordan,

Thanks for your reply. I tried the `dyn_cast<ParenExpr>(src)`, but it
gives me null. Here's what I've added:

bool TypeChecker::diagnoseSelfAssignment(const Expr *E) {

...

auto src = AE->getSrc();
auto parenSrc = dyn_cast<ParenExpr>(src);
if (parenSrc)
   return false;

...

}

On Thu, Apr 6, 2017 at 6:49 PM, Jordan Rose <jordan_rose@apple.com> wrote:

Hi, Halen. Welcome to the compiler. :slight_smile: What you're seeing is that we don't
usually use C++'s normal RTTI mechanism, but instead go with a "Kind" field
that's checked by the custom 'cast', 'dyn_cast', and 'isa' functions. (More
information in the LLVM Programmer's Manual.) The debugger doesn't know
about this, so it just always shows the base class to be conservative. If
you're debugging, you can call dump() to see what kind of Expr it really is,
and then cast the pointer down to the right type as needed. In your actual
code, you can check `isa<ParenExpr>(src)`, or `dyn_cast<ParenExpr>(src)` if
you then need to manipulate the ParenExpr.

Hope that helps,
Jordan

On Apr 6, 2017, at 15:30, Halen Wooten via swift-dev <swift-dev@swift.org> >>>> wrote:

Hi swift devs,

I'm working on SR-4464 to learn how to contribute to Swift. I think I
have the solution, but I'm getting unexpected results.

I'm using the swift repl within Xcode for testing. Here's my test code.

var name = "name"
name = (name)

In TypeChecker::diagnoseSelfAssignment in CSDiag.cpp, the src of the
AssignExpr is a plain Expr *, but I would expect it to be a ParenExpr
*. Could someone help me figure out what's happening?

Thanks,
Halen
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev