GCC Rust Weekly Status Report 33

Thanks again to Open Source Security, inc and Embecosm for their ongoing support for this project.

Milestone Progress

Another week of steady progress, where we landed the initial support for operator overloading, was all due to merging the lang-items work, which has unblocked a bunch of stuff within the compiler. The other major work was the first steps to remove the GCC abstractions we inherited from gccgo. The goal of GCC Rust has always been to make a GCC quality front-end for Rust and the GCC tree structures are very well suited to static analysis, and removing this abstraction will make work on const generics down the line much more straightforward.

This milestone has been an excellent opportunity to test the front-end on more complex test cases and fix bugs arising from this, which overall is hardening the code paths and understanding how Rust works in general.

Thank you to everyone who continues to support and work on the compiler.

Completed Activities

  • Merge LangItems work and operator overloading support PR801
  • Remove Btype, Bexpression, etc. abstractions over gcc trees PR805
  • Fix MethodCalls for covariant impl blocks PR810
  • Remove implicit name hack for trait associated types PR811

Contributors this month

Overall Task Status

CategoryLast WeekThis WeekDelta
TODO9393
In Progress1417+3
Completed244246+2
GitHub Issues

Test Cases

CategoryLast WeekThis WeekDelta
Passing49315106+255
XFAIL2121
make check-rust

Bugs

CategoryLast WeekThis WeekDelta
TODO2324+1
In Progress46+2
Completed8687+1
GitHub Bugs

Milestones Progress

MilestoneLast WeekThis WeekDeltaStart DateCompletion DateTarget
Data Structures 1 – Core100%100%30th Nov 202027th Jan 202129th Jan 2021
Control Flow 1 – Core100%100%28th Jan 202110th Feb 202126th Feb 2021
Data Structures 2 – Generics100%100%11th Feb 202114th May 202128th May 2021
Data Structures 3 – Traits100%100%20th May 202117th Sept 202127th Aug 2021
Control Flow 2 – Pattern Matching70%80%+10%20th Sept 202129th Nov 2021
Macros and cfg expansion0%0%1st Dec 202128th Mar 2022
Imports and Visibility0%0%29th Mar 202227th May 2022
Const Generics0%0%30th May 202225th Jul 2022
Intrinsics0%0%6th Sept 202130th Sept 2022
GitHub Milestones

Risks

RiskImpact (1-3)Likelihood (0-10)Risk (I * L)Mitigation
Rust Language Changes3721Keep up to date with the Rust language on a regular basis
Going over target dates3515Maintain status reports and issue tracking to stakeholders

Planned Activities

  • Finish work code generation for enums
  • Fix Qualified Path bug

Detailed changelog

Operator Overloading

Rust supports operator overloading of many different operations, we have added support for all the regular arithmetic operators (+,-,*,/,%), compound assignments such as (+=, …), the unary negation operators (!x, and -x). There is support for the deref operations but there are a few bugs to work through there to get it right. Since we cannot compile libcore yet we require you to define the lang items you want to use within your crate, we have taken the same traits from libcore to be sure that we can compile them correctly.

extern "C" {
    fn printf(s: *const i8, ...);
}

#[lang = "add"]
pub trait Add<Rhs = Self> {
    type Output;

    fn add(self, rhs: Rhs) -> Self::Output;
}

impl Add for i32 {
    type Output = i32;

    fn add(self, other: i32) -> i32 {
        self + other
    }
}

struct Foo(i32);
impl Add for Foo {
    type Output = Foo;

    fn add(self, other: Foo) -> Foo {
        Foo(self.0 + other.0)
    }
}


fn main() {
    let res;
    res = Foo(1) + Foo(2);

    unsafe {
        let a = "%i\n\0";
        let b = a as *const str;
        let c = b as *const i8;

        printf(c, res.0);
    }
}

The purpose of this test case is to ensure that when we add the Foo structure together that it will break down into calling the operator overload for i32. It should be noted that when you turn on optimizations these function calls are fully inlined just like C++ operator overloads.

See compiler explorer for more information https://godbolt.org/z/95bc4eWPW

Covariant Self’s within impl blocks

Impl blocks on rust support all types without bounds. Which mens the specified Self type for an impl block in this examples case is a reference to a generic type parameter. This means when we do a method call we must handle this case. Method resolution breaks down into two phases, the candidate probe then the actual resolution from the candidates. The first is about searching for a function named correctly which matches the impl block Self type then we use the autoderef mechanism to match the self parameter to find the candidate. Probing for candidates in method calls is a little bit unclear to me yet, but I believe the correct mechanism is meant to be looking for any impl block with a function named correctly then check via autodref if our receiver can be autoderef’d to the impl blocks implicit Self type to find all the potential candidates. Then we autoderef on small self.

pub trait Foo {
    type Target;

    fn bar(&self) -> &Self::Target;
}

impl<T> Foo for &T {
    type Target = T;

    fn bar(&self) -> &T {
        *self
    }
}

pub fn main() {
    let a: i32 = 123;
    let b: &i32 = &a;

    b.bar();
}

Remove GCC abstraction types

  • The goal of GCC Rust has always been to make a GCC quality front-end for Rust.
    • This means this goal comes first before any long term goal of porting the code to new compiler platforms etc.
  • The GCC IR is very suitable for further static analysis, and the abstractions will make this very awkward.
    • In the long term, we could potentially look at building a borrow checker at the GENERIC tree level, which might have some interesting code to share with wider GCC.
  • Constant Folding
    • Const Generics will be very awkward until this is removed.
    • The abstraction requires features such as constant Folding, which does not fit very well right now.

So overall removing the abstraction is going to make some things much easier to work with. For example, in the short term, code generation for unions/ADTs/match-expr could be simplified a lot if we remove this. It also might help attract more GCC people to work with the backend code generation piece to clean up the code here.

See: https://github.com/Rust-GCC/gccrs/issues/412

Leave a Reply

Your email address will not be published.