Does CLion possible evaluate a function when debugging Rust code? - debugging

A snip of Rust code:
pub fn main() {
let a = "hello";
let b = a.len();
let c =b;
println!("len:{}",c)
}
When debugging in CLion, Is it possible to evaluate a function? For example, debug the code step by step, now the code is running to the last line println!... and the current step stops here, by adding the expression a.len() to the watch a variable window, the IDE can't evaluate the a.len(). It says: error: no field named len

This is the same reason you can't make conditional breakpoints for Rust code:
Can't create a conditional breakpoint in VSCode-LLDB with Rust

I hope, I'm not too late to answer this, but with both lldb and gdb, Rust debugging capability is currently rather constrained.
Expressions that are straightforward work; anything complex is likely to produce issues.
My observations from rust-lldb trying this, are that only a small portion of Rust is understood by the expression parser.
There is no support for macros.
Non-used functions are not included in the final binary.
For instance, since that method is not included in the binary, you are unable to execute capacity() on the HashMap in the debugger.
Methods must be named as follows:
struct value.method(&struct value)
There is no technique that I've discovered to call monomorphized functions on generic structs (like HashMap).
For example, "hello" is a const char [5] including the trailing NUL byte. String constants "..." in lldb expressions are produced as C-style string constants.
Therefore, they are not valid functions

Related

Execute a statement while debugging in Rust

While Coding in Python, I often do something like
test.py
x = []
breakpoint()
± |master U:5 ?:4 ✗| → python3 test.py
-> breakpoint()
(Pdb) x
[]
(Pdb) x.append(1)
(Pdb) x
[1]
Is it possible to execute the statement while debugging Rust?
use std::collections::HashMap;
fn main() {
let mut contacts = HashMap::new();
contacts.insert("Daniel", "798-1364");
contacts.insert("Ashley", "645-7689");
//set breakpoint here
}
So far, I can execute p contacts in the debug console, the meaning of this output isn't straight to me. What if I want to know the outcome of println!("{:?}", contacts); without writting this line of code in the source file.
And also I want to know the outcome of contacts.insert("Robert", "956-1742"), If I execute expr contacts.insert("Robert", "956-1742") in the debug console, it says error: no field named insert.
Rust debugging support is currently quite limited with both lldb and gdb. Simple expressions work, anything more complex is likely to cause problems.
My experience while testing this with rust-lldb:
The expression parser only understands a limited subset of Rust. Macros are not supported.
Functions that are not used are not included in the resulting binary. E.g. you cannot call capacity() on the HashMap in the debugger since that function is not included in the binary.
Methods have to be called like this: struct_value.method(&struct_value)
I haven't found a way to call monomorphized methods on generic structs (like HashMap).
String constants "..." in lldb expressions are created as C-style string constants, e.g. "abcdef" is a const char [7] including the trailing NUL byte. Thus they cannot be easily passed to Rust functions expecting &str arguments.
Trying to use a helper function like this:
pub fn print_contacts(contacts: &HashMap<&str, &str>) {
println!("{:?}", contacts);
}
causes lldb to crash:
(lldb) expr print_contacts(&contacts)
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0. Program arguments: [...]
Segmentation fault: 11
So it seems that what you want to do is not possible at this time.

Changing behavior based on number of return arguments like type assertions

I've been learning Go and one thing that stood out as particularly interesting to me is the way that the behavior of type assertions changes based on how many return values are being captured:
var i interface{} = "hello"
val, ok := i.(int) // All good
fmt.Println(val, ok)
val = i.(int) // Panics
fmt.Println(val)
This feels like a pattern that can be very useful for user defined functions. The user either has to explicitly get the "ok" second return value or use an underscore to ignore it. In either case, they're making it clear that they're aware that the function can fail. Whereas if they just get one return value, it could silently fail. Hence, it seems reasonable to panic or similar if the user isn't checking for an error (which would be reasonable if the error should "never" happen). I assume that's the logic behind the language developers in making type assertions work this way.
But when I tried to find out how that could be done, I found nothing. I'm aware that type assertions aren't an actual function. And many languages with multiple return values can't check how many return values are actually being used (MATLAB is the only one I'm aware of), but then again, most of those don't use behavior like the type assertions demonstrate.
So, is it possible and if so, how? If not, is there a particular reason that this behavior was excluded despite it being possible with the built in type assertions?
Sadly they cannot be used in normal functions. As far as i know only type assertions, map value access and range allow it.
Usually when you want to have a function with one and optional a second error argument you name them like
func DoSomething() (string, error) {...} // i will return an error
func MustDoSomething() string {...} // i will panic
An example would be https://golang.org/pkg/regexp/#MustCompile
This answer: https://stackoverflow.com/a/41816171/10278 by #christian provides the best practical advice for how to emulate the "overloaded-on-result-count" pattern.
My aim is to address another part of the question—this part: "But when I tried to find out how that could be done, I found nothing".
The following explains how it is done for Go type assertions.
Invocations of type assertions in Go behave as though they are overloaded based on number of results.
Yet, Go does not support overloading of methods and operators.
Looking at Go's implementation, here is the reason type assertions appear to be overloaded based on number of results:
The Go compiler provides special handling that is peculiar to these built-in operations.
This special dispatching occurs for the built-in concept of type assertions because the compiler is carving out special logic that is not available to non-built-in code.
The Go compiler and runtime are written in Go. That made it (somewhat) easy for me to discover that the compiler is the key to explaining this behavior.
Take a look at this part of the compiler:
https://github.com/golang/go/blob/8d86ef2/src/cmd/compile/internal/gc/ssa.go#L4782
The code comment already reveals a lot:
// dottype generates SSA for a type assertion node.
// commaok indicates whether to panic or return a bool.
// If commaok is false, resok will be nil.
We can go further by using a debugger to step through some type assertion code.
Take this playground snippet for example. Specifically, these lines:
object_as_closer_hardstop := thing.(io.Closer) // will panic!!
object_as_closer, ok := thing.(io.Closer)
(If you build Go from source, then) if you use a debugger to step into the first type assertion, you will end up at the following code in the Go runtime:
https://github.com/golang/go/blob/8d86ef2/src/runtime/iface.go#L438
If you step into the second one, you end up at:
https://github.com/golang/go/blob/8d86ef2/src/runtime/iface.go#L454
On line 438, you see func assertI2I (with a single return value). A bit lower, on line 454, you see assertI2I2. Note that these two functions have nearly identical names, but not quite!
The second function has a trailing 2 at the end of its name. That function also has two returned results.
As we expect:
assertI2I can panic, but
assertI2I2 cannot.
(Look at the function bodies in iface.go and note which contains panic.)
assertI2I and assertI2I2 abide by the overloading rules we expect. If they were to differ only by number of results, then those of us who compile Go from source would be unable to compile the Go runtime, due to a compiler error such as "assertI2I redeclared".
Users of the language are generally not aware of these builtin runtime functions, so on the surface, both lines of code seem to call the same function:
object_as_closer_hardstop := thing.(io.Closer) // will panic!!
object_as_closer, ok := thing.(io.Closer)
However, at compile time the compiler branches based on whether it found the case "commaok":
https://github.com/golang/go/blob/8d86ef2/src/cmd/compile/internal/gc/ssa.go#L4871
Our own end-user code does not get to modify Go's lexing/parsing/AST-walking in order to dispatch different flavors of our functions based on "commaok".
For better or for worse, that is why user-written code cannot leverage this pattern.

Expression result unused: strange behaviour of c++ compiler?

I accidentally typed the following code but my code successfully built and even ran properly.
std::string myString = "This is my string ";
std::shared_ptr<std::string> s = std::make_shared<std::string>(myString);
p->pushString(s);”accidental typo”;
It just showed a warning Expression result unused.
Why it is not a compiler or run time error?
I am using Xcode editor
Thanks
Why it is not a compiler [...] error?
Because it does not violate any rule of the C++ standard. If a program conforms to the standard then the compiler should allow its compilation. However, it was friendly enough to warn you that the expression is useless.
or run time error?
The expression doesn't result in any executed code, so it would be quite surprising if it resulted in a run time error.
You know that you can have arbitrary expressions as statements? That's how simple functions calls works, or assignments. In fact the statement
p->pushString(s);
is actually such an expression-statement. The p->pushString(s) part is an expression, it's the context (with the terminating semi-colon) that turns it into a statement.
That also means you can do something like
5;
Or in your case
"some string here";
Those are valid statements. They do however produce a result, which is (legally) discarded or ignored, but might cause the compiler to emit a warning about the ignored result.
It's really no different than e.g.
some_function_which_returns_a_result(); // Result ignored

What Rust construct uses nearbyint from libsystem_m?

I've profiled my program with Valgrind and Callgrind and found that most of the time is spent in the nearbyint$fenv_access_off function.
I've found that it's a LLVM intrinsic, but which Rust language construct uses it? How can I avoid it?
Doing a search for nearbyint finds the related symbols nearbyintf32 and nearbyintf64. These are documented as returning the nearest integer to a floating point value. However, there appears to be no calls to that specific function.
fenv_access_off appears to be an OS X specific aspect of the math library.
The other thing in your trace is round. I can believe that round could use nearbyint. I also don't see any cases of round in the standard library that seem like they would occur in a tight loop.
Beyond this, anything is pure guessing.
I've reproduced it with:
fn main() {
let data:Vec<_> = (0..999999).map(|x|{
(x as f64).powf(2.2).round() as u8
}).collect();
}
so it seems as u8 is implemented using nearbyint.
It's the same speed as C uchar = round(pow(i, 2.2)), so I'll have to replace it with a good'ol lookup table…

What does :: mean in Rust?

What does the :: syntax in Rust, as seen here, mean:
fn chunk(n: uint, idx: uint) -> uint {
let sh = uint::BITS - (SHIFT * (idx + 1));
(n >> sh) & MASK
}
In languages like Haskell it means a type hint, but here the compiler already has an annotation of that values type, so it seems it's likely type casting.
Please review Appendix B: Operators and Symbols of The Rust Programming Language.
In this case, the double colon (::) is the path separator. Paths are comprised of crates, modules, and items.
The full path for your example item, updated for 1.0 is:
std::usize::BITS
Here, std is the crate, usize is a module, and BITS is the specific item — in this case a constant.
If you scroll up in your file, you'll see use core::usize. use adds the path to the set of items to look in. That's how you can get away with just saying usize::BITS. The core crate is an implementation detail of the façade that is the std crate, so you can just substitute std for core in normal code.
:: can also be used as a way to specify generic types when they cannot otherwise be inferred; this is called the turbofish.
See also:
What is the syntax: `instance.method::<SomeThing>()`?
Oops. I wasn't reading very clearly. In this case, it's just the normal way of referring to anything under a module. uint::BITS is a constant, it seems.

Resources