profile
viewpoint
Eduard-Mihai Burtescu eddyb @LykenSol Bucharest, Romania Senior Compiler/PL Engineer

alexcrichton/rustc-demangle 77

Rust symbol demangling

Centril/rfc-effects 8

Preparing an RFC on effect polymorphism in Rust with focus on 'const'

eddyb/aoc 2

Advent of Code solutions in Rust

eddyb/bootstrap 2

HTML, CSS, and JS toolkit from Twitter

eddyb/hematite 2

A simple Minecraft written in Rust with the Piston game engine

eddyb/1ml 0

1ML prototype interpreter

eddyb/cargo 0

The Rust package manager

eddyb/clap-rs 0

A full featured, fast Command Line Argument Parser for Rust

Pull request review commentrust-lang/rust

#[track_caller] in traits

+// run-pass++#![feature(track_caller)]+#![allow(dead_code)]++trait Trait {+    #[track_caller] //~ WARN: `#[track_caller]` is ignored on function prototypes+    fn foo(&self);

It could be inherited by impls by default, for example.

anp

comment created time in 2 hours

Pull request review commentrust-lang/rust

#[track_caller] in traits

+// run-pass++#![feature(track_caller)]+#![allow(dead_code)]++trait Trait {+    #[track_caller] //~ WARN: `#[track_caller]` is ignored on function prototypes+    fn foo(&self);+}++extern "Rust" {+    #[track_caller] //~ WARN: `#[track_caller]` is ignored on function prototypes+    fn bar();

I think we'd want that to be an error (it should already be in general, e.g. if you're defining an extern "C" fn, i.e. exporting it).

anp

comment created time in 2 hours

issue commentrust-lang/rust

Tracking issue for RFC #2056: Allow trivial constraints to appear in where clauses

I think this would still compile/ignore the bound

If it doesn't error when compiling the function, it will error when trying to use it. It's not going to let you call the function without erroring.

aturon

comment created time in 6 hours

Pull request review commentrust-lang/rust

#[track_caller] in traits

+// run-pass++#![feature(track_caller)]+#![allow(dead_code)]++trait Trait {+    #[track_caller] //~ WARN: `#[track_caller]` is ignored on function prototypes+    fn foo(&self);

We might also want to error here if we want to reserve the right to add meaning to it?

anp

comment created time in 6 hours

Pull request review commentrust-lang/rust

#[track_caller] in traits

+// run-pass++#![feature(track_caller)]+#![allow(dead_code)]++trait Trait {+    #[track_caller] //~ WARN: `#[track_caller]` is ignored on function prototypes+    fn foo(&self);+}++extern "Rust" {+    #[track_caller] //~ WARN: `#[track_caller]` is ignored on function prototypes+    fn bar();

Btw we might want this to actually work and change the ABI to pass the caller!

anp

comment created time in 6 hours

pull request commentrust-lang/rust

#[track_caller] in traits

r? @nikomatsakis for the rubber-stamp

anp

comment created time in 6 hours

issue commentrust-lang/rust

Tracking issue for RFC 2091: Implicit caller location

the bug @eddyb mentioned in https://github.com/rust-lang/rust/issues/47809#issuecomment-583784847 has a proposed fix in #68965

No, it was brought up on #68965, but the fix is to track hygiene info cross-crate, which last I heard @Aaron1011 was working on.

aturon

comment created time in 6 hours

Pull request review commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

 #![crate_type = "rlib"] #![feature(thread_local)] -// CHECK: @STATIC_VAR_1 = thread_local local_unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4+// CHECK: @STATIC_VAR_1 = thread_local global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4 #[no_mangle] #[thread_local] static mut STATIC_VAR_1: [u32; 8] = [0; 8]; -// CHECK: @STATIC_VAR_2 = thread_local local_unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4+// CHECK: @STATIC_VAR_2 = thread_local global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4

The name and whether it's private should be decoupled.

I guess we have no notion of "private name" today, so my intuition was wrong about this being easy :disappointed:.

chrissimpkins

comment created time in 6 hours

pull request commentrust-lang/rust

Blacklist powerpc-unknown-linux-gnu as having non-ignored GNU C ZSTs.

r? @nikomatsakis or @pnkfelix

anyska

comment created time in 6 hours

pull request commentrust-lang/rust

perf: Only process changed obligations in ObligationForest

r? @nikomatsakis

Marwes

comment created time in 8 hours

pull request commentrust-lang/rust

#[track_caller] in traits

LGTM, as long as we want to do this.

anp

comment created time in 8 hours

Pull request review commentrust-lang/rust

Miscellaneous cleanup to formatting

 struct Void { #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] #[doc(hidden)] pub struct ArgumentV1<'a> {-    value: &'a Void,-    formatter: fn(&Void, &mut Formatter<'_>) -> Result,+    value: &'a Opaque,+    formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } -impl<'a> ArgumentV1<'a> {-    #[inline(never)]-    fn show_usize(x: &usize, f: &mut Formatter<'_>) -> Result {-        Display::fmt(x, f)-    }+// This gurantees a single stable value for the function pointer associated with+// indices/counts in the formatting infrastructure.+//+// Note that a function defined as such would not be correct as functions are+// always tagged unnamed_addr with the current lowering to LLVM IR, so their+// address is not considered important to LLVM and as such the as_usize cast+// could have been miscompiled. In practice, we never call as_usize on non-usize+// containing data (as a matter of static generation of the formatting+// arguments), so this is merely an additional check.+#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]+static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {};

Ah, I see what the argument is. Indeed, we shouldn't introduce non-determinism and USIZE_MARKER == USIZE_MARKER should always hold.

The funny thing though is that because you used |_, _| loop {}, anyone doing the same thing (loop {} in the body) could end up being collapsed to this (I don't think the signature matters, because usize is not passed by value).

Mark-Simulacrum

comment created time in 9 hours

Pull request review commentrust-lang/rust

Miscellaneous cleanup to formatting

 struct Void { #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] #[doc(hidden)] pub struct ArgumentV1<'a> {-    value: &'a Void,-    formatter: fn(&Void, &mut Formatter<'_>) -> Result,+    value: &'a Opaque,+    formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } -impl<'a> ArgumentV1<'a> {-    #[inline(never)]-    fn show_usize(x: &usize, f: &mut Formatter<'_>) -> Result {-        Display::fmt(x, f)-    }+// This gurantees a single stable value for the function pointer associated with+// indices/counts in the formatting infrastructure.+//+// Note that a function defined as such would not be correct as functions are+// always tagged unnamed_addr with the current lowering to LLVM IR, so their+// address is not considered important to LLVM and as such the as_usize cast+// could have been miscompiled. In practice, we never call as_usize on non-usize+// containing data (as a matter of static generation of the formatting+// arguments), so this is merely an additional check.+#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]+static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {};

I don't see how it's much more different from the previous approach. LLVM will replace loads from USIZE_MARKER with the fn pointer, which is still unnamed_addr.

Mark-Simulacrum

comment created time in 2 days

issue commentrust-lang/rust

Tracking issue for RFC #2056: Allow trivial constraints to appear in where clauses

@Luro02 What else do you generate? Does your proc macro use unsafe and would it do the wrong thing without that "doesn't implement Copy" error?

If so why not put the bound on some impl or fn that would misbehave?

That would actually protect it, unlike an unrelated and unused type definition.

(Alternatively, just use _AssertCopy somewhere in your unsafe code)

aturon

comment created time in 2 days

Pull request review commentrust-lang/rust

Allow trait methods to be called on concrete types in a const context

 impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {                     return;                 } +                // See if this is a trait method for a concrete type whose impl of that trait is+                // `const`.+                if self.tcx.features().const_trait_impl {+                    let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs);

As long as self.param_env is tcx.param_env(some_def_id) without calling .with_reveal_all() or w/e, it should be fine.

ecstatic-morse

comment created time in 3 days

Pull request review commentrust-lang/rust

Allow trait methods to be called on concrete types in a const context

 impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {                     return;                 } +                // See if this is a trait method for a concrete type whose impl of that trait is+                // `const`.+                if self.tcx.features().const_trait_impl {+                    let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs);+                    debug!("Resolving ({:?}) -> {:?}", def_id, instance);+                    if let Some(func) = instance {+                        if let InstanceDef::Item(def_id) = func.def {

This can't be affected by #69036 (which only affects the shims).

ecstatic-morse

comment created time in 3 days

pull request commentrust-lang/rust

Allow trait methods to be called on concrete types in a const context

This seems straight-forward and the use of Instance::resolve looks correct. However, I think you should make sure that the ParamEnv is UserFacing, not RevealAll, because you want maximally conservative behavior around specialization - similar to associated types in typeck.

cc @nikomatsakis

ecstatic-morse

comment created time in 3 days

pull request commentrust-lang/rust

Fix printing of `Yield` terminator

@bors r+

jonas-schievink

comment created time in 3 days

pull request commentrust-lang/rust

[WIP] Treat NodeIs as pure values for incremental compilation

@eddyb, do you remember these PRs - #56492 ("syntax: use MetaPath (a simpler version of Path) for Attribute and MetaItem"), #56480 (Use hir::Path instead of ast::Path in HIR Attribute's)?

Oh right, it's... been a while. I plan to eventually go over unfinished work like that as soon as it's possible, but things keep coming up and most of my plans end up in the trash. All I can do for the time being is apologize, I suppose.

HIR hashing can insert some kind of runtime panic for them.

I wanted to suggest panicking but I wasn't sure if we're expecting leftover NodeIds, thanks!

Zoxc

comment created time in 3 days

pull request commentrust-lang/rust

[WIP] Treat NodeIs as pure values for incremental compilation

cc @petrochenkov (sounds like the problem is interpolated Nonterminals?)

Zoxc

comment created time in 3 days

pull request commentrust-lang/rust

[WIP] Treat NodeIs as pure values for incremental compilation

Do we deal with NodeIds anymore though? Can we remove these impls?

Zoxc

comment created time in 3 days

issue commentrust-lang/rust

rustc segfaults when printing a backtrace for ICEs when debug=true is set

It would probably also be a good idea to investigate why 2.1 GB of debuginfo is getting generated - this seems really excessive.

You pretty much never want debug=true. For backtraces, all you need is debuginfo-level=1.

debug=true is for stepping rustc in a debugger and inspecting variables... which I'm not really aware of anyone doing (with perhaps the rare exception of a crash inside LLVM?)

Aaron1011

comment created time in 3 days

pull request commentrust-lang/rust

Use `ResultsCursor` for `elaborate_drops`

@bors r+

ecstatic-morse

comment created time in 3 days

issue commentrust-lang/rust

unused_unsafe: stop interpreting `unsafe fn`s as unsafe contexts

So looking at the code, it seems that the outermost active unsafe block (or unsafe fn) is used: https://github.com/rust-lang/rust/blob/dbef35309d10bed2f09cd55b3e9ea980a58c62aa/src/librustc_mir_build/build/block.rs#L212-L216

(NB: very confusing terminology around unpushed_unsafe, AFAICT it means "unsafe unrelated to {Push,Pop}Unsafe", and the latter is a hacky way to do allow_internal_unsafe, so we should rip it out sooner or later - but it shouldn't impact this issue, it's just confusing)

This are the possible values for Safety: https://github.com/rust-lang/rust/blob/dbef35309d10bed2f09cd55b3e9ea980a58c62aa/src/librustc/mir/mod.rs#L380-L388

So when the "current safety" is Safety::FnUnsafe, it early-returns, instead of replacing it with the inner Safety::ExplicitUnsafe.

By making this change, I think we can get the desired lint effect (while unsafe fn still allowing unsafe operations outside of unsafe blocks):

- Safety::Safe => {}
+ Safety::Safe | Safety::FnUnsafe => {}
Centril

comment created time in 3 days

Pull request review commentrust-lang/rust

Change const eval to just return the value

 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {                         err                     })             }-            _ => Ok(self.monomorphize(&constant.literal)),+            ty::ConstKind::Value(value) => Ok(value),+            _ => {+                let const_ = self.monomorphize(&constant.literal);+                if let ty::ConstKind::Value(value) = const_.val {+                    Ok(value)+                } else {+                    bug!("encountered bad ConstKind in codegen");

Also if at all possible, prefer span_bug! to bug!.

skinny121

comment created time in 3 days

issue commentrust-lang/rust

Semantics of MIR assignments, around aliasing, ordering, and primitives.

There are no Places in Operands -- as I (think I) said, that's just a Miri implementation detail.

To be clear, I meant "syntactically", in MIR, mir::Operand may contain a mir::Place, and I was talking about multiple mir::Places being involved in some operation (and therefore not being allowed to overlap) with at least one of them being from a mir::Operand. That is, to me mir::Operand as "terminology" implies being fully evaluatable to a value (not just in the mathematical sense of the spec, but also in real implementations) before whatever operation it's an operand of, is performed.

So to give a perhaps more explicit example, I would think that a borrow (mir::Rvalue::Ref) taking a mir::Operand would be nonsensical (and indeed we use a mir::Place).

That's probably less relevant given all the other stuff that has been discussed since, but I wanted to clarify that I wasn't talking about the dynamic semantics.

<hr/>

I think this is close to what you meant when you said "Rvalue is computing into the destination Place". Somehow I missed that before and just realized it right now when re-reading your posts. ... You seem to think that this "destination-passing style" solves the overlap problem, could you explain how? The evaluation of places and operands would still perform a particular sequence of memory operations in a particular order, there is no UB if any of these operations overlap.

Glad that proposal makes sense! (even if it's less necessary now that I grasp the overall picture better)

I agree there is a potential defined outcome of overlaps (after all, memmove exists). AFAIK, the main reason the memcpy/memmove distinction exists is a "forward loop" implementation will do the wrong thing for memcpy(p, p+x, n) if p..p+n overlaps with p+x..p+x+n, because at least one source byte will be destroyed by a write to the destination, replacing it with a (different) source byte. So memmove takes the penalty of a check + moving to a "reverse loop" implementation (which may also be less efficient, depending on the platform).

Something we could do is use memmove unless the mir::Places are "obviously disjoint", allowing the spec to omit the overlap rule (not that it would be a smart move to leave it out completely), but I think that would hurt writing non-primitives to &mut T pointers.

To answer your question more directly: even with destination-passing, if everything is defined in terms of "byte sequences", spec-wise something would probably have to say "destination can't overlap with any operands" or "first thing we do is write undef to the destination" (which can be just as well in Assign, without destination-passing into Rvalue. and also undef might not be strong enough to imply the UB of overlap, poison is more appropriate?).

<hr/>

I... think so. I am not entirely sure what your proposed lowering from "rustc MIR" to "spec MIR" is relative to the "overlap" rule, but I agree with your high-level statements and that is always a good start. :D

I was hoping to get that across with the example in https://github.com/rust-lang/rust/issues/68364#issuecomment-580142313, but here it is: "expand constructs (which don't want to take advantage of overlap), into multiple statements, mentioning at most one non-temporary mir::Place per statement, meaning the overlap rule doesn't kick in". In that example, all of the temporaries are SSA-like scalars, so codegen wouldn't be penalized even if it was working with the temporary-laden spec MIR.

eddyb

comment created time in 3 days

Pull request review commentrust-lang/rust

Change const eval to just return the value

 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {     pub(super) fn const_eval(         &self,         gid: GlobalId<'tcx>,+        ty: Ty<'tcx>,

It's pub(super), so only accessible inside the interpreter.

Ahh, sorry, sometimes I confuse that for "may be used in the implementation of a query", but that's really pub(crate) because the CTFE queries are in the rustc_mir::const_eval module, right?

skinny121

comment created time in 3 days

Pull request review commentrust-lang/rust

Change const eval to just return the value

 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {     pub(super) fn const_eval(         &self,         gid: GlobalId<'tcx>,+        ty: Ty<'tcx>,

Miri doesn't care about lifetimes though.

The caller does. Or is const_eval an internal API? (It's sometimes hard to tell on GitHub).

But here we just believe the type the caller tells us.

If this is not internal, and this matters, we could assert that the type is identical after erasing the one that might have lifetimes.

If it is internal, then yeah, using whatever lifetime-erased type can be computed from GlobalId would be fine.

skinny121

comment created time in 3 days

Pull request review commentrust-lang/rust

Change const eval to just return the value

 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {     pub(super) fn const_eval(         &self,         gid: GlobalId<'tcx>,+        ty: Ty<'tcx>,

This makes me think it would be nice to provide a "lifetime substitution" instead of the full type (and compute the non-lifetime parts from GlobalId), but that might need a lot more infrastructure than this PR (in general we might want lifetimes slots to be placeholders for e.g. MIR borrowck to work with).

cc @nikomatsakis (who I'm sure has had this idea before)

skinny121

comment created time in 3 days

Pull request review commentrust-lang/rust

Change const eval to just return the value

 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {     pub(super) fn const_eval(         &self,         gid: GlobalId<'tcx>,+        ty: Ty<'tcx>,

This is pretty much down to lifetime parametricity/polymorphism. Basically the entire type is determinable except lifetimes.

And because lifetimes shouldn't affect const-evaluation, and to maximize caching, we want to erase them, but we also don't want the lifetime-erased type to leak back into e.g. typeck.

skinny121

comment created time in 3 days

Pull request review commentrust-lang/rust

Change const eval to just return the value

 impl<'tcx> ConstValue<'tcx> {             ConstValue::Scalar(val) => Some(val),         }     }++    pub fn try_to_bits(&self, size: Size) -> Option<u128> {+        self.try_to_scalar()?.to_bits(size).ok()+    }++    pub fn try_to_bits_for_ty(+        &self,+        tcx: TyCtxt<'tcx>,+        param_env: ParamEnv<'tcx>,+        ty: Ty<'tcx>,+    ) -> Option<u128> {+        let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;

Lately I've had to say almost the exact opposite (because some misunderstanding around Reveal::All's ability to cope with polymorphic situations: modulo bugs, it should always work), so I'm not sure what the context was for what you're thinking of.

Note that layout_of, IIRC, uses with_reveal_all internally, so if this does anything, it avoids extra queries.

skinny121

comment created time in 3 days

issue commentrust-lang/rust

Rustc overflow its stack when using impl Trait and the struct containing the function itself

Godbolt says this regressed in 1.30.0 and used to compile fine in 1.29.0.

Just checked, this is what that looks like: https://godbolt.org/z/vc3D35

PSA: seeing <No assembly generated> in godbolt is a big warning sign. It means you're accidentally not testing anything (at least codegen-wise).

Making main pub fn on 1.29.0 (keep in mind, godbolt always compiles a lib crate, not a bin one) results in this: https://godbolt.org/z/icX4pU (thread 'main' has overflowed its stack).

And it's the same on 1.26.0 (first stable w/ -> impl Trait): https://godbolt.org/z/WyuNsB.

This fits with https://github.com/rust-lang/rust/issues/69096#issuecomment-585965841, and I wish godbolt had nightly versions matching stable ones, or at least a way to pass env vars (because there's no real protection against abusing stable compilers).

lszxb

comment created time in 3 days

pull request commentrust-lang/rust

O(log n) lookup of associated items by name

AFAICT, the current machinery does not support this.

this seems like something we could O(n) process in lang item collection and store HirIds or indices (whatever identified an associated item, I forget) like that for.

Don't understand this point. Associated items are identified by DefIds like everything else, and I'm pretty sure you can just stick #[lang_item = "..."] on a trait or impl method or associated type etc. (if not that's a bug in the lang item collector.

Doing all that is much easier than this PR (it's just adding a few attributes here and there, and entries in the list of lang items), which is why I suggested doing it first.

ecstatic-morse

comment created time in 3 days

Pull request review commentrust-lang/rust

Change const eval to just return the value

 fn collect_const<'tcx>(         _ => {}     } }++fn collect_const_value<'tcx>(+    tcx: TyCtxt<'tcx>,+    value: ConstValue<'tcx>,+    output: &mut Vec<MonoItem<'tcx>>,+) {+    match value {+        ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output),+        ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {+            for &((), id) in alloc.relocations().values() {+                collect_miri(tcx, id, output);

Unrelated, but collect_miri should probably be called collect_miri_alloc.

skinny121

comment created time in 3 days

Pull request review commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

 #![crate_type = "rlib"] #![feature(thread_local)] -// CHECK: @STATIC_VAR_1 = thread_local local_unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4+// CHECK: @STATIC_VAR_1 = thread_local global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4 #[no_mangle] #[thread_local] static mut STATIC_VAR_1: [u32; 8] = [0; 8]; -// CHECK: @STATIC_VAR_2 = thread_local local_unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4+// CHECK: @STATIC_VAR_2 = thread_local global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4

That's a problem, we need to be able to provide a name and still keep it private.

chrissimpkins

comment created time in 3 days

Pull request review commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

 // CHECK: @STATIC = {{.*}}, align 4  // This checks the constants from inline_enum_const-// CHECK: @{{[0-9]+}} = {{.*}}, align 2+// CHECK: @alloc{{[0-9]+\.[0-9]+}} = {{.*}} zeroinitializer, align 2

I think we should hardcode the @alloc number if it's deterministic (usually the case if it's small like 1 or 2.

chrissimpkins

comment created time in 3 days

Pull request review commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

 impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {                     Some(GlobalAlloc::Memory(alloc)) => {                         let init = const_alloc_to_llvm(self, alloc);                         if alloc.mutability == Mutability::Mut {-                            self.static_addr_of_mut(init, alloc.align, None)+                            self.static_addr_of_mut(+                                init,+                                alloc.align,+                                Some(format!("{:?}", ptr.alloc_id).as_str()),+                            )                         } else {-                            self.static_addr_of(init, alloc.align, None)+                            self.static_addr_of(+                                init,+                                alloc.align,+                                Some(format!("{:?}", ptr.alloc_id).as_str()),

In the back&forth it looks like you lost the deduplication here, which my primary concern. Having two copies of this line makes it harder to discuss and/or change the logic.

chrissimpkins

comment created time in 3 days

pull request commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

static_addr_of making the fewer_names check shouldn't be relied upon. It's not free to generate that string, so we should avoid it.

chrissimpkins

comment created time in 3 days

pull request commentrust-lang/rust

simplify_try: address some of eddyb's comments

@bors r+

Centril

comment created time in 4 days

Pull request review commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

 #![crate_type = "rlib"] #![feature(thread_local)] -// CHECK: @STATIC_VAR_1 = thread_local local_unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4+// CHECK: @STATIC_VAR_1 = thread_local global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4 #[no_mangle] #[thread_local] static mut STATIC_VAR_1: [u32; 8] = [0; 8]; -// CHECK: @STATIC_VAR_2 = thread_local local_unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4+// CHECK: @STATIC_VAR_2 = thread_local global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4

But also this is thread-local? I am confused.

chrissimpkins

comment created time in 4 days

Pull request review commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

 #![crate_type = "rlib"] #![feature(thread_local)] -// CHECK: @STATIC_VAR_1 = thread_local local_unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4+// CHECK: @STATIC_VAR_1 = thread_local global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4 #[no_mangle] #[thread_local] static mut STATIC_VAR_1: [u32; 8] = [0; 8]; -// CHECK: @STATIC_VAR_2 = thread_local local_unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4+// CHECK: @STATIC_VAR_2 = thread_local global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4

Uh oh we're losing local_unnamed_addr, that's bad isn't it? I guess we need to do an audit of static_addr_of(_mut) uses.

chrissimpkins

comment created time in 4 days

Pull request review commentrust-lang/rust

Add support for LLVM globals corresponding to miri allocations should be named alloc123

 impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {                     Some(GlobalAlloc::Memory(alloc)) => {                         let init = const_alloc_to_llvm(self, alloc);                         if alloc.mutability == Mutability::Mut {-                            self.static_addr_of_mut(init, alloc.align, None)+                            self.static_addr_of_mut(+                                init,+                                alloc.align,+                                Some(&ptr.alloc_id.to_string()),

You should compute this only once for both arms, to avoid duplication.

Also, judging from the output, it should be format!("alloc{}", ptr.alloc_id) because it doesn't look like to_string adds that prefix (the test should say @alloc1 not @1).

Oh and to limit this to situations where we see the IR at all, you need to only have the name be Some when self.sess().opts.fewer_names is false or something like that.

cc @oli-obk @bjorn3 Can we also make sure static_addr_of(_mut) with a None last argument doesn't set any name? Oh and the methods themselves aren't great, they should be something like global(_mut)_from_value and to avoid a LLVM-ism it should be changed to take a miri alloc and do const_alloc_to_llvm internally (with e.g. Cranelift you just encode the miri alloc directly, bytes+relocations are linker-friendly).

chrissimpkins

comment created time in 4 days

issue commentrust-lang/rust

Re-evaluate `Hash{Set,Map}` vs `FxHash{Set,Map}` once #69152 lands

Didn't we also use a custom hasher to bypass randomness? If we rely on hashbrown we must make sure its compile-time randomness is disabled.

nnethercote

comment created time in 4 days

pull request commentrust-lang/rust

Always const qualify literals by type

r=me with or without any comment changes.

matthewjasper

comment created time in 5 days

Pull request review commentrust-lang/rust

Always const qualify literals by type

 pub trait Qualif {             }              Operand::Constant(ref constant) => {-                if constant.check_static_ptr(cx.tcx).is_some() {-                    // `mir_const_qualif` does return the qualifs in the final value of a `static`,-                    // so we could use value-based qualification here, but we shouldn't do this-                    // without a good reason.-                    //-                    // Note: this uses `constant.literal.ty` which is a reference or pointer to the-                    // type of the actual `static` item.-                    Self::in_any_value_of_ty(cx, constant.literal.ty)-                } else if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val-                {+                // Check the qualifs of the value of `const` items.+                if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {                     assert!(promoted.is_none());                     // Don't peek inside trait associated constants.-                    if cx.tcx.trait_of_item(def_id).is_some() {-                        Self::in_any_value_of_ty(cx, constant.literal.ty)-                    } else {+                    if cx.tcx.trait_of_item(def_id).is_none() {                         let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id);-                        let qualif = Self::in_qualifs(&qualifs);+                        if !Self::in_qualifs(&qualifs) {+                            return false;+                        }                          // Just in case the type is more specific than                         // the definition, e.g., impl associated const                         // with type parameters, take it into account.-                        qualif && Self::in_any_value_of_ty(cx, constant.literal.ty)                     }-                } else {-                    false                 }+                // Otherwise use the qualifs of the type.+                //+                // We could use value-based qualification if this is a+                // pointer to a static, but we shouldn't do that without a+                // good reason.+                //+                // Note: If this is a pointer to a static, this uses+                // `constant.literal.ty` which is a reference or pointer to+                // the type of the actual static item.

This is technically correct, but also sounds somewhat tautological. Since it's a reference/pointer, it should be treated like one, no need to special-case statics.

In fact I doubt borrow-checking even needs to know about these, it's just a matter of tweaking the messaging.

matthewjasper

comment created time in 5 days

issue commentrust-lang/rust

Rustc overflow its stack when using impl Trait and the struct containing the function itself

@Centril Any chance you forgot to add pub? godbolt is always in library mode IIRC so there might not be enough codegen to reach the infinite recursion (and maybe we changed the rules when some things are codegen'd, especially around impl Trait)

lszxb

comment created time in 5 days

issue commentrust-lang/cargo-bisect-rustc

Cargo emits "error: Unrecognized option: 'json'" error beginning ~ 07/2019, consider elimination of cargo from bisect testing

Specifically in this case, the testcase is just one file and should reproduce with just rustc, I think we should have the option to bisect rustc directly without Cargo.

chrissimpkins

comment created time in 5 days

issue commentrust-lang/rust

Rustc overflow its stack when using impl Trait and the struct containing the function itself

I am seeing an error: Unrecognized option: 'json' error before that date but no stack overflow.

That suggests that you're using a Cargo too new or somehow back-compat logic was removed (or never present?) in Cargo (not sure what our policy is).

You need an older Cargo to go back past the addition of --json.

But also it would be nice if Cargo didn't need to be involved in the bisection process, because it IMO unnecessarily complicates it.

lszxb

comment created time in 5 days

issue openedrust-lang/rust

LLVM globals corresponding to miri allocations should be named alloc123.

That is, if -Zfewer-names is false (usually only because of --emit=llvm-ir), we should use the same name for LLVM globals we generate out of miri allocs as #67133 does in MIR output (allocN).

This way, we can easily see the mapping between MIR and LLVM IR (and it shouldn't be any costlier for regular compilation, which would continue to use unnamed globals).

Relevant code (btw this could probably use extra caching keyed on AllocId?): https://github.com/rust-lang/rust/blob/be493fe8cc40c3d3f6030a1313c1ff747fce770d/src/librustc_codegen_llvm/common.rs#L260-L267

cc @rust-lang/wg-mir-opt @bjorn3

created time in 5 days

issue commentrust-lang/rust

Rustc overflow its stack when using impl Trait and the struct containing the function itself

Looks like this is in rustc::ty::print::obsolete::DefPathBasedNames, which we want to get rid of anyway, I'm not surprised it's buggy.

More specifically, it looks like it's crashing while trying to generate a name for a LLVM type.

cc @rust-lang/wg-codegen Should we make LLVM type names respect -Zfewer-names? (which defaults to true unless --emit=llvm-ir is used)

lszxb

comment created time in 5 days

issue commentrust-lang/rust

Static lifetimes checking regression in rustc 1.41.0

I expected the behavior to match that of this example (which still errors):

fn foo(p: *mut &'static u8) {
    let n = 42;
    unsafe {
        *p = &n;
    }
}

I wonder if the 'static gets erased somehow. Maybe an "user type annotation" is required on the *mut T from a static mut FOO: T, to give it a lifetime'd type?

ilyavenner

comment created time in 5 days

issue commentrust-lang/rust

ICE in incr comp after s/trait/struct/: src/librustc/dep_graph/graph.rs:688: DepNode Hir(...) should have been pre-allocated but wasn't.

local item

Nitpick: ItemLocalId is meant to mean "item-local (node) ID", maybe something like IntraOwnerId would be better at describing this but unsure.

DefId and HIR owners matching is something I want in the medium-term but I'm unsure how long it would take to get there.

ProgVal

comment created time in 6 days

issue commentrust-lang/rust

non-deterministic syn-opt run

It might be a combination. LLVM is known to have trouble maintaining deterministic performance, in a similar vein to rustc hashing pointers, but potentially even affecting output for LLVM optimziations.

I highly advise disabling at least userspace ASLR, and manually check (by dumping /proc/self/maps from rustc? or even interned e.g. Ty pointers) that the heap addresses match between two runs, even with a slightly different rustc. There's also the question of randomness sensitivity, but I suspect we don't want that even in real builds.

IIRC @emberian managed to get the nondeterminism down to a bimodal (i.e. two possible profiles) situation for "irsy" (Is Rust Slim Yet), back in the day. It's a bit of a shame that the "irsy" lessons were lost in time.

Mark-Simulacrum

comment created time in 6 days

Pull request review commentrust-lang/rust

rustc_codegen_llvm: don't generate any type debuginfo for -Cdebuginfo=1.

 const DW_TAG_arg_variable: c_uint = 0x101;  /// A context object for maintaining all state needed by the debuginfo module. pub struct CrateDebugContext<'a, 'tcx> {+    // FIXME(eddyb) we need this?! at all?!

Okay I was a bit confused about DIBuilder so I took another look at it and I can kind of see what you mean.

I would definitely want to rename CrateDebugContext to DIBuilder or LlvmDbgBuilder or something like that if we want it to be disjoint from CodegenCx, I'm still worrying a bit about duplication I guess.

eddyb

comment created time in 6 days

Pull request review commentrust-lang/rust

rustc_codegen_llvm: don't generate any type debuginfo for -Cdebuginfo=1.

 const DW_TAG_arg_variable: c_uint = 0x101;  /// A context object for maintaining all state needed by the debuginfo module. pub struct CrateDebugContext<'a, 'tcx> {+    // FIXME(eddyb) we need this?! at all?!

That doesn't really work for LLVM though... I think CrateDebugContext is a misleading name and it should be called DebugData or DebugBuilder.

The only way this would make sense to me is if there was an entirely different rustc_codegen_debuginfo crate with abstractions separate from rustc_codegen_ssa (but which the latter used, because it's needed for using locations and variables in a function).

But even then... they still feel too coupled.

eddyb

comment created time in 6 days

pull request commentrust-lang/rust

rustc_codegen_llvm: don't generate any type debuginfo for -Cdebuginfo=1.

I want to be careful with merging this so we don't run into a problem like #60020.

Definitely, I don't think this PR is ready (and I might have to postpone working on it for a week), there's also that last commit which I added as a placeholder, there's https://github.com/rust-lang/rust/issues/69074#issuecomment-585140625 etc.

eddyb

comment created time in 6 days

Pull request review commentrust-lang/rust

rustc_codegen_llvm: don't generate any type debuginfo for -Cdebuginfo=1.

 impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {                     // so avoid methods on other types (e.g., `<*mut T>::null`).                     match impl_self_ty.kind {                         ty::Adt(def, ..) if !def.is_box() => {-                            Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))+                            // Again, only create type information if full debuginfo is enabled

The comment is verbatim copy-pasted from a few lines up, which also has the verbatim condition if cx.sess().opts.debuginfo == DebugInfo::Full.

eddyb

comment created time in 6 days

Pull request review commentrust-lang/rust

rustc_codegen_llvm: don't generate any type debuginfo for -Cdebuginfo=1.

 const DW_TAG_arg_variable: c_uint = 0x101;  /// A context object for maintaining all state needed by the debuginfo module. pub struct CrateDebugContext<'a, 'tcx> {+    // FIXME(eddyb) we need this?! at all?!

CodegenCx is no longer passed to all debuginfo functions

I don't see how that can work, it should still involve CodegenCx one way or another, and most of this debuginfo state should live in it.

eddyb

comment created time in 6 days

issue commentrust-lang/rust

-Cdebuginfo=1 wastefully produces full type descriptions.

That would reduce the quality of ICE backtraces reported by the average user.

Right now we have no debuginfo at all AFAIK, but if there was an optional component we could tell people to install it. Or maybe we could take the backtrace they report, and the version, and generate the full backtrace ourselves using the right debuginfo (since all you need is addresses, right?).

eddyb

comment created time in 6 days

pull request commentrust-lang/rust

Micro-optimize the heck out of LEB128 reading and writing.

while these read and write methods only handle a single LEB128 int per call

May not be relevant, but the serialized data is basically a sequence of LEB128s (perhaps intermixed with strings), they just semantically represent more hierarchical values than an UTF-8 stream.

nnethercote

comment created time in 6 days

pull request commentrust-lang/rust

Micro-optimize the heck out of LEB128 reading and writing.

@nnethercote If you're bored, I wonder how this implementation compares to the pre-#59820 one in libproc_macro (which I implemented from scratch in safe code).

It definitely feels like your new version here is close to mine, but without checking I can't tell which one LLVM will prefer (or if they compile all the same).

nnethercote

comment created time in 6 days

Pull request review commentrust-lang/rust

Micro-optimize the heck out of LEB128 reading and writing.

 macro_rules! impl_read_unsigned_leb128 {     ($fn_name:ident, $int_ty:ident) => {         #[inline]         pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {-            let mut result: $int_ty = 0;+            let mut result = 0;             let mut shift = 0;             let mut position = 0;--            for _ in 0..leb128_size!($int_ty) {-                let byte = unsafe { *slice.get_unchecked(position) };+            loop {+                let byte = slice[position];                 position += 1;-                result |= ((byte & 0x7F) as $int_ty) << shift;                 if (byte & 0x80) == 0 {-                    break;+                    result |= (byte as $int_ty) << shift;+                    return (result, position);+                } else {+                    result |= ((byte & 0x7F) as $int_ty) << shift;

Preexisting, but I think the style we use is more 0x7f (lowercase hex).

nnethercote

comment created time in 6 days

pull request commentrust-lang/rust

`O(log n)` lookup of associated items by name

Ideally, this would be implemented using an insertion-order preserving, hash-based multi-map, but one is not readily available.

It's not a multi-map, but IndexMap<K, V> is insertion-order preserving and I think we should use it more (see #60608).

ecstatic-morse

comment created time in 6 days

pull request commentrust-lang/rust

rustc_codegen_ssa: only "spill" SSA-like values to the stack for debuginfo.

FWIW, this is the comparison for the actual merged build (dc4242d9052a42cdf329c3a2430d02a3b3d415cb...b6690a8c35e9afa3e0f65140cc69d4ba1b9e78c4).

Doesn't really look any different from the PR run, which is nice. I need to use these to do a debug-mode lolbench run, but it might be tricky. The goal is to show that runtime performance in debug mode improved (while staying debuggable).

eddyb

comment created time in 6 days

pull request commentrust-lang/rust

Properly use the darwin archive format on Apple targets

@bors r+

cc @alexcrichton @rust-lang/wg-codegen

nox

comment created time in 6 days

issue commentrust-lang/rust

-Cdebuginfo=1 wastefully produces full type descriptions.

Ah, weird, it looked like it's been like this forever, thankfully godbolt has all stable version.

In that issue you suggest we should not even be emitting DISubprogram, will that still let inlined calls show up on the backtrace? I guess I can cause an ICE on purpose to find out.

It would be good to remove even more than #69080 does right now, because then we might stand a chance to ship debuginfo.

Of course the ideal thing would be split DWARF and a rustc-debuginfo component in rustup but I am not sure how to get there.

eddyb

comment created time in 6 days

issue commentrust-lang/rust

Formatting code is in conflict with unnamed_addr

I mean, I did consider that, but do you want to take the hit of 16 extra bytes on the stack even when not needed?

However, if we do that thing we've talked about, where the fn pointers are in 'static' memory while the references to the runtime data are separate, we would have to wrap accesses to the runtime data instead of having a safe &[fmt::ArgumentV1], so the runtime data could be a bunch of usizes followed by references, and the only cost would be the count of counts (ugh) in 'static memory.

RalfJung

comment created time in 7 days

Pull request review commentrust-lang/rust

rustc: don't resolve Instances which would produce malformed shims.

 pub enum InstanceDef<'tcx> {     },      /// `drop_in_place::<T>; None` for empty drop glue.+    ///+    /// NB: the type must be monomorphic for MIR shims to work.+    // FIXME(eddyb) support generating shims for a "shallow type",+    // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic+    // `Foo<Bar>` or `[String]` etc.     DropGlue(DefId, Option<Ty<'tcx>>),      ///`<T as Clone>::clone` shim.+    ///+    /// NB: the type must be monomorphic for MIR shims to work.

I don't think we should treat monomorphic codegen as "a fact of life" in rustc, since it easily leads to soundness holes (Instance::resolve until recently was wrong about specialization, for example).

Instead, we should assume that everything is as absurdly polymorphic as possible, and restrict it only when it's unworkable.

You're right that the comments on the variants are useless though.

Note that the comments are intended for creators of the variants, not consumers. Anyone can theoretically make an Instance out of thin air, and I need to figure out a good way to document the fact that generic parameters are not supported.

And they're not supported because... they would have to be substitutable away by the Substs in Instance, which are for the definition of the shimmed thing (e.g. clone method of trait Clone, so the only available parameter would be Self, which ironically is the type itself).

But the symptom would be that the MIR body of the shim would be malformed, since it would likely refer to type parameters that don't even fit the Substs.

Overall this is annoying to explain and I just wish it was easier to implement the "correct thing" where the shims are never monomorphic (except for user ADTs with no generics).

eddyb

comment created time in 7 days

Pull request review commentrust-lang/rust

rustc: don't resolve Instances which would produce malformed shims.

 fn resolve_associated_item<'tcx>(                 trait_closure_kind,             ))         }-        traits::VtableFnPointer(ref data) => Some(Instance {-            def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),-            substs: rcvr_substs,-        }),+        traits::VtableFnPointer(ref data) => {+            // `FnPtrShim` requires a monomorphic aka concrete type.+            if data.fn_ty.needs_subst() {+                return None;+            }++            Some(Instance {+                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),+                substs: rcvr_substs,+            })+        }         traits::VtableObject(ref data) => {             let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);             Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })         }         traits::VtableBuiltin(..) => {-            if tcx.lang_items().clone_trait().is_some() {-                Some(Instance {-                    def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),-                    substs: rcvr_substs,-                })+            if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {

There isn't a bug really, but previously it pretended clone_from was a shim but reusing the mir::Body of the trait default method, which made reasoning about clone itself harder. I should probably make it its own commit?

eddyb

comment created time in 7 days

issue commentrust-lang/rust

Formatting code is in conflict with unnamed_addr

@Mark-Simulacrum The problem with that is that the &[core::fmt::rt::v1::Argument] is really a &'static [_] from promotion (and used to be an explicit static), IIUC, so now you'd have a lot of stuff on the stack instead.

RalfJung

comment created time in 7 days

PR opened rust-lang/rust

rustc_codegen_llvm: don't generate any type debuginfo for -Cdebuginfo=1.

Fixes #69074 by adding more checks for DebugInfo::Full in a few places in rustc_codegen_llvm, bringing us in line with what clang -g1 generates (no debuginfo types, nor debuginfo for statics).

TODO: finish the last commit (i.e. ensure the compiler never emits type debuginfo at -Cdebuginfo=1, but instead ICEs).

<hr/>

My local build's (debuginfo-level=1, debug-assertions=1) librustc_driver-*.so went from just over 1GiB (1019MiB) down to 402MiB.

It's still bad, but the .debug_* sections themselves (as reported by objdump) went from something like 853MiB down to 236MiB, i.e. roughly a 3.6x reduction.

<hr/>

Sadly, I don't think this is enough to justify shipping all of this debuginfo, but now it's more plausible that we could at least build with debuginfo-level=1 then strip it. That would give us real backtraces for e.g. ICEs during builds, but I don't know how often that's relevant.

There's also the possibility of making it slimmer by omitting parameters to functions, or perhaps some deduplication (I think right now there is no DWARF reuse across CGUs? maybe ThinLTO helps?).

r? @michaelwoerister cc @rust-lang/wg-codegen @alexcrichton @Mark-Simulacrum

+37 -7

0 comment

4 changed files

pr created time in 7 days

create barncheddyb/rust

branch : one-billion-dwarves-walk-into-a-bar

created branch time in 7 days

issue commentrust-lang/rust

Formatting code is in conflict with unnamed_addr

I have no idea how this works, but this:

println!("{0:#0$x}", 20)

prints:

                0x14
RalfJung

comment created time in 7 days

issue commentrust-lang/rust

Formatting code is in conflict with unnamed_addr

@Mark-Simulacrum Sorry, no, I mean that the usize argument can also be used for as a regular argument, which is why show_usize's body is Display::fmt(x, f).

RalfJung

comment created time in 7 days

Pull request review commentrust-lang/rust

Document unsafe blocks in core::fmt

 impl<'a> ArgumentV1<'a> {      fn as_usize(&self) -> Option<usize> {         if self.formatter as usize == ArgumentV1::show_usize as usize {+            // SAFETY: if the formatter is `show_usize`, it means it came in as `&usize`

That means it should be display_usize today.

foeb

comment created time in 7 days

Pull request review commentrust-lang/rust

Document unsafe blocks in core::fmt

 impl<'a> ArgumentV1<'a> {     #[doc(hidden)]     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]     pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {+        // SAFETY: `mem::transmute(x)` is safe because+        //     1. `&'b T` is transmuted to have an explicit lifetime `'b`+        //              (so as to not have an unbounded lifetime)+        //     2. `&'b T` and `&'b Void` have the same memory layout+        //              (as long as `T` is `Sized`)+        // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`+        // and `fn(&Void, &mut Formatter<'_>) -> Result` have the same ABI+        // (as long as `T` is `Sized`)

It's not a uninhabited type -- it's a ZST.

Okay so we fixed that, not as scary as it used to be. The name is very wrong though, it should be Opaque or something similar. Void should be reserved for empty enums.

foeb

comment created time in 7 days

issue commentrust-lang/rust

Formatting code is in conflict with unnamed_addr

I am not sure if the same argument can be both a width and a formatting argument.

I think that's true though, which is why I went with the show_usize hack.

RalfJung

comment created time in 7 days

issue commentrust-lang/rust

-Cdebuginfo=1 wastefully produces full type descriptions.

More examples (using enum Foo from above):

pub static FOO: Option<Foo> = None;
pub fn foo() -> &'static dyn Sync {
    &None::<Foo>
}

However, clang generates no debuginfo for this at -g1 (see godbolt output):

struct {
    int should_not_be_in_debug_info;
} foo;

I think we should follow clang -g1's example for rustc -Cdebuginfo=1.

eddyb

comment created time in 7 days

issue commentservo/servo

macOS ld considers libscript-*.rlib to be invalid

@nox What does clang do? DARWIN or BSD?

CYBAI

comment created time in 7 days

pull request commentrust-lang/rust

Suggestion when encountering assoc types from hrtb

cc @nikomatsakis @pnkfelix

estebank

comment created time in 7 days

issue openedrust-lang/rust

-Cdebuginfo=1 wastefully produces full type descriptions.

This example makes -Cdebuginfo=1 emit the variant (see godbolt output):

pub enum Foo {
    ThisShouldNotBeInDebugInfo([u8; 1337])
}

impl Foo {
    pub fn foo() {}
}

Its resulting LLVM IR shows all of these DebugInfo metadata nodes:

!6 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !8, file: !7, size: 10696, align: 8, elements: !{!10}, identifier: "65d4d9f1044eb0325dc66254af8523df")
!10 = !DICompositeType(tag: DW_TAG_variant_part, scope: !8, file: !7, size: 10696, align: 8, elements: !{!12}, templateParams: !4, identifier: "65d4d9f1044eb0325dc66254af8523df_variant_part")
!12 = !DIDerivedType(tag: DW_TAG_member, name: "ThisShouldNotBeInDebugInfo", scope: !10, file: !7, baseType: !13, size: 10696, align: 8)
!13 = !DICompositeType(tag: DW_TAG_structure_type, name: "ThisShouldNotBeInDebugInfo", scope: !6, file: !7, size: 10696, align: 8, elements: !{!15}, templateParams: !4, identifier: "65d4d9f1044eb0325dc66254af8523df::ThisShouldNotBeInDebugInfo")
!15 = !DIDerivedType(tag: DW_TAG_member, name: "__0", scope: !13, file: !7, baseType: !16, size: 10696, align: 8)
!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !17, size: 10696, align: 8, elements: !{!19})
!17 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
!19 = !DISubrange(count: 1337)

But at -Cdebuginfo=1, this is really what we want to see:

!6 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !8, file: !7)

If this doesn't work we can always just use DINamespace instead.

<hr/>

IIUC, this specific example is caused from the way we handle inherent impls, but there might be others, so we probably want to make the debuginfo generating infrastructure ICE when it's trying to generate non-trivial type debuginfo but -Cdebuginfo=1 is set.

Oh, and, I found this because librustc_driver-*.so is 1GB with debuginfo-level=1 (and debug-assertions=1) in config.toml, and most of that is type debuginfo.

cc @rust-lang/compiler @alexcrichton

created time in 7 days

Pull request review commentrust-lang/rust

Deduplicate pretty printing of constants

 pub trait PrettyPrinter<'tcx>:                     p!(write("{}{}", data, ui_str))                 };             }-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {-                let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128;+            (Scalar::Raw { data, .. }, ty::Int(i)) => {+                let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size();+                let bit_size = size.bits() as u128;                 let min = 1u128 << (bit_size - 1);                 let max = min - 1; -                let ty = self.tcx().lift(&ty).unwrap();-                let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;                 let i_str = i.name_str();                 match data {                     d if d == min => p!(write("std::{}::MIN", i_str)),                     d if d == max => p!(write("std::{}::MAX", i_str)),                     _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)),                 }             }-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => {-                p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()))+            // Char+            (Scalar::Raw { data, .. }, ty::Char) => match ::std::char::from_u32(data as u32) {+                Some(c) => p!(write("{:?}", c)),+                None => p!(write("{}_char", data)),+            },+            // Raw pointers+            (Scalar::Raw { data, .. }, ty::RawPtr(_)) => {+                p!(write("{{0x{:x} as ", data), print(ty), write("}}"))             }-            (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")),-            (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => {+            (Scalar::Ptr(ptr), ty::FnPtr(_)) => {                 let instance = {                     let alloc_map = self.tcx().alloc_map.lock();                     alloc_map.unwrap_fn(ptr.alloc_id)                 };                 p!(print_value_path(instance.def_id(), instance.substs));             }-            _ => {-                let printed = if let ty::Ref(_, ref_ty, _) = ty.kind {-                    let byte_str = match (ct, &ref_ty.kind) {-                        (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {-                            let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());-                            Some(-                                self.tcx()-                                    .alloc_map-                                    .lock()-                                    .unwrap_memory(ptr.alloc_id)-                                    .get_bytes(&self.tcx(), ptr, Size::from_bytes(n))-                                    .unwrap(),-                            )-                        }-                        (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {-                            // The `inspect` here is okay since we checked the bounds, and there are-                            // no relocations (we have an active slice reference here). We don't use-                            // this result to affect interpreter execution.-                            Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))-                        }-                        _ => None,-                    };--                    if let Some(byte_str) = byte_str {-                        p!(write("b\""));-                        for &c in byte_str {-                            for e in std::ascii::escape_default(c) {-                                self.write_char(e as char)?;-                            }-                        }-                        p!(write("\""));-                        true-                    } else if let (ConstValue::Slice { data, start, end }, ty::Str) =-                        (ct, &ref_ty.kind)-                    {-                        // The `inspect` here is okay since we checked the bounds, and there are no-                        // relocations (we have an active `str` reference here). We don't use this-                        // result to affect interpreter execution.-                        let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);-                        let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");-                        p!(write("{:?}", s));-                        true-                    } else {-                        false-                    }+            // For zsts just print their type as their value gives no extra information+            (Scalar::Raw { size: 0, .. }, _) => p!(print(ty)),

It only works with tuples if all the leaves are () or unit structs, I'd rather this went into a general recursive algorithm.

oli-obk

comment created time in 7 days

Pull request review commentrust-lang/rust

Deduplicate pretty printing of constants

 pub trait PrettyPrinter<'tcx>:                     p!(write("{}{}", data, ui_str))                 };             }-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {-                let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128;+            (Scalar::Raw { data, .. }, ty::Int(i)) => {+                let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size();+                let bit_size = size.bits() as u128;                 let min = 1u128 << (bit_size - 1);                 let max = min - 1; -                let ty = self.tcx().lift(&ty).unwrap();-                let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;                 let i_str = i.name_str();                 match data {                     d if d == min => p!(write("std::{}::MIN", i_str)),                     d if d == max => p!(write("std::{}::MAX", i_str)),                     _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)),                 }             }-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => {-                p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()))+            // Char+            (Scalar::Raw { data, .. }, ty::Char) => match ::std::char::from_u32(data as u32) {+                Some(c) => p!(write("{:?}", c)),+                None => p!(write("{}_char", data)),+            },+            // Raw pointers+            (Scalar::Raw { data, .. }, ty::RawPtr(_)) => {+                p!(write("{{0x{:x} as ", data), print(ty), write("}}"))             }-            (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")),-            (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => {+            (Scalar::Ptr(ptr), ty::FnPtr(_)) => {                 let instance = {                     let alloc_map = self.tcx().alloc_map.lock();                     alloc_map.unwrap_fn(ptr.alloc_id)                 };                 p!(print_value_path(instance.def_id(), instance.substs));

The fact that it's a fn pointer? The value path is a ZST.

oli-obk

comment created time in 7 days

Pull request review commentrust-lang/rust

Deduplicate pretty printing of constants

 pub trait PrettyPrinter<'tcx>:                     p!(write("{}{}", data, ui_str))                 };             }-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {-                let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128;+            (Scalar::Raw { data, .. }, ty::Int(i)) => {+                let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size();+                let bit_size = size.bits() as u128;                 let min = 1u128 << (bit_size - 1);                 let max = min - 1; -                let ty = self.tcx().lift(&ty).unwrap();-                let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;                 let i_str = i.name_str();                 match data {                     d if d == min => p!(write("std::{}::MIN", i_str)),                     d if d == max => p!(write("std::{}::MAX", i_str)),                     _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)),                 }             }-            (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => {-                p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()))+            // Char+            (Scalar::Raw { data, .. }, ty::Char) => match ::std::char::from_u32(data as u32) {+                Some(c) => p!(write("{:?}", c)),+                None => p!(write("{}_char", data)),

I think you can call from_u32 twice, it should be a cheap range check.

oli-obk

comment created time in 7 days

issue commentrust-lang/rust

Choose a naming scheme for codegen debuginfo emission.

Having added a couple more debuginfo abstractions in in #68965, I think I'm starting to agree more: we can expose few types, which happen to be semantically very distinct (type/scope/variable/location), and leave most of the naming choice to their constructors (e.g. dbg_scope_fn instead of dw_subprogram).

And I guess that bare minimal support (-C debuginfo=1, just mapping from code ranges to source locations) just needs function scopes and locations, so that should transfer well to other debuginfo formats, and everything else can be best-effort.

eddyb

comment created time in 7 days

issue commentrust-lang/rust

Formatting code is in conflict with unnamed_addr

What if... we actually called the function?! And there was a Formatter field that the fmt::Display impl for usize would fill in if a flag was set, and return without printing anything?

RalfJung

comment created time in 7 days

pull request commentrust-lang/rust

Document unsafe blocks in core::fmt

cc @rust-lang/wg-unsafe-code-guidelines (I believe the mention doesn't work for non-members)

foeb

comment created time in 7 days

Pull request review commentrust-lang/rust

Document unsafe blocks in core::fmt

 impl<'a> ArgumentV1<'a> {      fn as_usize(&self) -> Option<usize> {         if self.formatter as usize == ArgumentV1::show_usize as usize {+            // SAFETY: if the formatter is `show_usize`, it means it came in as `&usize`

Wait, was Display ever called Show? Why is it called show_usize?

foeb

comment created time in 7 days

Pull request review commentrust-lang/rust

Document unsafe blocks in core::fmt

 impl<'a> ArgumentV1<'a> {     #[doc(hidden)]     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]     pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {+        // SAFETY: `mem::transmute(x)` is safe because+        //     1. `&'b T` is transmuted to have an explicit lifetime `'b`+        //              (so as to not have an unbounded lifetime)+        //     2. `&'b T` and `&'b Void` have the same memory layout+        //              (as long as `T` is `Sized`)+        // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`+        // and `fn(&Void, &mut Formatter<'_>) -> Result` have the same ABI+        // (as long as `T` is `Sized`)

Oh god we haven't fixed that yet? enum Void {} should be replaced with an extern { type Erased; }.

foeb

comment created time in 7 days

issue commentrust-lang/rust

non-deterministic syn-opt run

This may have been happening a lot, if anyone has the time, going through the history of syn-opt runs would be useful.

It's far noisier than it should be IMO, and non-determinism might play a significant role.

Mark-Simulacrum

comment created time in 7 days

pull request commentrust-lang/rust

rustc: don't resolve Instances which would produce malformed shims.

Okay that's pure noise :( Does not make me feel good about relying on perf.rlo

eddyb

comment created time in 7 days

issue commentrust-lang/rust

Duplicated errors on UB inside a promoted

Or do you suggest we ignore UB in promoteds?

If we want to be clever we could only check promoteds that are still reachable after constant folding + simplify_cfg. Because the Assert guarding the use of the erroring promoted would have become unconditional.

Actually, do we have an unconditional Panic terminator?

estebank

comment created time in 7 days

delete branch eddyb/rust

delete branch : dbg-stack-dunk

delete time in 7 days

issue commentservo/servo

macOS ld considers libscript-*.rlib to be invalid

Could this happen because the size of the rlib reached 4Gb?

Makes sense, would explain the 64, LLVM must be switching to that format by necessity.

Knowing this you should be able to repro with just something like dd if=/dev/zero of=foo bs=1M count=4096 and then trying to archive that with llvm-ar (I don't know what the system ar can do)

There might not be any way to make this actually work, there's a high chance that LLVM is right and Apple is wrong.

In that case, Servo might need to somehow switch to lld on macOS, if that is even an option.

Or maybe we can "just" turn off SYM64 emission on macOS for the rare cases that cross the 4GiB limit, which may work with only performance losses as a side-effect.

cc @alexcrichton @michaelwoerister

CYBAI

comment created time in 7 days

pull request commentrust-lang/rust

rustc_mir: track inlined callees in SourceScopeData.

I just pushed 4 supporting codegen refactor commits, and the debuginfo implementation itself. It makes the backtrace-debuginfo test work, which is a good sign IMO.

eddyb

comment created time in 8 days

push eventeddyb/rust

Eduard-Mihai Burtescu

commit sha 2d03e10c9392d21762a4f8c62ca576362ca265d0

rustc: don't resolve Instances which would produce malformed shims.

view details

Eduard-Mihai Burtescu

commit sha b6cbf8f80f9e314951f4d3b1128f3be2b08c6fe1

rustc_mir: rename `location: SourceInfo` to `source_info`.

view details

Eduard-Mihai Burtescu

commit sha ef711ccf660decb408ada1acbe443e68fb6af20c

rustc_mir: use Instance more in the inliner.

view details

Eduard-Mihai Burtescu

commit sha 625a5b1ad0a519cbdd9bc8ac1dd2ab116874cadf

rustc_mir: track inlined callees in SourceScopeData.

view details

Eduard-Mihai Burtescu

commit sha bcaf6baa51d3bacbc8312d4da48276199c3bc36b

test: ensure #[track_caller] tests also test MIR inlining.

view details

Eduard-Mihai Burtescu

commit sha 1ce27ea3de66d4bcd4a1e68e31b7c4ec64b59f77

rustc_mir: support MIR-inlining #[track_caller] functions.

view details

Eduard-Mihai Burtescu

commit sha 205a556f552071b100d0dfb1327d54c8e777040b

rustc_mir: don't throw away inlined locals' spans.

view details

Eduard-Mihai Burtescu

commit sha 6eec9d0910f69ce43d17623d499058ef2e59fddc

rustc_codegen_llvm: create `DIFile`s from just `SourceFile`s.

view details

Eduard-Mihai Burtescu

commit sha 656c88ca4d262759a57961dadec1f7e938c914a4

rustc_codegen_llvm: move DISubprogram creation to a dbg_scope_fn method.

view details

Eduard-Mihai Burtescu

commit sha 651ca8d175771268f984cdc4ac2f692d7d248fc6

rustc_codegen_llvm: avoid converting between DILocation and Value.

view details

Eduard-Mihai Burtescu

commit sha 0d5f005e93fc341fab8f5cabb1d6d9622c666f5e

rustc_codegen_llvm: expose DILocation to rustc_codegen_ssa.

view details

Eduard-Mihai Burtescu

commit sha 3297ea1c5d0c03c13f5e201e1b7faf0318dec803

rustc_codegen_llvm: add support for inlined function debuginfo.

view details

push time in 8 days

pull request commentrust-lang/rust

[WIP] Cleanup `rmeta::MacroDef`

@petrochenkov I am trying to come up with a way for @Centril to rewrite say_hello_extern (from src/test/ui/proc-macro/span-api-tests.rs) as a proc macro that generates the "Hello, World!" literal with a Span that doesn't point to a real FileName.

I naively expected, judging from this, that the FileName would be ProcMacroSourceCode, for tokens parsed from a string (e.g. "foo bar baz".parse::<TokenStream>()): https://github.com/rust-lang/rust/blob/e6ec0d125eba4074122b187032474b4174fb9d31/src/librustc_expand/proc_macro_server.rs#L397-L404

But the last argument is named override_span in parse_stream_from_source_str, so I guess we try very hard to hide what the actual source was?

Centril

comment created time in 8 days

IssuesEvent

issue commentrust-lang/rust

Rename CodeMap/FileMap to SourceMap/SourceFile.

I came across over this instance of cm today: https://github.com/rust-lang/rust/blob/e6ec0d125eba4074122b187032474b4174fb9d31/src/librustc_errors/lib.rs#L149

So we might need to do another pass just for easier to miss things like cm.

eddyb

comment created time in 8 days

Pull request review commentrust-lang/rust

Deduplicate pretty printing of constants

 fn main() {} // START rustc.FOO.PromoteTemps.before.mir // bb0: { // ...-//     _5 = const Scalar(alloc1+0) : &i32;+//     _5 = const {alloc1+0: &i32};

And it's still not actual Rust code so why bother?

I think I agree for miri purposes, but I'd prefer if constants in MIR were as close to Rust as possible.

oli-obk

comment created time in 8 days

more