Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird behavior with type errors in macros #64113

Closed
lopopolo opened this issue Sep 3, 2019 · 4 comments
Closed

Weird behavior with type errors in macros #64113

lopopolo opened this issue Sep 3, 2019 · 4 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@lopopolo
Copy link
Contributor

lopopolo commented Sep 3, 2019

Unfortunately I don't have a reproducer but this is what I think I know:

  • I had some nested macros that took types as arguments and implemented traits.
  • Somewhere in the chain I was using a HashMap.
  • HashMap was not imported in the scope where the macro was invoked (same source file as macro definition).
  • The compiler ground to a halt. A codebase that normally compiles in 30 seconds took around 5 minutes to (fail to) compile.
  • For most of this time, only one core was being used by rustc and it was pegged to 100%.
  • There was no output from the compiler.
  • Once the compiler was done chruning, around 10k errors got spat out.
  • The ones at the bottom of the scrollback had the line impl Foo<[type error]> for Bar in them.

What is supposed to happen here? Was the compiler spinning on generating error output? What does the output with the literal "[type error]" for a type mean?

@Centril Centril added A-diagnostics Area: Messages for errors, warnings, and lints A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels Sep 3, 2019
@Centril
Copy link
Contributor

Centril commented Sep 3, 2019

What does the output with the literal "[type error]" for a type mean?

This is the pretty printing output for ty::Error.

@lopopolo
Copy link
Contributor Author

lopopolo commented Sep 3, 2019

It's not exactly minimal, but I've found a reproducer:

type Int = i64;
type Float = f64;

struct Artichoke;
struct ArtichokeError;
struct Value;

impl Value {
    fn try_into<T>(self) -> Result<T, ArtichokeError>
    where
        Artichoke: TryConvert<Self, T>,
    {
        Err(ArtichokeError)
    }
}

pub trait Convert<T, U> {
    fn convert(&self, from: T) -> U;
}

pub trait TryConvert<T, U> {
    fn try_convert(&self, value: T) -> Result<U, ArtichokeError>;
}

impl<T, U, V> TryConvert<T, U> for V
where
    V: Convert<T, U>,
{
    fn try_convert(&self, value: T) -> Result<U, ArtichokeError> {
        Ok(Convert::convert(self, value))
    }
}

// bail out implementation for mixed-type collections
impl Convert<Vec<Value>, Value> for Artichoke {
    fn convert(&self, value: Vec<Value>) -> Value {
        Value
    }
}

impl TryConvert<Value, Vec<Value>> for Artichoke {
    fn try_convert(&self, value: Value) -> Result<Vec<Value>, ArtichokeError> {
        Ok(vec![Value])
    }
}

macro_rules! array_to_ruby {
    ($elem:ty) => {
        impl<'a> Convert<Vec<$elem>, Value> for Artichoke {
            fn convert(&self, value: Vec<$elem>) -> Value {
                let elems = value
                    .into_iter()
                    .map(|elem| self.convert(elem))
                    .collect::<Vec<Value>>();
                self.convert(elems)
            }
        }
    };
}

macro_rules! ruby_to_array {
    ($elem:ty) => {
        impl<'a> TryConvert<Value, Vec<$elem>> for Artichoke {
            fn try_convert(&self, value: Value) -> Result<Vec<$elem>, ArtichokeError> {
                let elems: Vec<Value> = self.try_convert(value)?;
                let mut vec = <Vec<$elem>>::with_capacity(elems.len());
                for elem in elems.into_iter() {
                    let elem = elem.try_into::<$elem>()?;
                    vec.push(elem);
                }
                Ok(vec)
            }
        }
    };
}

// Primitives
array_to_ruby!(bool);
array_to_ruby!(Vec<u8>);
array_to_ruby!(Int);
array_to_ruby!(Float);
array_to_ruby!(String);
array_to_ruby!(&'a str);

// Optional primitives
array_to_ruby!(Option<Value>);
array_to_ruby!(Option<bool>);
array_to_ruby!(Option<Vec<u8>>);
array_to_ruby!(Option<Int>);
array_to_ruby!(Option<Float>);
array_to_ruby!(Option<String>);
array_to_ruby!(Option<&'a str>);

// Array of primitives
array_to_ruby!(Vec<Value>);
array_to_ruby!(Vec<bool>);
array_to_ruby!(Vec<Vec<u8>>);
array_to_ruby!(Vec<Int>);
array_to_ruby!(Vec<Float>);
array_to_ruby!(Vec<String>);
array_to_ruby!(Vec<&'a str>);

// Array of optional primitives
array_to_ruby!(Vec<Option<Value>>);
array_to_ruby!(Vec<Option<bool>>);
array_to_ruby!(Vec<Option<Vec<u8>>>);
array_to_ruby!(Vec<Option<Int>>);
array_to_ruby!(Vec<Option<Float>>);
array_to_ruby!(Vec<Option<String>>);
array_to_ruby!(Vec<Option<&'a str>>);

// Hash of primitive keys to values
array_to_ruby!(HashMap<bool, Value>);
array_to_ruby!(HashMap<bool, bool>);
array_to_ruby!(HashMap<bool, Vec<u8>>);
array_to_ruby!(HashMap<bool, Int>);
array_to_ruby!(HashMap<bool, Float>);
array_to_ruby!(HashMap<bool, String>);
array_to_ruby!(HashMap<bool, &'a str>);
array_to_ruby!(HashMap<Vec<u8>, Value>);
array_to_ruby!(HashMap<Vec<u8>, bool>);
array_to_ruby!(HashMap<Vec<u8>, Vec<u8>>);
array_to_ruby!(HashMap<Vec<u8>, Int>);
array_to_ruby!(HashMap<Vec<u8>, Float>);
array_to_ruby!(HashMap<Vec<u8>, String>);
array_to_ruby!(HashMap<Vec<u8>, &'a str>);
array_to_ruby!(HashMap<Int, Value>);
array_to_ruby!(HashMap<Int, bool>);
array_to_ruby!(HashMap<Int, Vec<u8>>);
array_to_ruby!(HashMap<Int, Int>);
array_to_ruby!(HashMap<Int, Float>);
array_to_ruby!(HashMap<Int, String>);
array_to_ruby!(HashMap<Int, &'a str>);
array_to_ruby!(HashMap<String, Value>);
array_to_ruby!(HashMap<String, bool>);
array_to_ruby!(HashMap<String, Vec<u8>>);
array_to_ruby!(HashMap<String, Int>);
array_to_ruby!(HashMap<String, Float>);
array_to_ruby!(HashMap<String, String>);
array_to_ruby!(HashMap<String, &'a str>);
array_to_ruby!(HashMap<&'a str, Value>);
array_to_ruby!(HashMap<&'a str, bool>);
array_to_ruby!(HashMap<&'a str, Vec<u8>>);
array_to_ruby!(HashMap<&'a str, Int>);
array_to_ruby!(HashMap<&'a str, Float>);
array_to_ruby!(HashMap<&'a str, String>);
array_to_ruby!(HashMap<&'a str, &'a str>);

// Hash of optional keys to values
array_to_ruby!(HashMap<Option<bool>, Value>);
array_to_ruby!(HashMap<Option<bool>, bool>);
array_to_ruby!(HashMap<Option<bool>, Vec<u8>>);
array_to_ruby!(HashMap<Option<bool>, Int>);
array_to_ruby!(HashMap<Option<bool>, Float>);
array_to_ruby!(HashMap<Option<bool>, String>);
array_to_ruby!(HashMap<Option<bool>, &'a str>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Value>);
array_to_ruby!(HashMap<Option<Vec<u8>>, bool>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Vec<u8>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Int>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Float>);
array_to_ruby!(HashMap<Option<Vec<u8>>, String>);
array_to_ruby!(HashMap<Option<Vec<u8>>, &'a str>);
array_to_ruby!(HashMap<Option<Int>, Value>);
array_to_ruby!(HashMap<Option<Int>, bool>);
array_to_ruby!(HashMap<Option<Int>, Vec<u8>>);
array_to_ruby!(HashMap<Option<Int>, Int>);
array_to_ruby!(HashMap<Option<Int>, Float>);
array_to_ruby!(HashMap<Option<Int>, String>);
array_to_ruby!(HashMap<Option<Int>, &'a str>);
array_to_ruby!(HashMap<Option<String>, Value>);
array_to_ruby!(HashMap<Option<String>, bool>);
array_to_ruby!(HashMap<Option<String>, Vec<u8>>);
array_to_ruby!(HashMap<Option<String>, Int>);
array_to_ruby!(HashMap<Option<String>, Float>);
array_to_ruby!(HashMap<Option<String>, String>);
array_to_ruby!(HashMap<Option<String>, &'a str>);
array_to_ruby!(HashMap<Option<&'a str>, Value>);
array_to_ruby!(HashMap<Option<&'a str>, bool>);
array_to_ruby!(HashMap<Option<&'a str>, Vec<u8>>);
array_to_ruby!(HashMap<Option<&'a str>, Int>);
array_to_ruby!(HashMap<Option<&'a str>, Float>);
array_to_ruby!(HashMap<Option<&'a str>, String>);
array_to_ruby!(HashMap<Option<&'a str>, &'a str>);

// Hash of primitive keys to optional values
array_to_ruby!(HashMap<bool, Option<Value>>);
array_to_ruby!(HashMap<bool, Option<bool>>);
array_to_ruby!(HashMap<bool, Option<Vec<u8>>>);
array_to_ruby!(HashMap<bool, Option<Int>>);
array_to_ruby!(HashMap<bool, Option<Float>>);
array_to_ruby!(HashMap<bool, Option<String>>);
array_to_ruby!(HashMap<bool, Option<&'a str>>);
array_to_ruby!(HashMap<Vec<u8>, Option<Value>>);
array_to_ruby!(HashMap<Vec<u8>, Option<bool>>);
array_to_ruby!(HashMap<Vec<u8>, Option<Vec<u8>>>);
array_to_ruby!(HashMap<Vec<u8>, Option<Int>>);
array_to_ruby!(HashMap<Vec<u8>, Option<Float>>);
array_to_ruby!(HashMap<Vec<u8>, Option<String>>);
array_to_ruby!(HashMap<Vec<u8>, Option<&'a str>>);
array_to_ruby!(HashMap<Int, Option<Value>>);
array_to_ruby!(HashMap<Int, Option<bool>>);
array_to_ruby!(HashMap<Int, Option<Vec<u8>>>);
array_to_ruby!(HashMap<Int, Option<Int>>);
array_to_ruby!(HashMap<Int, Option<Float>>);
array_to_ruby!(HashMap<Int, Option<String>>);
array_to_ruby!(HashMap<Int, Option<&'a str>>);
array_to_ruby!(HashMap<String, Option<Value>>);
array_to_ruby!(HashMap<String, Option<bool>>);
array_to_ruby!(HashMap<String, Option<Vec<u8>>>);
array_to_ruby!(HashMap<String, Option<Int>>);
array_to_ruby!(HashMap<String, Option<Float>>);
array_to_ruby!(HashMap<String, Option<String>>);
array_to_ruby!(HashMap<String, Option<&'a str>>);
array_to_ruby!(HashMap<&'a str, Option<Value>>);
array_to_ruby!(HashMap<&'a str, Option<bool>>);
array_to_ruby!(HashMap<&'a str, Option<Vec<u8>>>);
array_to_ruby!(HashMap<&'a str, Option<Int>>);
array_to_ruby!(HashMap<&'a str, Option<Float>>);
array_to_ruby!(HashMap<&'a str, Option<String>>);
array_to_ruby!(HashMap<&'a str, Option<&'a str>>);

// Hash of primitive optional keys to optional values
array_to_ruby!(HashMap<Option<bool>, Option<Value>>);
array_to_ruby!(HashMap<Option<bool>, Option<bool>>);
array_to_ruby!(HashMap<Option<bool>, Option<Vec<u8>>>);
array_to_ruby!(HashMap<Option<bool>, Option<Int>>);
array_to_ruby!(HashMap<Option<bool>, Option<Float>>);
array_to_ruby!(HashMap<Option<bool>, Option<String>>);
array_to_ruby!(HashMap<Option<bool>, Option<&'a str>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Option<Value>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Option<bool>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Option<Vec<u8>>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Option<Int>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Option<Float>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Option<String>>);
array_to_ruby!(HashMap<Option<Vec<u8>>, Option<&'a str>>);
array_to_ruby!(HashMap<Option<Int>, Option<Value>>);
array_to_ruby!(HashMap<Option<Int>, Option<bool>>);
array_to_ruby!(HashMap<Option<Int>, Option<Vec<u8>>>);
array_to_ruby!(HashMap<Option<Int>, Option<Int>>);
array_to_ruby!(HashMap<Option<Int>, Option<Float>>);
array_to_ruby!(HashMap<Option<Int>, Option<String>>);
array_to_ruby!(HashMap<Option<Int>, Option<&'a str>>);
array_to_ruby!(HashMap<Option<String>, Option<Value>>);
array_to_ruby!(HashMap<Option<String>, Option<bool>>);
array_to_ruby!(HashMap<Option<String>, Option<Vec<u8>>>);
array_to_ruby!(HashMap<Option<String>, Option<Int>>);
array_to_ruby!(HashMap<Option<String>, Option<Float>>);
array_to_ruby!(HashMap<Option<String>, Option<String>>);
array_to_ruby!(HashMap<Option<String>, Option<&'a str>>);
array_to_ruby!(HashMap<Option<&'a str>, Option<Value>>);
array_to_ruby!(HashMap<Option<&'a str>, Option<bool>>);
array_to_ruby!(HashMap<Option<&'a str>, Option<Vec<u8>>>);
array_to_ruby!(HashMap<Option<&'a str>, Option<Int>>);
array_to_ruby!(HashMap<Option<&'a str>, Option<Float>>);
array_to_ruby!(HashMap<Option<&'a str>, Option<String>>);
array_to_ruby!(HashMap<Option<&'a str>, Option<&'a str>>);

// Primitives
ruby_to_array!(bool);
ruby_to_array!(Vec<u8>);
ruby_to_array!(Int);
ruby_to_array!(Float);
ruby_to_array!(String);
ruby_to_array!(&'a str);

// Optional primitives
ruby_to_array!(Option<Value>);
ruby_to_array!(Option<bool>);
ruby_to_array!(Option<Vec<u8>>);
ruby_to_array!(Option<Int>);
ruby_to_array!(Option<Float>);
ruby_to_array!(Option<String>);
ruby_to_array!(Option<&'a str>);

// Array of primitives
ruby_to_array!(Vec<Value>);
ruby_to_array!(Vec<bool>);
ruby_to_array!(Vec<Vec<u8>>);
ruby_to_array!(Vec<Int>);
ruby_to_array!(Vec<Float>);
ruby_to_array!(Vec<String>);
ruby_to_array!(Vec<&'a str>);

// Array of optional primitives
ruby_to_array!(Vec<Option<Value>>);
ruby_to_array!(Vec<Option<bool>>);
ruby_to_array!(Vec<Option<Vec<u8>>>);
ruby_to_array!(Vec<Option<Int>>);
ruby_to_array!(Vec<Option<Float>>);
ruby_to_array!(Vec<Option<String>>);
ruby_to_array!(Vec<Option<&'a str>>);

// Hash of primitive keys to values
ruby_to_array!(HashMap<bool, Value>);
ruby_to_array!(HashMap<bool, bool>);
ruby_to_array!(HashMap<bool, Vec<u8>>);
ruby_to_array!(HashMap<bool, Int>);
ruby_to_array!(HashMap<bool, Float>);
ruby_to_array!(HashMap<bool, String>);
ruby_to_array!(HashMap<bool, &'a str>);
ruby_to_array!(HashMap<Vec<u8>, Value>);
ruby_to_array!(HashMap<Vec<u8>, bool>);
ruby_to_array!(HashMap<Vec<u8>, Vec<u8>>);
ruby_to_array!(HashMap<Vec<u8>, Int>);
ruby_to_array!(HashMap<Vec<u8>, Float>);
ruby_to_array!(HashMap<Vec<u8>, String>);
ruby_to_array!(HashMap<Vec<u8>, &'a str>);
ruby_to_array!(HashMap<Int, Value>);
ruby_to_array!(HashMap<Int, bool>);
ruby_to_array!(HashMap<Int, Vec<u8>>);
ruby_to_array!(HashMap<Int, Int>);
ruby_to_array!(HashMap<Int, Float>);
ruby_to_array!(HashMap<Int, String>);
ruby_to_array!(HashMap<Int, &'a str>);
ruby_to_array!(HashMap<String, Value>);
ruby_to_array!(HashMap<String, bool>);
ruby_to_array!(HashMap<String, Vec<u8>>);
ruby_to_array!(HashMap<String, Int>);
ruby_to_array!(HashMap<String, Float>);
ruby_to_array!(HashMap<String, String>);
ruby_to_array!(HashMap<String, &'a str>);
ruby_to_array!(HashMap<&'a str, Value>);
ruby_to_array!(HashMap<&'a str, bool>);
ruby_to_array!(HashMap<&'a str, Vec<u8>>);
ruby_to_array!(HashMap<&'a str, Int>);
ruby_to_array!(HashMap<&'a str, Float>);
ruby_to_array!(HashMap<&'a str, String>);
ruby_to_array!(HashMap<&'a str, &'a str>);

// Hash of optional keys to values
ruby_to_array!(HashMap<Option<bool>, Value>);
ruby_to_array!(HashMap<Option<bool>, bool>);
ruby_to_array!(HashMap<Option<bool>, Vec<u8>>);
ruby_to_array!(HashMap<Option<bool>, Int>);
ruby_to_array!(HashMap<Option<bool>, Float>);
ruby_to_array!(HashMap<Option<bool>, String>);
ruby_to_array!(HashMap<Option<bool>, &'a str>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Value>);
ruby_to_array!(HashMap<Option<Vec<u8>>, bool>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Vec<u8>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Int>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Float>);
ruby_to_array!(HashMap<Option<Vec<u8>>, String>);
ruby_to_array!(HashMap<Option<Vec<u8>>, &'a str>);
ruby_to_array!(HashMap<Option<Int>, Value>);
ruby_to_array!(HashMap<Option<Int>, bool>);
ruby_to_array!(HashMap<Option<Int>, Vec<u8>>);
ruby_to_array!(HashMap<Option<Int>, Int>);
ruby_to_array!(HashMap<Option<Int>, Float>);
ruby_to_array!(HashMap<Option<Int>, String>);
ruby_to_array!(HashMap<Option<Int>, &'a str>);
ruby_to_array!(HashMap<Option<String>, Value>);
ruby_to_array!(HashMap<Option<String>, bool>);
ruby_to_array!(HashMap<Option<String>, Vec<u8>>);
ruby_to_array!(HashMap<Option<String>, Int>);
ruby_to_array!(HashMap<Option<String>, Float>);
ruby_to_array!(HashMap<Option<String>, String>);
ruby_to_array!(HashMap<Option<String>, &'a str>);
ruby_to_array!(HashMap<Option<&'a str>, Value>);
ruby_to_array!(HashMap<Option<&'a str>, bool>);
ruby_to_array!(HashMap<Option<&'a str>, Vec<u8>>);
ruby_to_array!(HashMap<Option<&'a str>, Int>);
ruby_to_array!(HashMap<Option<&'a str>, Float>);
ruby_to_array!(HashMap<Option<&'a str>, String>);
ruby_to_array!(HashMap<Option<&'a str>, &'a str>);

// Hash of primitive keys to optional values
ruby_to_array!(HashMap<bool, Option<Value>>);
ruby_to_array!(HashMap<bool, Option<bool>>);
ruby_to_array!(HashMap<bool, Option<Vec<u8>>>);
ruby_to_array!(HashMap<bool, Option<Int>>);
ruby_to_array!(HashMap<bool, Option<Float>>);
ruby_to_array!(HashMap<bool, Option<String>>);
ruby_to_array!(HashMap<bool, Option<&'a str>>);
ruby_to_array!(HashMap<Vec<u8>, Option<Value>>);
ruby_to_array!(HashMap<Vec<u8>, Option<bool>>);
ruby_to_array!(HashMap<Vec<u8>, Option<Vec<u8>>>);
ruby_to_array!(HashMap<Vec<u8>, Option<Int>>);
ruby_to_array!(HashMap<Vec<u8>, Option<Float>>);
ruby_to_array!(HashMap<Vec<u8>, Option<String>>);
ruby_to_array!(HashMap<Vec<u8>, Option<&'a str>>);
ruby_to_array!(HashMap<Int, Option<Value>>);
ruby_to_array!(HashMap<Int, Option<bool>>);
ruby_to_array!(HashMap<Int, Option<Vec<u8>>>);
ruby_to_array!(HashMap<Int, Option<Int>>);
ruby_to_array!(HashMap<Int, Option<Float>>);
ruby_to_array!(HashMap<Int, Option<String>>);
ruby_to_array!(HashMap<Int, Option<&'a str>>);
ruby_to_array!(HashMap<String, Option<Value>>);
ruby_to_array!(HashMap<String, Option<bool>>);
ruby_to_array!(HashMap<String, Option<Vec<u8>>>);
ruby_to_array!(HashMap<String, Option<Int>>);
ruby_to_array!(HashMap<String, Option<Float>>);
ruby_to_array!(HashMap<String, Option<String>>);
ruby_to_array!(HashMap<String, Option<&'a str>>);
ruby_to_array!(HashMap<&'a str, Option<Value>>);
ruby_to_array!(HashMap<&'a str, Option<bool>>);
ruby_to_array!(HashMap<&'a str, Option<Vec<u8>>>);
ruby_to_array!(HashMap<&'a str, Option<Int>>);
ruby_to_array!(HashMap<&'a str, Option<Float>>);
ruby_to_array!(HashMap<&'a str, Option<String>>);
ruby_to_array!(HashMap<&'a str, Option<&'a str>>);

// Hash of primitive optional keys to optional values
ruby_to_array!(HashMap<Option<bool>, Option<Value>>);
ruby_to_array!(HashMap<Option<bool>, Option<bool>>);
ruby_to_array!(HashMap<Option<bool>, Option<Vec<u8>>>);
ruby_to_array!(HashMap<Option<bool>, Option<Int>>);
ruby_to_array!(HashMap<Option<bool>, Option<Float>>);
ruby_to_array!(HashMap<Option<bool>, Option<String>>);
ruby_to_array!(HashMap<Option<bool>, Option<&'a str>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Option<Value>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Option<bool>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Option<Vec<u8>>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Option<Int>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Option<Float>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Option<String>>);
ruby_to_array!(HashMap<Option<Vec<u8>>, Option<&'a str>>);
ruby_to_array!(HashMap<Option<Int>, Option<Value>>);
ruby_to_array!(HashMap<Option<Int>, Option<bool>>);
ruby_to_array!(HashMap<Option<Int>, Option<Vec<u8>>>);
ruby_to_array!(HashMap<Option<Int>, Option<Int>>);
ruby_to_array!(HashMap<Option<Int>, Option<Float>>);
ruby_to_array!(HashMap<Option<Int>, Option<String>>);
ruby_to_array!(HashMap<Option<Int>, Option<&'a str>>);
ruby_to_array!(HashMap<Option<String>, Option<Value>>);
ruby_to_array!(HashMap<Option<String>, Option<bool>>);
ruby_to_array!(HashMap<Option<String>, Option<Vec<u8>>>);
ruby_to_array!(HashMap<Option<String>, Option<Int>>);
ruby_to_array!(HashMap<Option<String>, Option<Float>>);
ruby_to_array!(HashMap<Option<String>, Option<String>>);
ruby_to_array!(HashMap<Option<String>, Option<&'a str>>);
ruby_to_array!(HashMap<Option<&'a str>, Option<Value>>);
ruby_to_array!(HashMap<Option<&'a str>, Option<bool>>);
ruby_to_array!(HashMap<Option<&'a str>, Option<Vec<u8>>>);
ruby_to_array!(HashMap<Option<&'a str>, Option<Int>>);
ruby_to_array!(HashMap<Option<&'a str>, Option<Float>>);
ruby_to_array!(HashMap<Option<&'a str>, Option<String>>);
ruby_to_array!(HashMap<Option<&'a str>, Option<&'a str>>);

fn main() {
    println!("Hello, world!");
}

This program spits out compiler errors indicating that the type HashMap is not in scope. Unfortunately, this is the first error that gets emitted and it is lost in the scrollback, even though it is the root cause:

   Compiling demo v0.1.0 (/Users/lopopolo/Desktop/demo)
error[E0412]: cannot find type `HashMap` in this scope
   --> src/main.rs:113:16
    |
113 | array_to_ruby!(HashMap<bool, Value>);
    |                ^^^^^^^ not found in this scope
help: possible candidates are found in other modules, you can import them into scope
    |
1   | use std::collections::HashMap;
    |
1   | use std::collections::hash_map::HashMap;

The errors I am most likely to see when compiling in the console look like this:

error[E0277]: the trait bound `Artichoke: Convert<i64, _>` is not satisfied
  --> src/main.rs:53:38
   |
53 |                     .map(|elem| self.convert(elem))
   |                                      ^^^^^^^ the trait `Convert<i64, _>` is not implemented for `Artichoke`
...
80 | array_to_ruby!(Int);
   | -------------------- in this macro invocation
   |
   = help: the following implementations were found:
             <Artichoke as Convert<std::vec::Vec<&'a str>, Value>>
             <Artichoke as Convert<std::vec::Vec<Value>, Value>>
             <Artichoke as Convert<std::vec::Vec<[type error]>, Value>>
             <Artichoke as Convert<std::vec::Vec<[type error]>, Value>>
           and 164 others

This program takes orders of magnitude longer to (fail to) compile than I would expect it to.

@nathanwhit
Copy link
Member

I believe the slowness described in this issue is an instance of #63478

@Mark-Simulacrum
Copy link
Member

I'm going to close this as a duplicate of #63478 since I think the other problem is sort of unsolveable (we should do better at poisoning, probably, but not exactly sure).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants