Code Monkey home page Code Monkey logo

proc-macro-workshop's Issues

Feature request: examples using proc-macro2 and darling

Thank you for creating this project! It's what I've been looking for to learn how to write procedural macros in rust.

I noticed that you are the co-author of the proc-macro2 crate; could you add some examples of how to use that crate here? Also, could you give examples of how to use darling?

I know nothing about writing macros, but want to learn how to do so correctly so that end users actually want to use my macros, instead of feeling that they have to use them. So once again, thank you for making this project!

Lesson 3

If would if if gods if would if soon if would if references if self if would if will if would if god if would if tests if would if fail?

use proc_macro::TokenStream;
use syn::{DeriveInput, __private::quote::quote, parse_macro_input};
#[proc_macro_derive(Builder)]
pub fn derive(input: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    let name = &ast.ident;
    let bname = format!("{}Builder", name);
    let bident = syn::Ident::new(&bname, name.span());
    let expanded = quote! {
        pub struct #bident {
            executable: Option<String>,
            args: Option<Vec<String>>,
            env: Option<Vec<String>>,
            current_dir: Option<String>,
        }
        impl #bident {
            pub fn executable(&mut self, executable: String) -> &mut self {
                self.executable = Some(executable);
                self
            }
            pub fn args(&mut self, args: Vec<String>) -> &mut self {
                self.args = Some(args);
                self
            }
            pub fn env(&mut self, env: Vec<String>) -> &mut self {
                self.env = Some(env);
                self
            }
            pub fn current_dir(&mut self, current_dir: String) -> &mut self {
                self.current_dir = Some(current_dir);
                self
            }
        }
        impl #name {
            fn builder() -> #bident {
                #bident {
                    executable: None,
                    args: None,
                    env: None,
                    current_dir: None
                }
            }
        }
    }; 
    expanded.into()
}

if would if throws if gods if would if error?

expected type, found module `self`
  --> $DIR/02-create-builder.rs:47:10
   |
47 | #[derive(Builder)]
   |          ^^^^^^^ help: a self type with a similar name exists: `Self`
   |
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

if would if could if would if post if would if answers if gods if would if solutions if to if would if lessons?

if would if is if gods https://www.youtube.com/watch?v=geovSK3wMB8&t=17s if minute if 42.22

The build function in Builder derive macro should take ownership

In the build derive macro, 04-call-builder, the build function takes a &mut self, and it returns a Command with the ownership of the fields. So I have to clone the fields in the implementation, which is not correct I suppose.

The build function should take the ownership of Builder, and return a builded result.

like this:

fn build(self) -> Result<Command, dyn Error>{
    unimplemented!()
}

List comprehension macro

I'd like to see a basic implementation of a macro for Python-style list and map comprehensions, and decide whether it would be a better teaching example for function-like proc macros than the current seq! project.

Something like:

let squares_map = c![n => n*n for n in 0..100 if n % 5 != 0];

Suggested by @jonhoo.

Nothing is implemented

there's probably something i'm not getting here, but i checked out the builder and the bitfield code and they are empty. what's happening?

builder/tests/07-repeated-field.rs needs a fix to pass

Hello. First things first, this is an excellent learning resource for Rust. If I was a recruiter, I would require passing this workshop before hiring. =) Now to the issue: In the builder project tests/07-repeated-field.rs , the test can't pass because the env field isn't optional but the test code doesn't set it before calling build(). A line like .env("FOO=1".to_owned()) just before the call to build (line 49) should fix this. It made it pass for me.

Full path in compiler error for bitfield 04

I am trying to solve 04 right now. There is just a small thing left where I was wondering how this was done in the reference implementation.

My error output currently looks like this:

EXPECTED:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error[E0277]: the trait bound `bitfield::checks::SevenMod8: bitfield::checks::TotalSizeIsMultipleOfEightBits` is not satisfied
  --> tests/04-multiple-of-8bits.rs:53:1
   |
53 | #[bitfield]
   | ^^^^^^^^^^^ the trait `bitfield::checks::TotalSizeIsMultipleOfEightBits` is not implemented for `bitfield::checks::SevenMod8`
   |
   = help: the trait `bitfield::checks::TotalSizeIsMultipleOfEightBits` is implemented for `bitfield::checks::ZeroMod8`
   = note: this error originates in the attribute macro `bitfield` (in Nightly builds, run with -Z macro-backtrace for more info)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error[E0277]: the trait bound `SevenMod8: TotalSizeIsMultipleOfEightsBits` is not satisfied
   --> tests/04-multiple-of-8bits.rs:53:1
    |
53  | #[bitfield]
    | ^^^^^^^^^^^ the trait `TotalSizeIsMultipleOfEightsBits` is not implemented for `SevenMod8`
    |
    = help: the trait `TotalSizeIsMultipleOfEightsBits` is implemented for `ZeroMod8`
note: required by a bound in `width_check`
   --> src/lib.rs
    |
    |     pub fn width_check<T: TotalSizeIsMultipleOfEightsBits>() {}
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `width_check`
    = note: this error originates in the attribute macro `bitfield` (in Nightly builds, run with -Z macro-backtrace for more info)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

I am happy with this, but I was curious why my output does not have the full paths as the reference implementation had and what to consider to get those full paths.

Kind Regards
Robin

Help with Cargo Expand?

Hello,

Thank you for the wonderful workshop. It is helping me learn macros!
One thing is that I am using the cargo expand command... and I'm not getting clean expansion...

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(Builder)]
pub fn derive(input: TokenStream) -> TokenStream {
    let ast = match ::syn::parse_macro_input::parse::<DeriveInput>(input) {
        ::syn::__private::Ok(data) => data,
        ::syn::__private::Err(err) => {
            return ::syn::__private::TokenStream::from(err.to_compile_error());
        }
    };
    let name = &ast.ident;
    let bname = syn::Ident::new(
        &{
            let res = ::alloc::fmt::format(::core::fmt::Arguments::new_v1(
                &["", "Builder"],
                &[::core::fmt::ArgumentV1::new_display(&name)],
            ));
            res
        },
        name.span(),
    );
    let fields = if let syn::Data::Struct(syn::DataStruct {
        fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }),
        ..
    }) = ast.data
    {
        named
    } else {
        ::core::panicking::panic("not implemented")
    };
    let bname_struct_fields = fields.iter().map(|field| {
        let field_name = &field.ident;
        let field_type = &field.ty;
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&field_name, &mut _s);
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_ident(&mut _s, "std");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "option");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Option");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&field_type, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            _s
        }
    });
    let builder = {
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_ident(&mut _s, "pub");
        ::quote::__private::push_ident(&mut _s, "struct");
        ::quote::ToTokens::to_tokens(&bname, &mut _s);
        ::quote::__private::push_group(&mut _s, ::quote::__private::Delimiter::Brace, {
            let mut _s = ::quote::__private::TokenStream::new();
            {
                use ::quote::__private::ext::*;
                let has_iter = ::quote::__private::ThereIsNoIteratorInRepetition;
                #[allow(unused_mut)]
                let (mut bname_struct_fields, i) = bname_struct_fields.quote_into_iter();
                let has_iter = has_iter | i;
                let _: ::quote::__private::HasIterator = has_iter;
                while true {
                    let bname_struct_fields = match bname_struct_fields.next() {
                        Some(_x) => ::quote::__private::RepInterp(_x),
                        None => break,
                    };
                    ::quote::ToTokens::to_tokens(&bname_struct_fields, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                }
            };
            _s
        });
        ::quote::__private::push_ident(&mut _s, "impl");
        ::quote::ToTokens::to_tokens(&name, &mut _s);
        ::quote::__private::push_group(&mut _s, ::quote::__private::Delimiter::Brace, {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "pub");
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "builder");
            ::quote::__private::push_group(
                &mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new(),
            );
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::ToTokens::to_tokens(&bname, &mut _s);
            ::quote::__private::push_group(&mut _s, ::quote::__private::Delimiter::Brace, {
                let mut _s = ::quote::__private::TokenStream::new();
                ::quote::__private::push_ident(&mut _s, "return");
                ::quote::ToTokens::to_tokens(&bname, &mut _s);
                ::quote::__private::push_group(&mut _s, ::quote::__private::Delimiter::Brace, {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "executable");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "None");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "args");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "None");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "env");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "None");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "current_dir");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "None");
                    ::quote::__private::push_comma(&mut _s);
                    _s
                });
                _s
            });
            _s
        });
        _s
    };
    return builder.into();
}
const _: () = {
    extern crate proc_macro;
    #[rustc_proc_macro_decls]
    #[allow(deprecated)]
    static _DECLS: &[proc_macro::bridge::client::ProcMacro] =
        &[proc_macro::bridge::client::ProcMacro::custom_derive(
            "Builder",
            &[],
            derive,
        )];
};

I've seen other output, per tutorial by Jon Gjengset](https://www.youtube.com/watch?v=geovSK3wMB8), and it looks clearer and helpful. While the current expand is filled with " ::quote::__private::push_comma"... Not sure if it is just a setting? Any direction or help would be really appreciated!

Thank you!

Builder test 2 - Option intended?

builder/tests/02-create-builder.rs says "Before moving on, have the macro also generate:" and it shows the CommandBuilder struct based on the input Command type, but with each field made Optional if it's not already.

I understand why they'd be optional -- the builder pattern requires adding individual fields before construction of the output type -- but is dynamically making fields optional an intended piece of test 2? It comes quite early in the workshop, but doing so seems rather complicated.

In particular, it seems to assume knowledge gained in test 6 (see #12) regarding detection of whether a field has Option (because one field is already Option) plus knowledge of modifying field types.

Simpler tasks, like building an ident, have a resource link, but there's no comment about type modification.

Sorry if I'm missing an obvious alternative for adding Option!

Why span in `compile_error!` error message include the ending `;` ?

I use rustc 1.54.0 (a178d0322 2021-07-26), in seq/tests/03-expand-four-errors.rs, span in the expected error message doesn't include the ending ; as shown below.

error: error number 0
  --> tests/03-expand-four-errors.rs:20:5
   |
20 |     compile_error!(concat!("error number ", stringify!(N)));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

However, my solution gives an almost equal version except that the span ^ includes the ending ';'.

error: error number 0
  --> tests/03-expand-four-errors.rs:20:5
   |
20 |     compile_error!(concat!("error number ", stringify!(N)));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I try to add compile_error! explicitly, and the error message also includes the ending ;.

error: error number 0
  --> main.rs:13:5
   |
13 |     compile_error!(concat!("error number ", stringify!(0)));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I wonder whether it's just an compiler version issue or it's intended to be so and I should figure out how to control the span in error meesage generated by compile_error!?

Update projects and tests to 2021 edition

At least the seq! project will require some rework because ident concatenation Variant#N is no longer legal syntax lexically. There may be other incompatibilities in the other projects as well.

[Help] How to parsing multi recursive proc macros ?

I want parsing recursive like this ”any“,”all” proc content. Is there a simpler tool or example?

(command is convert fn to trait struct, like rocket get/post macros)

// get name content
#[event(command("hello {name}"))]
async fn hello( name: Option<String>) -> anyhow::Result<bool> {
    if name.is_none() {
        return Ok(false);
    }
    Ok(true)
}

// all , any 
#[event(all(command("hello {name}", filter = "i_am_filter")))]
async fn hello( name: Option<String>) -> anyhow::Result<bool> {
    if name.is_none() && name.unwrap().start_with("123") {
        return Ok(false);
    }
    event.send_message_to_source(format!("hello {}", name.unwrap()).parse_message_chain()).await.unwrap();
    Ok(true)
}

async fn i_am_filter( name: Option<String>) -> anyhow::Result<bool> {
    if name.is_none() {
        return Ok(false);
    }
   // do some
    Ok(true)
}

#[event(regexp("^123$"))]

Thank you for creating this!

Thank you for creating this project; I'm moving through it very slowly, but I wanted to say thank you for putting it together. It's been a big help in learning to read macros in rust!

Compile fail on newer version of syn and quote on derive_builder unrecognize attribute test

In the newer version of syn and quote this 08-unrecognized-attribute.rs builder test fails.

EXPECTED:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: expected `builder(each = "...")`
  --> $DIR/08-unrecognized-attribute.rs:22:7
   |
22 |     #[builder(eac = "arg")]
   |       ^^^^^^^^^^^^^^^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: expected `builder(each = "...")`
  --> $DIR/08-unrecognized-attribute.rs:22:15
   |
22 |     #[builder(eac = "arg")]
   |               ^^^^^^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

Rust version: rustc 1.57.0-nightly (c02371c44 2021-10-01)
syn: 1.0.78
quote: 1.0.9

seq test case 03 fail

Hi,
my code failed when executing seq test case 03, the output is:

ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: error number 0
  --> tests/03-expand-four-errors.rs:19:1
   |
19 | / seq!(N in 0..4 {
20 | |     compile_error!(concat!("error number ", stringify!(N)));
21 | | });
   | |__^
   |
   = note: this error originates in the macro `seq` (in Nightly builds, run with -Z macro-backtrace for more info)

error: error number 1
  --> tests/03-expand-four-errors.rs:19:1
   |
19 | / seq!(N in 0..4 {
20 | |     compile_error!(concat!("error number ", stringify!(N)));
21 | | });
   | |__^
   |
   = note: this error originates in the macro `seq` (in Nightly builds, run with -Z macro-backtrace for more info)

error: error number 2
  --> tests/03-expand-four-errors.rs:19:1
   |
19 | / seq!(N in 0..4 {
20 | |     compile_error!(concat!("error number ", stringify!(N)));
21 | | });
   | |__^
   |
   = note: this error originates in the macro `seq` (in Nightly builds, run with -Z macro-backtrace for more info)

error: error number 3
  --> tests/03-expand-four-errors.rs:19:1
   |
19 | / seq!(N in 0..4 {
20 | |     compile_error!(concat!("error number ", stringify!(N)));
21 | | });
   | |__^
   |
   = note: this error originates in the macro `seq` (in Nightly builds, run with -Z macro-backtrace for more info)

I even tried to print the result TokenStream before returning and it looks totally correct (begin with "compile_error" as ident).
Download someone else's code from github and test, same output...

rust version: 1.75.0

dependencies:

proc-macro2 = "1.0.81"
syn = { version = "2.0.59", features = ["full", "extra-traits"] }
quote = "1.0.36"
prettyplease = "0.2.1"

repository: https://github.com/apodemakeles/proc-macro-workshop/blob/seq/seq/src/lib.rs

What is best way to print whole path

Hi

For a Path type for Error::Fmt, how to print it exactly same as the code?
When I convert it to tokenstream, then print it, it has space between path segments and punct.

EXPECTED:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: Error::Fmt should sort before Error::Io
  --> tests/06-pattern-path.rs:33:13
   |
33 |             Error::Fmt(e) => write!(f, "{}", e),
   |             ^^^^^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: Error :: Fmt should sort before Error :: Io
  --> tests/06-pattern-path.rs:33:13
   |
33 |             Error::Fmt(e) => write!(f, "{}", e),
   |             ^^^^^^^^^^

At present, I have to use quite a long expression to get the string

path
.segments
.iter()
.map(|seg| seg.ident.to_string())
.collect::<Vec<_>>()
.join("::");

Learning documents

Is there a presentation or book or blog posts that can be followed to learn the necessary knowledge required to accomplish the workshop ?

Seq05 would break multiple other tests.

Seq05 introduced new rule to only repeat tokens inside #( ... )*.
This new rule would cause other tests fall since they don't have their full body inside #( ... )*.
Broken tests are Seq02, Seq03, Seq04, Seq08 .

Getting the correct span for multi-segment Path

Hi,

I spent a long time tracing down a bug in my implementation of the sorted macro against the 06-pattern-path test. Namely, my output always looked like this:

error: Error::Fmt should sort before Error::Io
  --> main.rs:23:7
   |
23 |       Error::Fmt(e) => write!(f, "{}", e),
   |       ^^^^^

where the error span is just Error instead of the expected Error::Fmt. I checked my code to made sure in my code that it's indeed the path's span being stored and emitted instead of the ident's. It's even more confusing because cargo expand gives the expected output whereas the cargo test and cargo run gives different answer.

After more debugging and searching I finally stumbled upon this issue. So after switching my toolchain from stable to nightly, the test passes as expected. Now I see it's because the stable proc-macro doesn't allow joining of spans, thus only the first token of the syntax tree is returned upon calling the Spanned::span function.

I think it may be good to indicate this trick somewhere in note since it's probably not a trivial bug. Anyway, to the future learners who had their head scratched hard for this error, I hope this issue can be helpful :)

Help with `Seq` macro

Hi! I'm working on implementing the Seq macro and I'm getting a little stuck. It alludes to treating the body of the expression as a TokenStream and not as some type of syn AST structure.

I can parse out everything that's instructed in the 01-parse-header.rs file, but when I get to 02-parse-body.rs, I get stuck on how to treat the loop body of the macro as a TokenStream. Additionally, when I attempt to run cargo test, I get an error on unexpected tokens.

The error message:

Testing tests/01-parse-header.rs ... error
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: unexpected token
  --> $DIR/01-parse-header.rs:25:16
   |
25 |   seq!(N in 0..8 {
   |  ________________^
26 | |     // nothing
27 | | });
   | |_^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

Link to the code I have so far: https://github.com/ELD/proc-macro-workshop/blob/seq-macro/seq/src/lib.rs

Any guidance would be appreciated!

What to do?

Sorry if its really obvious. Where do I find the article, video, or whatever I am supposed to follow along?

Unused code warning in sorted 04

I received unused import warnings which lead to a compile error missmatch for an otherwise correct test 04.
I solved this issue by adding #![allow(unused_imports)] to the 04 code and adapting the line numbers in the *.stderr file.

Add more explanations/links to Builder

Hi

Following up on the builder tutorial, I found the transition to 06-optional-field to the end is tough. It'd help a lot to explain a little in more details what to do or link to similar code about how to check whether Option exists or not in 06.

Sorted: Tests for sorted match expressions do not catch if you always compare to the first arm

In sorted::check I forgot to update the last arm and ended comparing all arms with the first arm but still all tests (1-8) passed.

I only noticed my error because I was wondering why test 8 did not fail when having an arm that started with a lower case char (lower chase char > "-") before actually impl. it

EDIT:
For test 8 it also would be a good idea to use match arms that start with a lower case letter (e.g. io::Result) because otherwise the order is correct anyways because all upper case chars are less than "_". At least if you use string comparison.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.