Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doh004 posted:

Started new job where our new solution is all Swift. Are we doing something wrong where most of the objects aren't debuggable? I can't do po myObject anymore. Just get a slew of lldb errors. Is it some build configuration setting?

I'll get certain files or parts of certain files where any debugger action just spews errors instead. I can't be arsed to track down the problematic parts, but maybe knowing that you're not alone will help.

Adbot
ADBOT LOVES YOU

MrSaturn
Sep 8, 2004

Go ahead, laugh. They all laugh at first...
I see this a lot, especially when dealing with CoreData objects - even when the debugger is at a breakpoint, they're unintelligible unless I do loads of println() work around them...

Doh004
Apr 22, 2007

Mmmmm Donuts...

Ender.uNF posted:

Check for warnings or problems in your headers. If there's anything amiss it will put lldb into a tailspin.

Hmm there was one about some weird rear end library search header. Trying it now.

pokeyman posted:

I'll get certain files or parts of certain files where any debugger action just spews errors instead. I can't be arsed to track down the problematic parts, but maybe knowing that you're not alone will help.

Ugh this sucks. Do you also have Xcode randomly freak out and have the cursor jump around a file from time to time?

lord funk
Feb 16, 2004

I gave up trying to use lldb to drill down at all in Swift. I would show students breakpoints and 'po' but it would just hang for 10 seconds and then spit out gibberish, every time.

Doh004
Apr 22, 2007

Mmmmm Donuts...
So how the hell do we debug properly? println everywhere?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Just write correct code the first time.

MrSaturn
Sep 8, 2004

Go ahead, laugh. They all laugh at first...

Doh004 posted:

So how the hell do we debug properly? println everywhere?

Switch to visual studio I wish!

brap
Aug 23, 2004

Grimey Drawer
Is it easier to implement an awesome debugger like visual studio has for C# when the language uses JIT compilation? Or does that not matter? Either way, Swift's debugging capabilities are pretty lacking.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

fleshweasel posted:

Is it easier to implement an awesome debugger like visual studio has for C# when the language uses JIT compilation? Or does that not matter?

It doesn't really matter.

fleshweasel posted:

Either way, Swift's debugging capabilities are pretty lacking.

First: as a meta note, don't take this post as discouraging venting. Vent away about whatever terrible things you find. I just want to explain from my perspective (1) why some of this is how it is and (2) why there's reason to be hopeful.

The main thing is that, as I've tried to emphasize before, this first year is really more of a public beta of Swift than a proper release. I know that marketing hasn't been clear about this, but I've always tried to be straight with you. It's not just that Swift is not finished, in some grand sense of the word; it's that Swift is not really done. It's usable on some level, and we are promising to support what we've shipped; but there's a lot of stuff that's missing, or doesn't work, or is just embarrassingly broken. I hope that most of that will be better after the first full year, and that it'll be closer to just not being cosmically-speaking finished. But we'll see.

Now, I have some rants about LLDB that I can't really share because I'm not actually anonymous here; maybe if this were a goonmeet. But most of the instability/inadequacy you're seeing there really is caused by us — Swift, LLVM, LLDB, all together — trying some very aggressive things technically that haven't quite gelled yet. It is often the case, especially in language work but in programming in general, that one small corner-case problem in your code or your configuration blocks the entire product from functioning, even when that's not really the bit of your code that you care about at the moment. Of course, as a user you perceive that as the product being completely broken, which is a fair perspective in the sense that your work is completely disrupted; I'm just saying that, as an insight into the state of development, it doesn't actually tell you as much as you might think.

There are two major technical pushes hurting Swift debugging right now, at least that I can think of off the top of my head, and both of them should ultimately lead to a much better experience when they come together a bit more.

Traditional Unix/Darwin C debugging is based off of DWARF, which is basically a weird shadow AST that gets emitted into object files with ties back to the actual emitted function. gdb essentially implements its own language frontends using DWARF as the AST, which is both why it feels more forgiving sometimes and why there are firm limits to what it can handle in the expression parser. Part of the vision for LLDB has always been to provide a more authentic language experience, which it does by trying to map DWARF back into real Clang AST and letting Clang interpret it. That's why LLDB is capable of parsing arbitrary language structures, but also why it can be frustratingly strict. In principle, a lot of that strictness could be fixed — Clang knows that it's parsing a debugger expression and could apply more lenient language rules — but unfortunately that team has never had enough time for that kind of polish work because they keep getting pulled around by other projects. Like, say, getting told to add a whole new language mode for Swift.

Mapping DWARF back into Clang ASTs does have a major risk, though, which is that you really need DWARF to fully encode the actual language; if there are gaps that DWARF doesn't get right, things just break. For example, until fairly recently, the DWARF spec itself didn't have any way to encode C++11 ref-qualifiers on methods, so that stuff didn't round-trip correctly, with the result that you actually can't call those methods from lldb. That's getting fixed, but it's a problem we wanted to define away in Swift. Swift therefore uses DWARF pretty much only to track variables around the call frame; the DWARF types and declarations are just there to provide references back to the actual Swift ASTs generated during compilation. It's a really promising technical direction, and it does show benefits when it works, but unfortunately there are just a lot of kinks we haven't resolved yet; and when it doesn't work, it doesn't work at all. Plus, whenever you have a significant technical shift like this, it just takes time to replicate all the capabilities of the previous model; there's a lot of tooling which is tied to precise details of the old thing that you can never perfectly imitate, and which you may never have meant to guarantee even in the old world.

The second major technical direction is value tracking. In C, local variables usually live in memory, generally in fixed locations on the stack. LLVM is pretty good at honoring debugging directives that say obvious things like that: "hey, the location of this variable is this particular offset within the frame". When the optimizer moves the variable into registers, this sort of tracking gets more complicated, and LLVM kindof sucks at it. In C, that's arguably okay, maybe, because it's understood that optimization inhibits debugging somewhat; but LLVM often fails to even make best-effort attempts to remember debugging information about variables that aren't on the stack. Again, it's just polish work that they've been deprioritizing.

Well, it turns out that a bunch of language features in Swift make it harder to always keep variables in a fixed location on the stack, even in debug builds. We're much more reliant on having to tell LLVM, "hey, the address of this variable is the result of such-and-such computation" or "hey, the current value of this variable isn't stored in memory, it's just such-and-such value at this point in the function". Now, those are exactly the things that good optimized C debugging relies on, but like I said, LLVM has been punting on that work for a long time. The unfortunate thing for LLDB as a team is that it's not their fault at all; it's a combination of language complexity and LLVM bugs that just happens to look exactly like yet another "loving debugger can't do anything right" problem.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

That was an OK post.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Subjunctive posted:

That was an OK post.

:hugbox:

Doh004
Apr 22, 2007

Mmmmm Donuts...
Thanks for that rjmccall. While I understood about half of what you said, I do know that there's plenty of reasons for stuff not working. Definitely appreciate your perspective on it, just a bit frustrated at how unfinished it is. I know you're saying it should have been called a Beta, and I would have been cool with that label, but it sucks that Apple as a whole isn't calling it that.

This is most definitely not a 1.0.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I don't know why it feels better to have some insight into why poo poo breaks, but it does. Thanks.

I guess in the "ruthless efficiency" sense the current prioritization works on me: I haven't run away screaming from Swift. If I was leading a team on a new project today, though, there's no way I'd admit Swift into it.

I'll try to remember the missing "public beta" label, it's very easy to forget.

Kallikrates
Jul 7, 2002
Pro Lurker
Just imagine all the guys out there in the trenches, like us, without "Just one more thing - Swift thread"

brap
Aug 23, 2004

Grimey Drawer
Seriously, I have loved swift development. It's a great language. Thank you for the insight you provide into the issues facing the language designers.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
pre:
/Classes/PGOperation.h:9:9: note: in file included from /Classes/PGOperation.h:9:
#import <AFNetworking/AFHTTPRequestOperation.h>
        ^
/Pods/Headers/Public/AFNetworking/AFHTTPRequestOperation.h:24:9: 
note: in file included from /Pods/Headers/Public/AFNetworking/AFHTTPRequestOperation.h:24:
#import "AFURLConnectionOperation.h"
        ^
/Pods/Headers/Public/AFNetworking/AFURLConnectionOperation.h:192:1:
error: property with 'retain (or strong)' attribute must be of object type
@property (nonatomic, strong) dispatch_queue_t completionQueue;
When I replied last night I was trying to think of a good example and it just happened to me today while debugging some Swift code.

I am not using AFNetworking or even PGOperation anywhere in the code I am trying to debug, but because AFNetworking is reachable from the bridging header, the semantic error (treating the dispatch types as strong**) completely prevents LLDB from being able to print out certain objects or run certain commands.

I can fix it by moving the header into the implementation file if possible, or changing the AFNetworking definition.

** In reality, under Obj-C and ARC the GCD references are all object types so this is actually OK. I think LLDB is using the wrong defines when it processes the headers so it ends up with a different definition than the actual running code has which is... a whole other horror given the turing completeness of the C preprocessor.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

rjmccall posted:

First: as a meta note, don't take this post as discouraging venting. Vent away about whatever terrible things you find. I just want to explain from my perspective (1) why some of this is how it is and (2) why there's reason to be hopeful.

If we can't come here to vent then what's the point?

A++ post, would read again.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Ender.uNF posted:

** In reality, under Obj-C and ARC the GCD references are all object types so this is actually OK. I think LLDB is using the wrong defines when it processes the headers so it ends up with a different definition than the actual running code has which is... a whole other horror given the turing completeness of the C preprocessor.

I think that's exactly what's happening. GCD/XPC types like dispatch_queue_t are only object references in 10.8 / 6.0 and higher, and LLDB may not be setting a deployment target (despite knowing exactly what target to build for).

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

Subjunctive posted:

That was an OK post.

I liked it

Toady
Jan 12, 2009

Xcode 6.3b1 is out, with changes significant enough to warrant a code migrator.

lord funk
Feb 16, 2004

Swift Blog posted:

let constants are now more powerful and consistent — The new rule is that a let constant must be initialized before use (like a var), and that it may only be initialized, not reassigned or mutated after initialization.

:dance:

Actually, :dance: for everything in the post.

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer
Incremental compilation!!! :dance:

dizzywhip
Dec 23, 2005

Yessssssss! Downloading now, I hope the incremental builds work well. Tons of other cool new features and fixes too. I'm really happy you can "if let" multiple things at once now, although the syntax seems a little bizarre.

code:
if let a = foo(), b = bar() where a < b,
    let c = baz() {
}
Not sure why let x = y couldn't just be a standalone expression in the context of an if statement so you could just do something like this:

code:
if let a = foo() && let b = bar() && a < b && let c = baz() { ... }
So excited to try this out!

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Would the value of a let expression always be true, then? Would you expect short circuiting of evaluation?

dizzywhip
Dec 23, 2005

It'd be true if a value was extracted from the optional and false otherwise, and it would short-circuit like any other boolean expression. I think that would be a pretty logical extension of the simple if-let syntax and would eliminate the need for another special syntax. It's not a huge deal, I was just surprised when I saw that because I thought making it a boolean expression was the obvious solution. Maybe there's a reason it wouldn't work that I haven't thought of, though.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

dizzywhip posted:

Not sure why let x = y couldn't just be a standalone expression in the context of an if statement so you could just do something like this:

code:

if let a = foo() && let b = bar() && a < b && let c = baz() { ... }

Because && is an ordinary binary operator, and it would be kindof silly to have a special parsing rule for it so that if let x = foo() && bar() doesn't parse as if let x = (foo() && bar())

dizzywhip
Dec 23, 2005

I suppose so, but a special parsing rule that makes the language more intuitive for the user (or at least for me, I can't say how intuitive it would be in general) seems like a lesser evil than a new syntax to handle one specific situation.

chaosbreather
Dec 9, 2001

Wry and wise,
but also very sexual.

I would have thought it would have been if let a, b = foo(), bar() so it's like a regular multi assignment.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

chaosbreather posted:

I would have thought it would have been if let a, b = foo(), bar() so it's like a regular multi assignment.

What we're currently considering as the slightly longer-term vision here is introducing an optional-desugaring pattern, probably spelled ?, and then taking away the special semantics of if let. So to get the current behavior, you would have to write:

Swift code:
  if let a? = foo() { ... }
But this generalizes optional binding to arbitrary positions in the pattern, if you wanted to avoid the new syntax or had a return value with multiple optionals or whatever:

Swift code:
  if let (a?,b?) = (foo(), bar()) { ... }
It also generalizes if let to work with arbitrary refutable patterns, so that you could write:

Swift code:
  if let (a?,b) = (foo(), bar()) { ... }
or, if/when we add array patterns:

Swift code:
  if let [a,b,c] = foo() { ... }

rjmccall fucked around with this message at 23:43 on Feb 9, 2015

Toady
Jan 12, 2009

One weird tip to cause a segfault (19585191):
code:
class Crasher {
    var foo: [foo]? { return nil }
}

ljw1004
Jan 18, 2005

rum

rjmccall posted:

Because && is an ordinary binary operator, and it would be kindof silly to have a special parsing rule for it so that if let x = foo() && bar() doesn't parse as if let x = (foo() && bar())

Sure, but I guess I'd expected "let" to have much higher precedence. After all there are few useful operators upon possibly-null types, so you'll rarely want to do things like && on the argument of a "let ID = expr".

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
?? comes to mind. Right now it has the same precedence as ||, which is actually lower than &&, although we're looking at bumping it to higher than && for separate reasons.

Trust me, the first option we considered was &&, and after some discussion we decided that we didn't really like the results. Beyond the really weird things it does to the grammar (because && is not the lowest-precedence operator), it also implies way too much: it makes 'let' pattern '=' expression look like a general expression form that could be used anywhere, e.g. nested within ||, !, and arbitrary other short-circuiting or oddly-evaluated forms, which is basically just a disaster. A superficially similar construct, let x = y in z, works in functional languages; but there, crucially, the binding is scoped to a specific expression, which is not what you're asking for here. Here, the name really needs to be bound in an enclosing scope (albeit a new one) and then available in later expressions in the condition. It just doesn't work as a general expression with these semantics; the type-checker would actually have to check control flow through the expression before it could even resolve name lookup, or we'd have to come up with some further special-case rule about it. It's a lot of complexity to embrace just to get a slightly more natural operator, when the comma works fine and is analogous to list-comprehension (it is basically exactly the same, but in the Optional monad rather than List.)

dizzywhip
Dec 23, 2005

That makes sense. It seemed like a simpler solution on the surface, but I hadn't really considered the implications of how it would work in more complicated expressions.

I'm very happy with 1.2 overall so far. There does seem to be several new bugs that I've encountered, but I haven't run into anything that didn't have a straightforward workaround. And compile times are enormously improved in most cases so far, which is a huge relief.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
That's good to hear. There's a lot of work left to be done with both incremental compilation and type-checking speed generally, and I was a little worried that the improvements might not prove to be general enough, so I'm happy to hear that people are seeing a difference.

If anyone is curious, I spent most of this release cycle designing and implementing secret language features to make arrays faster. So if you see any weird results with arrays, it might be my fault (hopefully it is actually your fault for doing something that's not allowed (it is actually still my fault for not telling you what's not allowed)).

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Requiring 10.10 makes me sad :(

ljw1004
Jan 18, 2005

rum

rjmccall posted:

?? comes to mind. Right now it has the same precedence as ||, which is actually lower than &&, although we're looking at bumping it to higher than && for separate reasons.

I understand the rest of your post, but don't understand this as a counter-example for "if let x = a ?? b && let z = c".

If it means "if let x = (a ?? b)" then it's be wrong because a??b wouldn't be an option type and hence you couldn't do "if let" on it. (unless it was a double-option-type which is just ugly).

If it means "if (let x = a) ?? b" then it's wrong because the only way ??b could work is again if 'a' were a double option-type.

Overall, I'm struggling to see anything other than . and ?. and [] which should have a higher precedence than "let". The only operators where it would make sense would be either operators on optionals (and there aren't many), or the ternary if operator ?: as in "if let x = b ? a : b"

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The result of ?? has the optionality of its right-hand side. It is both (T?,T)->T and (T?,T?)->T?. That means if let x = y ?? z makes sense without weird nested optionals: it just binds x to the first of y or z that has a value, assuming they're both optional.

Kallikrates
Jul 7, 2002
Pro Lurker
I hope some of the more common 'functional' operators start landing in the standard library. Seeing some weird looking operators out there made out of a mish mash of what's allowed in operator definitions, and what exists in other languages. Either as global methods like map and filter or operator defined like "+"

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
They won't because that's a lovely idea. Why would you want to do that with operators?

I can understand wanting comprehensions, but seriously, some people just have the worst instincts.

ETA: oh, if you mean piping operators, I'm still skeptical but a little less so.

Adbot
ADBOT LOVES YOU

Kallikrates
Jul 7, 2002
Pro Lurker
Maybe I worded it poorly, but some of the libraries you get when you google "Functional swift" introduce some weird operators. For example "<^> j <| ...", "<*> j <|| ..., ">>==" (as a flat map not bit shift, already a collision), "<<" (another collision, append array). I don't want to have to guess (look up) what a `simple` operator means in different contexts so I prefer words. Some 3rd party swift library developers seem to have a different opinion.

I think the error description displayed when playing and trying to define operator flatMap vs just a function flapMap derailed my Sunday. I was just trying to see the different approaches others have taken (that seem popular). I think the better approach would be to follow 'map()'s example, and not '+'s. There is a large body of blogs and code that look at it as an operator.

  • Locked thread