Question:
The expansion of and both currently cause code to fail the stability check because they expand to reveal unstable implementation details. A seemingly reasonable solution to this would be to just not run the analysis on any code that has been macro-expanded. cc
I definitely agree with this approach: we should be able to annotate a macro with a stability level, and that's what should count for its users. Do we have a way of telling what part of an AST was generated via macro expansion by the time we get to linting?
Mostly; there's the field of a : for normal code, for macro generated code (basically containing the backtrace of macro invocations that led to that point).
OK, that makes this sound like a pretty easy fix. I'll take a quick look at it tomorrow (unless wants to?)
Hm, this seems slightly subtle, since the contents of a macro would then never be checked for stability. This differs to a conventional function, e.g. given , won't warn, but the contents of is still checked, while where is just never checked. (Of course, macros and phasing are both feature gated so you have to opt-in to instability to use non-standard macros anyway.)
Good point. Also, it looks tricky with the current infrastructure to even lint on the macro invocation -- the backtrace of macro expansion does not appear to link to the def_id of the macro (or give any other way of getting at the macro's stability). Nevertheless, I think we should bail out of the lint when we hit the results of expansion; those should be checked, if anywhere, at the site of macro definition. One other question: do syntax extensions also produce the span information you mentioned above? I ask because original problematic cases are written syntax extensions. If not, is there some other way of telling that an expansion happened?
I have a patch ready that bails of out the lint on expanded code. This also seems to mask uses of . If y'all are ok with this strategy for now, I'll file a PR.
Sounds good to me. Thanks!
cc

// aux-build:lint_stability.rs // aux-build:inherited_stability.rs <del> #![feature(globs)] </del> <ins> #![feature(globs, phase)] </ins> #![deny(unstable)] #![deny(deprecated)] #![deny(experimental)] #![allow(dead_code)] mod cross_crate { <ins> #[phase(plugin, link)] </ins> extern crate lint_stability; use self::lint_stability::*;


Question:
The expansion of and both currently cause code to fail the stability check because they expand to reveal unstable implementation details. A seemingly reasonable solution to this would be to just not run the analysis on any code that has been macro-expanded. cc
I definitely agree with this approach: we should be able to annotate a macro with a stability level, and that's what should count for its users. Do we have a way of telling what part of an AST was generated via macro expansion by the time we get to linting?
Mostly; there's the field of a : for normal code, for macro generated code (basically containing the backtrace of macro invocations that led to that point).
OK, that makes this sound like a pretty easy fix. I'll take a quick look at it tomorrow (unless wants to?)
Hm, this seems slightly subtle, since the contents of a macro would then never be checked for stability. This differs to a conventional function, e.g. given , won't warn, but the contents of is still checked, while where is just never checked. (Of course, macros and phasing are both feature gated so you have to opt-in to instability to use non-standard macros anyway.)
Good point. Also, it looks tricky with the current infrastructure to even lint on the macro invocation -- the backtrace of macro expansion does not appear to link to the def_id of the macro (or give any other way of getting at the macro's stability). Nevertheless, I think we should bail out of the lint when we hit the results of expansion; those should be checked, if anywhere, at the site of macro definition. One other question: do syntax extensions also produce the span information you mentioned above? I ask because original problematic cases are written syntax extensions. If not, is there some other way of telling that an expansion happened?
I have a patch ready that bails of out the lint on expanded code. This also seems to mask uses of . If y'all are ok with this strategy for now, I'll file a PR.
Sounds good to me. Thanks!
cc

foo.method_locked_text(); foo.trait_locked_text(); let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item let _ = ExperimentalStruct { i: 0 }; //~ ERROR use of experimental item let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable item


Question:
The expansion of and both currently cause code to fail the stability check because they expand to reveal unstable implementation details. A seemingly reasonable solution to this would be to just not run the analysis on any code that has been macro-expanded. cc
I definitely agree with this approach: we should be able to annotate a macro with a stability level, and that's what should count for its users. Do we have a way of telling what part of an AST was generated via macro expansion by the time we get to linting?
Mostly; there's the field of a : for normal code, for macro generated code (basically containing the backtrace of macro invocations that led to that point).
OK, that makes this sound like a pretty easy fix. I'll take a quick look at it tomorrow (unless wants to?)
Hm, this seems slightly subtle, since the contents of a macro would then never be checked for stability. This differs to a conventional function, e.g. given , won't warn, but the contents of is still checked, while where is just never checked. (Of course, macros and phasing are both feature gated so you have to opt-in to instability to use non-standard macros anyway.)
Good point. Also, it looks tricky with the current infrastructure to even lint on the macro invocation -- the backtrace of macro expansion does not appear to link to the def_id of the macro (or give any other way of getting at the macro's stability). Nevertheless, I think we should bail out of the lint when we hit the results of expansion; those should be checked, if anywhere, at the site of macro definition. One other question: do syntax extensions also produce the span information you mentioned above? I ask because original problematic cases are written syntax extensions. If not, is there some other way of telling that an expansion happened?
I have a patch ready that bails of out the lint on expanded code. This also seems to mask uses of . If y'all are ok with this strategy for now, I'll file a PR.
Sounds good to me. Thanks!
cc

let _ = StableTupleStruct (1); let _ = FrozenTupleStruct (1); let _ = LockedTupleStruct (1); <ins> // At the moment, the following just checks that the stability // level of expanded code does not trigger the // lint. Eventually, we will want to lint the contents of the // macro in the module *defining* it. Also, stability levels // on macros themselves are not yet linted. macro_test!(); </ins> } fn test_method_param<F: Trait>(foo: F) {


Question:
Right now we are running 8-core/15GM VMs but only 2 builds at a time, usually with -j2. It seems like we could easily bump this to 3 builds at a time to improve our utilization.
We might also switch back to high-mem instances, which have 30GB RAM, but slightly slower CPU's. That would allow us many more builds.
I've bumped the builds per slave to 3.

**Source:** https://github.com/rust-lang/rust-analyzer/blob/master/crates/rust-analyzer/src/config.rs[config.rs] <del> The <<_installation,Installation>> section contains details on configuration for some of the editors. </del> <ins> The <<installation,Installation>> section contains details on configuration for some of the editors. </ins> In general `rust-analyzer` is configured via LSP messages, which means that it's up to the editor to decide on the exact format and location of configuration files. Some clients, such as <<vs-code,VS Code>> or <<coc-rust-analyzer,COC plugin in Vim>> provide `rust-analyzer` specific configuration UIs. Others may require you to know a bit more about the interaction with `rust-analyzer`.


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

crate_name: crate_name.to_string(), deriving_hash_type_parameter: sess.features.borrow().default_type_params, enable_quotes: sess.features.borrow().quote, <ins> recursion_limit: sess.recursion_limit.get(), </ins> }; let ret = syntax::ext::expand::expand_crate(&sess.parse_sess, cfg,


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

pub exported_macros: Vec<P<ast::Item>>, pub syntax_env: SyntaxEnv, <ins> pub recursion_count: uint, </ins> } impl<'a> ExtCtxt<'a> {


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

trace_mac: false, exported_macros: Vec::new(), syntax_env: env, <ins> recursion_count: 0, </ins> } }


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

return v; } pub fn bt_push(&mut self, ei: ExpnInfo) { <ins> self.recursion_count += 1; if self.recursion_count > self.ecfg.recursion_limit { self.span_fatal(ei.call_site, format!("Recursion limit reached while expanding the macro `{}`", ei.callee.name).as_slice()); } </ins> let mut call_site = ei.call_site; call_site.expn_id = self.backtrace; self.backtrace = self.codemap().record_expansion(ExpnInfo {


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

match self.backtrace { NO_EXPANSION => self.bug("tried to pop without a push"), expn_id => { <ins> self.recursion_count -= 1; </ins> self.backtrace = self.codemap().with_expn_info(expn_id, |expn_info| { expn_info.map_or(NO_EXPANSION, |ei| ei.call_site.expn_id) });


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

pub crate_name: String, pub deriving_hash_type_parameter: bool, pub enable_quotes: bool, <ins> pub recursion_limit: uint, </ins> } impl ExpansionConfig {


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

crate_name: crate_name, deriving_hash_type_parameter: false, enable_quotes: false, <ins> recursion_limit: 64, </ins> } } }


Question:
Defining macros recursively like so will lead rustc to cause a stack overflow. It would be useful to improve the error message for that problem. There is currently no error message specified for that issue.
We already have a field in . We can copy it to libsyntax's and then track the recursion depth in .
I am looking into this issue. Howerver it seems like the same and are used for macro expansion, so it seems like recursion depth cannot be tracked naively.
The methods and already maintain a sort of stack of macro invocations. They can also maintain a counter so that we don't have to walk that stack on every check (it's a kind of indirect linked list).
Now that recursion depth is limited, is there anyway to configure it from the command line? The current depth setting (64?) is too aggressive for some macro magic I am working on, that recurses heavily.
I could at least increase it to 256 if that would help. Other than that someone else ( maybe) should look into it.
My patch did not include any method to customize the depth limit. I just used 64 because defaults to that as well. I am not aware of a command line interface to change session attributes, but I am not very familiar with rustc`s command line interface. Another way to customize the recursion depth for macro expansions could be using something like for macros which result in deeper recursions, but no in an infinite recursion. Anyhow, if there is a decision to do it one way or another, I'd be happy to work on a patch.
Could we at least for now bump the limit up to something much larger? The current setting of 64 is probably too low for macros that rely on reduction rules. (ie that match a portion of a statement and pass the remainder to another macro (often itself) for further expansion). I don't have a good handle on the expense of each macro expansion in terms of compiler memory/time ... but is there any reason for it not to be a number on a much larger scale, such as 1024?
I like the idea of a file/crate attribute to govern the recursion depth of macros expanded within that crate.
I will try to increase it to 2048. Someone else should maybe look into the attribute or command line argument thing.
Seems that 2048 is way to high and already causes stack overflows. If just the compiler wouldn't compile forever...
Seems surprising ... are you changing the to be 2048, or changing it at the level as well?
Just the ExpansionConfig limit, since the session limit won't go crazy way too far. I guess 1024 is still ok for macros. It is compiling and testing right now, so I can tell you more later.
Ah, I misunderstood you, I thought you meant the overflows were happening when compiling the compiler! You mean rather that an infinite recursion test will overflow before it hits the 2048 limit I think.
Yes
I got a workaround, but I guess it is not the best way. Sadly I got ill, so I won't be able to work on it further. Maybe someone else could go on? /cc ()

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(macro_rules)] macro_rules! recursive( () => ( recursive!() //~ ERROR Recursion limit reached while expanding the macro `recursive` ) ) fn main() { recursive!() } </ins>


Question:
Currently a macro cannot create a pub fn. It can however create a regular fn. Fails with:
This is a problem with methods specifically, it works fine if is used to define a normal top-level function (i.e. not inside an ).
Dupe of ?
thanks.


Question:
Here I'm using a fully-realized type that should be FFI safe, but rustc continues to complain:
Closing until I have an example that's actually correct.


Question:
If I'm not mistaken, . It won't terminate the program. It's or unwraps the value. Also, wouldn't a call to the IoResult's  be more direct? Although the custom failure message would be lost.
I thought this was already fixed :/


Question:
If I'm not mistaken, . It won't terminate the program. It's or unwraps the value. Also, wouldn't a call to the IoResult's  be more direct? Although the custom failure message would be lost.
I thought this was already fixed :/

# } fn compute_area(shape: &Shape) -> f64 { match *shape { <del> Circle(_, radius) => 2.0 * std::f64::consts::PI * radius * radius, </del> <ins> Circle(_, radius) => std::f64::consts::PI * radius * radius, </ins> Rectangle(_, ref size) => size.w * size.h } }


Question:
(PR on top of )
seems to work. However, the syntax is awful, and requires a comma for disambiguation.
As of today nightly, that doesn't work anymore. It seems that where clauses don't work with tuple structs anymore. Any plans to support them in the future?
is this the desired syntax? I'm assuming it was chosen in order to do some kind of parsing disambiguation. I am willing to submit a small patch for this, just want clarification on the syntax.
hmm afaik they should work, and I would expect the syntax to be
I will track this one down and follow up with a PR.
You can get the current syntax to compile if the generic type bound uses the trait sugar: Nominating, since we won't be able to move the where clause to after the tuple after 1.0 without breakage.

self.span_err(ty.span, "`virtual` structs have been removed from the language"); } <del> self.parse_where_clause(&mut generics); </del> <ins> // There is a special case worth noting here, as reported in issue #17904. // If we are parsing a tuple struct it is the case that the where clause // should follow the field list. Like so: // // struct Foo<T>(T) where T: Copy; // // If we are parsing a normal record-style struct it is the case // that the where clause comes before the body, and after the generics. // So if we look ahead and see a brace or a where-clause we begin // parsing a record style struct. // // Otherwise if we look ahead and see a paren we parse a tuple-style // struct. let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) { self.parse_where_clause(&mut generics); if self.eat(&token::Semi) { // If we see a: `struct Foo<T> where T: Copy;` style decl. (Vec::new(), Some(ast::DUMMY_NODE_ID)) } else { // If we see: `struct Foo<T> where T: Copy { ... }` (self.parse_record_struct_body(&class_name), None) } // No `where` so: `struct Foo<T>;` } else if self.eat(&token::Semi) { (Vec::new(), Some(ast::DUMMY_NODE_ID)) // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { let fields = self.parse_record_struct_body(&class_name); (fields, None) // Tuple-style struct definition with optional where-clause. } else { let fields = self.parse_tuple_struct_body(&class_name, &mut generics); (fields, Some(ast::DUMMY_NODE_ID)) }; </ins> <del> let mut fields: Vec<StructField>; let is_tuple_like; </del> <ins> (class_name, ItemStruct(P(ast::StructDef { fields: fields, ctor_id: ctor_id, }), generics), None) } pub fn parse_record_struct_body(&mut self, class_name: &ast::Ident) -> Vec<StructField> { let mut fields = Vec::new(); </ins> if self.eat(&token::OpenDelim(token::Brace)) { <del> // It's a record-like struct. is_tuple_like = false; fields = Vec::new(); </del> while self.token != token::CloseDelim(token::Brace) { fields.push(self.parse_struct_decl_field(true)); } if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be  <del> written as `struct {};`", token::get_ident(class_name))[]); </del> <ins> written as `struct {};`", token::get_ident(class_name.clone()))[]); </ins> } self.bump(); <del> } else if self.check(&token::OpenDelim(token::Paren)) { // It's a tuple-like struct. is_tuple_like = true; fields = self.parse_unspanned_seq( </del> <ins> } else { let token_str = self.this_token_to_string(); self.fatal(format!("expected `where`, or `{}` after struct  name, found `{}`", "{", token_str)[]); } fields } pub fn parse_tuple_struct_body(&mut self, class_name: &ast::Ident, generics: &mut ast::Generics) -> Vec<StructField> { // This is the case where we find `struct Foo<T>(T) where T: Copy;` if self.check(&token::OpenDelim(token::Paren)) { let fields = self.parse_unspanned_seq( </ins> &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), |p| { <del> let attrs = p.parse_outer_attributes(); let lo = p.span.lo; let struct_field_ = ast::StructField_ { kind: UnnamedField(p.parse_visibility()), id: ast::DUMMY_NODE_ID, ty: p.parse_ty_sum(), attrs: attrs, }; spanned(lo, p.span.hi, struct_field_) }); </del> <ins> let attrs = p.parse_outer_attributes(); let lo = p.span.lo; let struct_field_ = ast::StructField_ { kind: UnnamedField(p.parse_visibility()), id: ast::DUMMY_NODE_ID, ty: p.parse_ty_sum(), attrs: attrs, }; spanned(lo, p.span.hi, struct_field_) }); </ins> if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be  <del> written as `struct {};`", token::get_ident(class_name))[]); </del> <ins> written as `struct {};`", token::get_ident(class_name.clone()))[]); </ins> } <ins> self.parse_where_clause(generics); </ins> self.expect(&token::Semi); <del> } else if self.eat(&token::Semi) { // It's a unit-like struct. is_tuple_like = true; fields = Vec::new(); </del> <ins> fields // This is the case where we just see struct Foo<T> where T: Copy; } else if self.token.is_keyword(keywords::Where) { self.parse_where_clause(generics); self.expect(&token::Semi); Vec::new() // This case is where we see: `struct Foo<T>;` </ins> } else { let token_str = self.this_token_to_string(); <del> self.fatal(format!("expected `{}`, `(`, or `;` after struct  name, found `{}`", "{", token_str)[]) </del> <ins> self.fatal(format!("expected `where`, `{}`, `(`, or `;` after struct  name, found `{}`", "{", token_str)[]); </ins> } <del> let _ = ast::DUMMY_NODE_ID;  // FIXME: Workaround for crazy bug. let new_id = ast::DUMMY_NODE_ID; (class_name, ItemStruct(P(ast::StructDef { fields: fields, ctor_id: if is_tuple_like { Some(new_id) } else { None }, }), generics), None) </del> } /// Parse a structure field declaration


Question:
(PR on top of )
seems to work. However, the syntax is awful, and requires a comma for disambiguation.
As of today nightly, that doesn't work anymore. It seems that where clauses don't work with tuple structs anymore. Any plans to support them in the future?
is this the desired syntax? I'm assuming it was chosen in order to do some kind of parsing disambiguation. I am willing to submit a small patch for this, just want clarification on the syntax.
hmm afaik they should work, and I would expect the syntax to be
I will track this one down and follow up with a PR.
You can get the current syntax to compile if the generic type bound uses the trait sugar: Nominating, since we won't be able to move the where clause to after the tuple after 1.0 without breakage.

span: codemap::Span) -> IoResult<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); <del> try!(self.print_where_clause(generics)); </del> if ast_util::struct_def_is_tuple_like(struct_def) { if !struct_def.fields.is_empty() { try!(self.popen());


Question:
(PR on top of )
seems to work. However, the syntax is awful, and requires a comma for disambiguation.
As of today nightly, that doesn't work anymore. It seems that where clauses don't work with tuple structs anymore. Any plans to support them in the future?
is this the desired syntax? I'm assuming it was chosen in order to do some kind of parsing disambiguation. I am willing to submit a small patch for this, just want clarification on the syntax.
hmm afaik they should work, and I would expect the syntax to be
I will track this one down and follow up with a PR.
You can get the current syntax to compile if the generic type bound uses the trait sugar: Nominating, since we won't be able to move the where clause to after the tuple after 1.0 without breakage.

)); try!(self.pclose()); } <ins> try!(self.print_where_clause(generics)); </ins> try!(word(&mut self.s, ";")); try!(self.end()); self.end() // close the outer-box } else { <ins> try!(self.print_where_clause(generics)); </ins> try!(self.nbsp()); try!(self.bopen()); try!(self.hardbreak_if_not_bol());


Question:
(PR on top of )
seems to work. However, the syntax is awful, and requires a comma for disambiguation.
As of today nightly, that doesn't work anymore. It seems that where clauses don't work with tuple structs anymore. Any plans to support them in the future?
is this the desired syntax? I'm assuming it was chosen in order to do some kind of parsing disambiguation. I am willing to submit a small patch for this, just want clarification on the syntax.
hmm afaik they should work, and I would expect the syntax to be
I will track this one down and follow up with a PR.
You can get the current syntax to compile if the generic type bound uses the trait sugar: Nominating, since we won't be able to move the where clause to after the tuple after 1.0 without breakage.

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well. struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well. struct Foo<T> where T: Copy, (T); //~ ERROR unexpected token in `where` clause struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where` fn main() {} </ins>


Question:
(PR on top of )
seems to work. However, the syntax is awful, and requires a comma for disambiguation.
As of today nightly, that doesn't work anymore. It seems that where clauses don't work with tuple structs anymore. Any plans to support them in the future?
is this the desired syntax? I'm assuming it was chosen in order to do some kind of parsing disambiguation. I am willing to submit a small patch for this, just want clarification on the syntax.
hmm afaik they should work, and I would expect the syntax to be
I will track this one down and follow up with a PR.
You can get the current syntax to compile if the generic type bound uses the trait sugar: Nominating, since we won't be able to move the where clause to after the tuple after 1.0 without breakage.

// Test syntax checks for `type` keyword. <del> struct S1 for type; //~ ERROR expected `{`, `(`, or `;` after struct name, found `for` </del> <ins> struct S1 for type; //~ ERROR expected `where`, `{`, `(`, or `;` after struct name, found `for` </ins> pub fn main() { }


Question:
(PR on top of )
seems to work. However, the syntax is awful, and requires a comma for disambiguation.
As of today nightly, that doesn't work anymore. It seems that where clauses don't work with tuple structs anymore. Any plans to support them in the future?
is this the desired syntax? I'm assuming it was chosen in order to do some kind of parsing disambiguation. I am willing to submit a small patch for this, just want clarification on the syntax.
hmm afaik they should work, and I would expect the syntax to be
I will track this one down and follow up with a PR.
You can get the current syntax to compile if the generic type bound uses the trait sugar: Nominating, since we won't be able to move the where clause to after the tuple after 1.0 without breakage.

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. struct Foo<T> where T: Copy; struct Bar<T>(T) where T: Copy; struct Bleh<T, U>(T, U) where T: Copy, U: Sized; struct Baz<T> where T: Copy { field: T } fn main() {} </ins>


Question:
This should say Undefinedfn foo() -Undefined {}` does.
triage: still true today
As of the error is I will add a regression test so this issue can be closed.

<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. impl Undefined {} //~^ ERROR use of undeclared type name `Undefined` fn main() {} </ins>


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

AssignmentLhsSized,        // L = X implies that L is Sized StructInitializerSized,    // S { ... } must be Sized VariableType(ast::NodeId), // Type of each variable must be Sized <ins> ReturnType,                // Return type must be Sized </ins> RepeatVec,                 // [T,..n] --> T must be Copy // Captures of variable the given id by a closure (span is the


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

// Remember return type so that regionck can access it later. let fn_sig_tys: Vec<ty::t> = <del> arg_tys.iter() .chain([ret_ty].iter()) .map(|&ty| ty) .collect(); </del> <ins> arg_tys.iter().chain([ret_ty].iter()).map(|&ty| ty).collect(); </ins> debug!("fn-sig-map: fn_id={} fn_sig_tys={}", fn_id, fn_sig_tys.repr(tcx)); <del> inherited.fn_sig_map .borrow_mut() .insert(fn_id, fn_sig_tys); </del> <ins> inherited.fn_sig_map.borrow_mut().insert(fn_id, fn_sig_tys); </ins> { let mut visit = GatherLocalsVisitor { fcx: &fcx, };


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

visit.visit_block(body); } <ins> fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType); </ins> check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

traits::RepeatVec => { tcx.sess.span_note( obligation.cause.span, <del> format!( "the `Copy` trait is required because the  repeated element will be copied").as_slice()); </del> <ins> "the `Copy` trait is required because the  repeated element will be copied"); </ins> } traits::VariableType(_) => { tcx.sess.span_note( obligation.cause.span, "all local variables must have a statically known size"); } <ins> traits::ReturnType => { tcx.sess.span_note( obligation.cause.span, "the return type of a function must have a  statically known size"); } </ins> traits::AssignmentLhsSized => { tcx.sess.span_note( obligation.cause.span,


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

#![no_std] #![feature(lang_items)] <ins> #[lang="sized"] pub trait Sized for Sized? {} </ins> #[lang="fail"] fn fail(_: &(&'static str, &'static str, uint)) -> ! { loop {} }


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

C([Box<A>]), } <del> fn c(c:char) -> A { B(c) //~ ERROR cannot move a value of type A: the size of A cannot be statically determined </del> <ins> fn c(c:char) { B(c); //~^ ERROR cannot move a value of type A: the size of A cannot be statically determined </ins> } pub fn main() {}


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. pub trait AbstractRenderer {} fn _create_render(_: &()) -> AbstractRenderer //~^ ERROR: the trait `core::kinds::Sized` is not implemented { match 0u { _ => unimplemented!() } } fn main() { } </ins>


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

r: A+'static } <del> fn new_struct(r: A+'static) -> Struct { </del> <ins> fn new_struct(r: A+'static) -> Struct { //~^  ERROR the trait `core::kinds::Sized` is not implemented </ins> //~^ ERROR the trait `core::kinds::Sized` is not implemented Struct { r: r } //~^ ERROR the trait `core::kinds::Sized` is not implemented


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

// option. This file may not be copied, modified, or distributed // except according to those terms. <del> #![feature(globs)] </del> <ins> #![feature(globs, lang_items)] </ins> #![no_std] // makes debugging this test *a lot* easier (during resolve) <ins> #[lang = "sized"] pub trait Sized for Sized? {} </ins> // Test to make sure that private items imported through globs remain private // when  they're used.


Question:
The following code causes an ICE: Removing the parameter or changing it to be a value instead of a reference stops the crash with an error saying I need to specify a lifetime, which makes me think this is a problem related to inferred lifetimes.
It isn't, you just have to specify a lifetime: ICE-s as well. Returning an unsized type should be a typeck error.
happens to work because it implies , i.e. would also work.

// option. This file may not be copied, modified, or distributed // except according to those terms. <ins> #![feature(lang_items)] </ins> #![no_std] <ins> #[lang="sized"] pub trait Sized for Sized? {} </ins> // error-pattern:requires `start` lang_item fn main() {}


Question:
There are 3 cases of this undefined behaviour in : There is no guarantee that and have the same layout under the new rules. This needs to manually copy over the fields one by one which would compile to the same code as long as a feature like struct randomization wasn't enabled. Since vectors expose , it could be switched to make use of that. However, this is a pervasive issue with in the standard libraries.
I would like to fix this one. However, I don't understand why you would need to use . If we need to copy everything, why don't we do it directly to a ?
the fields of Vec are private, so you can't just use

#[inline] unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> { <del> let v: Vec<u8> = mem::transmute(self); v.into_ascii_nocheck() </del> <ins> self.into_bytes().into_ascii_nocheck() </ins> } }


Question:
There are 3 cases of this undefined behaviour in : There is no guarantee that and have the same layout under the new rules. This needs to manually copy over the fields one by one which would compile to the same code as long as a feature like struct randomization wasn't enabled. Since vectors expose , it could be switched to make use of that. However, this is a pervasive issue with in the standard libraries.
I would like to fix this one. However, I don't understand why you would need to use . If we need to copy everything, why don't we do it directly to a ?
the fields of Vec are private, so you can't just use

#[inline] unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> { <del> mem::transmute(self) </del> <ins> let v = Vec::from_raw_parts(self.len(), self.capacity(), mem::transmute(self.as_ptr())); // We forget `self` to avoid freeing it at the end of the scope // Otherwise, the returned `Vec` would point to freed memory mem::forget(self); v </ins> } }


Question:
There are 3 cases of this undefined behaviour in : There is no guarantee that and have the same layout under the new rules. This needs to manually copy over the fields one by one which would compile to the same code as long as a feature like struct randomization wasn't enabled. Since vectors expose , it could be switched to make use of that. However, this is a pervasive issue with in the standard libraries.
I would like to fix this one. However, I don't understand why you would need to use . If we need to copy everything, why don't we do it directly to a ?
the fields of Vec are private, so you can't just use

impl IntoBytes for Vec<Ascii> { fn into_bytes(self) -> Vec<u8> { <del> unsafe { mem::transmute(self) } </del> <ins> unsafe { let v = Vec::from_raw_parts(self.len(), self.capacity(), mem::transmute(self.as_ptr())); // We forget `self` to avoid freeing it at the end of the scope // Otherwise, the returned `Vec` would point to freed memory mem::forget(self); v } </ins> } }


Question:
On the latest nightly (previously it worked fine) Rust fails to compile this code: It emits this error message: I managed to strip it down to this example: It fails to compile with this error: If is replaced with , then it compiles fine, so the error seems to be related to matching on s.
Sorry for the breakage, fix on its way.

let const_did = tcx.def_map.borrow().get_copy(&pat.id).def_id(); let const_pty = ty::lookup_item_type(tcx, const_did); fcx.write_ty(pat.id, const_pty.ty); <del> demand::eqtype(fcx, pat.span, expected, const_pty.ty); </del> <ins> demand::suptype(fcx, pat.span, expected, const_pty.ty); </ins> } ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => { let typ = fcx.local_ty(pat.span, pat.id);


Question:
On the latest nightly (previously it worked fine) Rust fails to compile this code: It emits this error message: I managed to strip it down to this example: It fails to compile with this error: If is replaced with , then it compiles fine, so the error seems to be related to matching on s.
Sorry for the breakage, fix on its way.

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. const X: &'static str = "12345"; fn test(s: String) -> bool { match s.as_slice() { X => true, _ => false } } fn main() { assert!(test("12345".to_string())); } </ins>


Question:
Right now the Int and Integer traits imply PartialOrd but not Ord. Is there a reason for this? It seems like integers do have a total order, not just partial. I asked on IRC and people seemed to think Int should imply Ord. If this is correct I can send a pull request?
Yup :)
I have two questions: May I ask what is the trait? Couldn't find any in the std doc: Did you mean  () when you wrote "the trait"? But it doesn't even inherit . Am I missing something?
The trait is in .
Ah, it was the big int code separated from the std lib! Thanks. I also overlooked implemented , implying . Sorry for the noise!

use {uint, u8, u16, u32, u64}; use {f32, f64}; use clone::Clone; <del> use cmp::{PartialEq, PartialOrd}; </del> <ins> use cmp::{Ord, PartialEq, PartialOrd}; </ins> use kinds::Copy; use mem::size_of; use ops::{Add, Sub, Mul, Div, Rem, Neg};


Question:
Right now the Int and Integer traits imply PartialOrd but not Ord. Is there a reason for this? It seems like integers do have a total order, not just partial. I asked on IRC and people seemed to think Int should imply Ord. If this is correct I can send a pull request?
Yup :)
I have two questions: May I ask what is the trait? Couldn't find any in the std doc: Did you mean  () when you wrote "the trait"? But it doesn't even inherit . Am I missing something?
The trait is in .
Ah, it was the big int code separated from the std lib! Thanks. I also overlooked implemented , implying . Sorry for the noise!

/// A primitive signed or unsigned integer equipped with various bitwise /// operators, bit counting methods, and endian conversion functions. pub trait Int: Primitive <ins> + Ord </ins> + CheckedAdd + CheckedSub + CheckedMul


Question:
In we had the submitter change a to an as follows: We felt that better communicated the intent of "this code should never panic assuming that the implementation is correct" (as opposed to , which communicates "this code should never panic assuming that the user passes in the correct inputs" (cf. indexing, division) and is generally to be avoided in the stdlib). However, I think it's a shame that by expressing the intent more clearly in the code we're simultaneously losing information regarding which invariant was violated in order to reach the unreachable code. Note that this isn't really a huge deal, because we can just move the "Invalid SearchStack" bit over into a comment next to . It's also not really a huge deal for the theoretical bug reporter who's filing an issue upon hitting this code, since still includes a filename and line number in its output. However, given the precedent of optional messages set by , I don't think it would be a stretch to imagine that could also have an optional message. Usage for the typical case would be the same: could optionally look like this:
I'll have a go at implementing this.

/// ``` #[macro_export] macro_rules! unreachable( <del> () => (panic!("internal error: entered unreachable code")) </del> <ins> () => ({ panic!("internal error: entered unreachable code") }); ($msg:expr) => ({ unreachable!("{}", $msg) }); ($fmt:expr, $($arg:tt)*) => ({ panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) }); </ins> ) /// A standardised placeholder for marking unfinished code. It panics with the


Question:
In we had the submitter change a to an as follows: We felt that better communicated the intent of "this code should never panic assuming that the implementation is correct" (as opposed to , which communicates "this code should never panic assuming that the user passes in the correct inputs" (cf. indexing, division) and is generally to be avoided in the stdlib). However, I think it's a shame that by expressing the intent more clearly in the code we're simultaneously losing information regarding which invariant was violated in order to reach the unreachable code. Note that this isn't really a huge deal, because we can just move the "Invalid SearchStack" bit over into a comment next to . It's also not really a huge deal for the theoretical bug reporter who's filing an issue upon hitting this code, since still includes a filename and line number in its output. However, given the precedent of optional messages set by , I don't think it would be a stretch to imagine that could also have an optional message. Usage for the typical case would be the same: could optionally look like this:
I'll have a go at implementing this.

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // error-pattern:internal error: entered unreachable code: 6 is not prime fn main() { unreachable!("{} is not {}", 6u32, "prime"); } </ins>


Question:
In we had the submitter change a to an as follows: We felt that better communicated the intent of "this code should never panic assuming that the implementation is correct" (as opposed to , which communicates "this code should never panic assuming that the user passes in the correct inputs" (cf. indexing, division) and is generally to be avoided in the stdlib). However, I think it's a shame that by expressing the intent more clearly in the code we're simultaneously losing information regarding which invariant was violated in order to reach the unreachable code. Note that this isn't really a huge deal, because we can just move the "Invalid SearchStack" bit over into a comment next to . It's also not really a huge deal for the theoretical bug reporter who's filing an issue upon hitting this code, since still includes a filename and line number in its output. However, given the precedent of optional messages set by , I don't think it would be a stretch to imagine that could also have an optional message. Usage for the typical case would be the same: could optionally look like this:
I'll have a go at implementing this.

<del> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // error-pattern:internal error: entered unreachable code fn main() { unreachable!() } </del>


Question:
In we had the submitter change a to an as follows: We felt that better communicated the intent of "this code should never panic assuming that the implementation is correct" (as opposed to , which communicates "this code should never panic assuming that the user passes in the correct inputs" (cf. indexing, division) and is generally to be avoided in the stdlib). However, I think it's a shame that by expressing the intent more clearly in the code we're simultaneously losing information regarding which invariant was violated in order to reach the unreachable code. Note that this isn't really a huge deal, because we can just move the "Invalid SearchStack" bit over into a comment next to . It's also not really a huge deal for the theoretical bug reporter who's filing an issue upon hitting this code, since still includes a filename and line number in its output. However, given the precedent of optional messages set by , I don't think it would be a stretch to imagine that could also have an optional message. Usage for the typical case would be the same: could optionally look like this:
I'll have a go at implementing this.

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // error-pattern:internal error: entered unreachable code: uhoh fn main() { unreachable!("uhoh") } </ins>


Question:
In we had the submitter change a to an as follows: We felt that better communicated the intent of "this code should never panic assuming that the implementation is correct" (as opposed to , which communicates "this code should never panic assuming that the user passes in the correct inputs" (cf. indexing, division) and is generally to be avoided in the stdlib). However, I think it's a shame that by expressing the intent more clearly in the code we're simultaneously losing information regarding which invariant was violated in order to reach the unreachable code. Note that this isn't really a huge deal, because we can just move the "Invalid SearchStack" bit over into a comment next to . It's also not really a huge deal for the theoretical bug reporter who's filing an issue upon hitting this code, since still includes a filename and line number in its output. However, given the precedent of optional messages set by , I don't think it would be a stretch to imagine that could also have an optional message. Usage for the typical case would be the same: could optionally look like this:
I'll have a go at implementing this.

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // error-pattern:internal error: entered unreachable code fn main() { unreachable!() } </ins>


Question:
Backtrace:
Well, this is interesting. It's broken all the way back to 0.10. I think it's been a bug in the type id implementation since it first landed. Here's a smaller test case:
is there a particular reason explicitly checks that all regions it encounters are ? Trans doesn't seem to go out of its way to erase late-bound regions in fn type signatures, which results in this ICE. I could add a call to in trans to fix this, but it would be cheaper to just ignore regions during hashing.
Ended up catching me
It seems we actually want to take late-bound regions into account when hashing. For example, the following should hold:

/// context it's calculated within. This is used by the `type_id` intrinsic. pub fn hash_crate_independent(tcx: &ctxt, ty: Ty, svh: &Svh) -> u64 { let mut state = sip::SipState::new(); <del> macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } ); macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } ); let region = |_state: &mut sip::SipState, r: Region| { match r { ReStatic => {} ReEmpty | ReEarlyBound(..) | ReLateBound(..) | ReFree(..) | ReScope(..) | ReInfer(..) => { tcx.sess.bug("non-static region found when hashing a type") </del> <ins> helper(tcx, ty, svh, &mut state); return state.result(); fn helper(tcx: &ctxt, ty: Ty, svh: &Svh, state: &mut sip::SipState) { macro_rules! byte( ($b:expr) => { ($b as u8).hash(state) } ); macro_rules! hash( ($e:expr) => { $e.hash(state) } ); let region = |state: &mut sip::SipState, r: Region| { match r { ReStatic => {} ReLateBound(db, BrAnon(i)) => { db.hash(state); i.hash(state); } ReEmpty | ReEarlyBound(..) | ReLateBound(..) | ReFree(..) | ReScope(..) | ReInfer(..) => { tcx.sess.bug("unexpected region found when hashing a type") } </ins> } <del> } }; let did = |state: &mut sip::SipState, did: DefId| { let h = if ast_util::is_local(did) { svh.clone() } else { tcx.sess.cstore.get_crate_hash(did.krate) </del> }; <del> h.as_str().hash(state); did.node.hash(state); }; let mt = |state: &mut sip::SipState, mt: mt| { mt.mutbl.hash(state); }; ty::walk_ty(ty, |ty| { match ty.sty { ty_bool => byte!(2), ty_char => byte!(3), ty_int(i) => { byte!(4); hash!(i); } ty_uint(u) => { byte!(5); hash!(u); } ty_float(f) => { byte!(6); hash!(f); } ty_str => { byte!(7); } ty_enum(d, _) => { byte!(8); did(&mut state, d); } ty_uniq(_) => { byte!(9); } ty_vec(_, Some(n)) => { byte!(10); n.hash(&mut state); } ty_vec(_, None) => { byte!(11); } ty_ptr(m) => { byte!(12); mt(&mut state, m); } ty_rptr(r, m) => { byte!(13); region(&mut state, r); mt(&mut state, m); } ty_bare_fn(ref b) => { byte!(14); hash!(b.unsafety); hash!(b.abi); </del> <ins> let did = |state: &mut sip::SipState, did: DefId| { let h = if ast_util::is_local(did) { svh.clone() } else { tcx.sess.cstore.get_crate_hash(did.krate) }; h.as_str().hash(state); did.node.hash(state); }; let mt = |state: &mut sip::SipState, mt: mt| { mt.mutbl.hash(state); }; let fn_sig = |state: &mut sip::SipState, sig: &FnSig| { let sig = anonymize_late_bound_regions(tcx, sig); for a in sig.inputs.iter() { helper(tcx, *a, svh, state); } if let ty::FnConverging(output) = sig.output { helper(tcx, output, svh, state); </ins> } <del> ty_closure(ref c) => { byte!(15); hash!(c.unsafety); hash!(c.onceness); hash!(c.bounds); match c.store { UniqTraitStore => byte!(0), RegionTraitStore(r, m) => { byte!(1) region(&mut state, r); assert_eq!(m, ast::MutMutable); </del> <ins> }; maybe_walk_ty(ty, |ty| { match ty.sty { ty_bool => byte!(2), ty_char => byte!(3), ty_int(i) => { byte!(4); hash!(i); } ty_uint(u) => { byte!(5); hash!(u); } ty_float(f) => { byte!(6); hash!(f); } ty_str => { byte!(7); } ty_enum(d, _) => { byte!(8); did(state, d); } ty_uniq(_) => { byte!(9); } ty_vec(_, Some(n)) => { byte!(10); n.hash(state); } ty_vec(_, None) => { byte!(11); } ty_ptr(m) => { byte!(12); mt(state, m); } ty_rptr(r, m) => { byte!(13); region(state, r); mt(state, m); } ty_bare_fn(ref b) => { byte!(14); hash!(b.unsafety); hash!(b.abi); fn_sig(state, &b.sig); return false; } ty_closure(ref c) => { byte!(15); hash!(c.unsafety); hash!(c.onceness); hash!(c.bounds); match c.store { UniqTraitStore => byte!(0), RegionTraitStore(r, m) => { byte!(1); region(state, r); assert_eq!(m, ast::MutMutable); } </ins> } <ins> fn_sig(state, &c.sig); return false; </ins> } <del> } ty_trait(box TyTrait { ref principal, bounds }) => { byte!(17); did(&mut state, principal.def_id); hash!(bounds); } ty_struct(d, _) => { byte!(18); did(&mut state, d); } ty_tup(ref inner) => { byte!(19); hash!(inner.len()); } ty_param(p) => { byte!(20); hash!(p.idx); did(&mut state, p.def_id); } ty_open(_) => byte!(22), ty_infer(_) => unreachable!(), ty_err => byte!(23), ty_unboxed_closure(d, r, _) => { byte!(24); did(&mut state, d); region(&mut state, r); } } }); </del> <ins> ty_trait(box TyTrait { ref principal, bounds }) => { byte!(17); did(state, principal.def_id); hash!(bounds); let principal = anonymize_late_bound_regions(tcx, principal); for subty in principal.substs.types.iter() { helper(tcx, *subty, svh, state); } </ins> <del> state.result() </del> <ins> return false; } ty_struct(d, _) => { byte!(18); did(state, d); } ty_tup(ref inner) => { byte!(19); hash!(inner.len()); } ty_param(p) => { byte!(20); hash!(p.idx); did(state, p.def_id); } ty_open(_) => byte!(22), ty_infer(_) => unreachable!(), ty_err => byte!(23), ty_unboxed_closure(d, r, _) => { byte!(24); did(state, d); region(state, r); } } true }); } </ins> } impl Variance {


Question:
Backtrace:
Well, this is interesting. It's broken all the way back to 0.10. I think it's been a bug in the type id implementation since it first landed. Here's a smaller test case:
is there a particular reason explicitly checks that all regions it encounters are ? Trans doesn't seem to go out of its way to erase late-bound regions in fn type signatures, which results in this ICE. I could add a call to in trans to fix this, but it would be cheaper to just ignore regions during hashing.
Ended up catching me
It seems we actually want to take late-bound regions into account when hashing. For example, the following should hold:

replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic).0 } <ins> /// Rewrite any late-bound regions so that they are anonymous.  Region numbers are /// assigned starting at 1 and increasing monotonically in the order traversed /// by the fold operation. /// /// The chief purpose of this function is to canonicalize regions so that two /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become /// structurally identical.  For example, `for<'a, 'b> fn(&'a int, &'b int)` and /// `for<'a, 'b> fn(&'b int, &'a int)` will become identical after anonymization. pub fn anonymize_late_bound_regions<'tcx, HR>(tcx: &ctxt<'tcx>, sig: &HR) -> HR where HR: HigherRankedFoldable<'tcx> { let mut counter = 0; replace_late_bound_regions(tcx, sig, |_, db| { counter += 1; ReLateBound(db, BrAnon(counter)) }).0 } </ins> /// Replaces the late-bound-regions in `value` that are bound by `value`. pub fn replace_late_bound_regions<'tcx, HR, F>( tcx: &ty::ctxt<'tcx>,


Question:
Backtrace:
Well, this is interesting. It's broken all the way back to 0.10. I think it's been a bug in the type id implementation since it first landed. Here's a smaller test case:
is there a particular reason explicitly checks that all regions it encounters are ? Trans doesn't seem to go out of its way to erase late-bound regions in fn type signatures, which results in this ICE. I could add a call to in trans to fix this, but it would be cheaper to just ignore regions during hashing.
Ended up catching me
It seems we actually want to take late-bound regions into account when hashing. For example, the following should hold:

fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> IoResult<()> { if !t.bound_lifetimes.is_empty() { try!(word(&mut self.s, "for<")); <ins> let mut comma = false; </ins> for lifetime_def in t.bound_lifetimes.iter() { <ins> if comma { try!(self.word_space(",")) } </ins> try!(self.print_lifetime_def(lifetime_def)); <ins> comma = true; </ins> } try!(word(&mut self.s, ">")); }


Question:
Backtrace:
Well, this is interesting. It's broken all the way back to 0.10. I think it's been a bug in the type id implementation since it first landed. Here's a smaller test case:
is there a particular reason explicitly checks that all regions it encounters are ? Trans doesn't seem to go out of its way to erase late-bound regions in fn type signatures, which results in this ICE. I could add a call to in trans to fix this, but it would be cheaper to just ignore regions during hashing.
Ended up catching me
It seems we actually want to take late-bound regions into account when hashing. For example, the following should hold:

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Test that type IDs correctly account for higher-rank lifetimes // Also acts as a regression test for an ICE (issue #19791) #![feature(unboxed_closures)] use std::intrinsics::TypeId; fn main() { // Bare fns { let a = TypeId::of::<fn(&'static int, &'static int)>(); let b = TypeId::of::<for<'a> fn(&'static int, &'a int)>(); let c = TypeId::of::<for<'a, 'b> fn(&'a int, &'b int)>(); let d = TypeId::of::<for<'a, 'b> fn(&'b int, &'a int)>(); assert!(a != b); assert!(a != c); assert!(a != d); assert!(b != c); assert!(b != d); assert_eq!(c, d); // Make sure De Bruijn indices are handled correctly let e = TypeId::of::<for<'a> fn(fn(&'a int) -> &'a int)>(); let f = TypeId::of::<fn(for<'a> fn(&'a int) -> &'a int)>(); assert!(e != f); } // Stack closures { let a = TypeId::of::<|&'static int, &'static int|>(); let b = TypeId::of::<for<'a> |&'static int, &'a int|>(); let c = TypeId::of::<for<'a, 'b> |&'a int, &'b int|>(); let d = TypeId::of::<for<'a, 'b> |&'b int, &'a int|>(); assert!(a != b); assert!(a != c); assert!(a != d); assert!(b != c); assert!(b != d); assert_eq!(c, d); // Make sure De Bruijn indices are handled correctly let e = TypeId::of::<for<'a> |(|&'a int| -> &'a int)|>(); let f = TypeId::of::<|for<'a> |&'a int| -> &'a int|>(); assert!(e != f); } // Boxed unboxed closures { let a = TypeId::of::<Box<Fn(&'static int, &'static int)>>(); let b = TypeId::of::<Box<for<'a> Fn(&'static int, &'a int)>>(); let c = TypeId::of::<Box<for<'a, 'b> Fn(&'a int, &'b int)>>(); let d = TypeId::of::<Box<for<'a, 'b> Fn(&'b int, &'a int)>>(); assert!(a != b); assert!(a != c); assert!(a != d); assert!(b != c); assert!(b != d); assert_eq!(c, d); // Make sure De Bruijn indices are handled correctly let e = TypeId::of::<Box<for<'a> Fn(Box<Fn(&'a int) -> &'a int>)>>(); let f = TypeId::of::<Box<Fn(Box<for<'a> Fn(&'a int) -> &'a int>)>>(); assert!(e != f); } // Raw unboxed closures // Note that every unboxed closure has its own anonymous type, // so no two IDs should equal each other, even when compatible { let a = id(|&: _: &int, _: &int| {}); let b = id(|&: _: &int, _: &int| {}); assert!(a != b); } fn id<T:'static>(_: T) -> TypeId { TypeId::of::<T>() } } </ins>


Question:
Info located at: Looking at the source code in libcollections there doesn't seem to be such a method alltogether.
This would be fixed by The new way is

* [Iterators](iterators.md) * [Generics](generics.md) * [Traits](traits.md) <del> * [Threads](threads.md) </del> <ins> * [Concurrency](concurrency.md) </ins> * [Error Handling](error-handling.md) * [Documentation](documentation.md) * [III: Advanced Topics](advanced.md)


Question:
Info located at: Looking at the source code in libcollections there doesn't seem to be such a method alltogether.
This would be fixed by The new way is

<ins> % Concurrency Concurrency and parallelism are incredibly important topics in computer science, and are also a hot topic in industry today. Computers are gaining more and more cores, yet many programmers aren't prepared to fully utilize them. Rust's memory safety features also apply to its concurrency story too. Even concurrent Rust programs must be memory safe, having no data races. Rust's type system is up to the task, and gives you powerful ways to reason about concurrent code at compile time. Before we talk about the concurrency features that come with Rust, it's important to understand something: Rust is low-level enough that all of this is provided by the standard library, not by the language. This means that if you don't like some aspect of the way Rust handles concurrency, you can implement an alternative way of doing things. [mio](https://github.com/carllerche/mio) is a real-world example of this principle in action. ## Background: `Send` and `Sync` Concurrency is difficult to reason about. In Rust, we have a strong, static type system to help us reason about our code. As such, Rust gives us two traits to help us make sense of code that can possibly be concurrent. ### `Send` The first trait we're going to talk about is [`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it indicates to the compiler that something of this type is able to have ownership transferred safely between threads. This is important to enforce certain restrictions. For example, if we have a channel connecting two threads, we would want to be able to send some data down the channel and to the other thread. Therefore, we'd ensure that `Send` was implemented for that type. In the opposite way, if we were wrapping a library with FFI that isn't threadsafe, we wouldn't want to implement `Send`, and so the compiler will help us enforce that it can't leave the current thread. ### `Sync` The second of these two trait is called [`Sync`](../std/marker/trait.Sync.html). When a type `T` implements `Sync`, it indicates to the compiler that something of this type has no possibility of introducing memory unsafety when used from multiple threads concurrently. For example, sharing immutable data with an atomic reference count is threadsafe. Rust provides a type like this, `Arc<T>`, and it implements `Sync`, so that it could be safely shared between threads. These two traits allow you to use the type system to make strong guarantees about the properties of your code under concurrency. Before we demonstrate why, we need to learn how to create a concurrent Rust program in the first place! ## Threads Rust's standard library provides a library for 'threads', which allow you to run Rust code in parallel. Here's a basic example of using `Thread`: ``` use std::thread::Thread; fn main() { Thread::scoped(|| { println!("Hello from a thread!"); }); } ``` The `Thread::scoped()` method accepts a closure, which is executed in a new thread. It's called `scoped` because this thread returns a join guard: ``` use std::thread::Thread; fn main() { let guard = Thread::scoped(|| { println!("Hello from a thread!"); }); // guard goes out of scope here } ``` When `guard` goes out of scope, it will block execution until the thread is finished. If we didn't want this behaviour, we could use `Thread::spawn()`: ``` use std::thread::Thread; use std::old_io::timer; use std::time::Duration; fn main() { Thread::spawn(|| { println!("Hello from a thread!"); }); timer::sleep(Duration::milliseconds(50)); } ``` Or call `.detach()`: ``` use std::thread::Thread; use std::old_io::timer; use std::time::Duration; fn main() { let guard = Thread::scoped(|| { println!("Hello from a thread!"); }); guard.detach(); timer::sleep(Duration::milliseconds(50)); } ``` We need to `sleep` here because when `main()` ends, it kills all of the running threads. [`scoped`](std/thread/struct.Builder.html#method.scoped) has an interesting type signature: ```text fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T> where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a ``` Specifically, `F`, the closure that we pass to execute in the new thread. It has two restrictions: It must be a `FnOnce` from `()` to `T`. Using `FnOnce` allows the closure to take ownership of any data it mentions from the parent thread. The other restriction is that `F` must be `Send`. We aren't allowed to transfer this ownership unless the type thinks that's okay. Many languages have the ability to execute threads, but it's wildly unsafe. There are entire books about how to prevent errors that occur from shared mutable state. Rust helps out with its type system here as well, by preventing data races at compile time. Let's talk about how you actually share things between threads. ## Safe Shared Mutable State Due to Rust's type system, we have a concept that sounds like a lie: "safe shared mutable state." Many programmers agree that shared mutable state is very, very bad. Someone once said this: > Shared mutable state is the root of all evil. Most languages attempt to deal > with this problem through the 'mutable' part, but Rust deals with it by > solving the 'shared' part. The same [ownership system](ownership.html) that helps prevent using pointers incorrectly also helps rule out data races, one of the worst kinds of concurrency bugs. As an example, here is a Rust program that would have a data race in many languages. It will not compile: ```ignore use std::thread::Thread; use std::old_io::timer; use std::time::Duration; fn main() { let mut data = vec![1u32, 2, 3]; for i in 0 .. 2 { Thread::spawn(move || { data[i] += 1; }); } timer::sleep(Duration::milliseconds(50)); } ``` This gives us an error: ```text 12:17 error: capture of moved value: `data` data[i] += 1; ^~~~ ``` In this case, we know that our code _should_ be safe, but Rust isn't sure. And it's actually not safe: if we had a reference to `data` in each thread, and the thread takes ownership of the reference, we have three owners! That's bad. We can fix this by using the `Arc<T>` type, which is an atomic reference counted pointer. The 'atomic' part means that it's safe to share across threads. `Arc<T>` assumes one more property about its contents to ensure that it is safe to share across threads: it assumes its contents are `Sync`. But in our case, we want to be able to mutate the value. We need a type that can ensure only one person at a time can mutate what's inside. For that, we can use the `Mutex<T>` type. Here's the second version of our code. It still doesn't work, but for a different reason: ```ignore use std::thread::Thread; use std::old_io::timer; use std::time::Duration; use std::sync::Mutex; fn main() { let mut data = Mutex::new(vec![1u32, 2, 3]); for i in 0 .. 2 { let data = data.lock().unwrap(); Thread::spawn(move || { data[i] += 1; }); } timer::sleep(Duration::milliseconds(50)); } ``` Here's the error: ```text <anon>:11:9: 11:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277] <anon>:11         Thread::spawn(move || { ^~~~~~~~~~~~~ <anon>:11:9: 11:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely <anon>:11         Thread::spawn(move || { ^~~~~~~~~~~~~ ``` You see, [`Mutex`](std/sync/struct.Mutex.html) has a [`lock`](http://doc.rust-lang.org/nightly/std/sync/struct.Mutex.html#method.lock) method which has this signature: ```ignore fn lock(&self) -> LockResult<MutexGuard<T>> ``` If we [look at the code for MutexGuard](https://github.com/rust-lang/rust/blob/ca4b9674c26c1de07a2042cb68e6a062d7184cef/src/libstd/sync/mutex.rs#L172), we'll see this: ```ignore __marker: marker::NoSend, ``` Because our guard is `NoSend`, it's not `Send`. Which means we can't actually transfer the guard across thread boundaries, which gives us our error. We can use `Arc<T>` to fix this. Here's the working version: ``` use std::sync::{Arc, Mutex}; use std::thread::Thread; use std::old_io::timer; use std::time::Duration; fn main() { let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); for i in (0us..2) { let data = data.clone(); Thread::spawn(move || { let mut data = data.lock().unwrap(); data[i] += 1; }); } timer::sleep(Duration::milliseconds(50)); } ``` We now call `clone()` on our `Arc`, which increases the internal count. This handle is then moved into the new thread. Let's examine the body of the thread more closely: ``` # use std::sync::{Arc, Mutex}; # use std::thread::Thread; # use std::old_io::timer; # use std::time::Duration; # fn main() { #     let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); #     for i in (0us..2) { #         let data = data.clone(); Thread::spawn(move || { let mut data = data.lock().unwrap(); data[i] += 1; }); #     } # } ``` First, we call `lock()`, which acquires the mutex's lock. Because this may fail, it returns an `Result<T, E>`, and because this is just an example, we `unwrap()` it to get a reference to the data. Real code would have more robust error handling here. We're then free to mutate it, since we have the lock. This timer bit is a bit awkward, however. We have picked a reasonable amount of time to wait, but it's entirely possible that we've picked too high, and that we could be taking less time. It's also possible that we've picked too low, and that we aren't actually finishing this computation. Rust's standard library provides a few more mechanisms for two threads to synchronize with each other. Let's talk about one: channels. ## Channels Here's a version of our code that uses channels for synchronization, rather than waiting for a specific time: ``` use std::sync::{Arc, Mutex}; use std::thread::Thread; use std::sync::mpsc; fn main() { let data = Arc::new(Mutex::new(0u32)); let (tx, rx) = mpsc::channel(); for _ in (0..10) { let (data, tx) = (data.clone(), tx.clone()); Thread::spawn(move || { let mut data = data.lock().unwrap(); *data += 1; tx.send(()); }); } for _ in 0 .. 10 { rx.recv(); } } ``` We use the `mpsc::channel()` method to construct a new channel. We just `send` a simple `()` down the channel, and then wait for ten of them to come back. While this channel is just sending a generic signal, we can send any data that is `Send` over the channel! ``` use std::sync::{Arc, Mutex}; use std::thread::Thread; use std::sync::mpsc; fn main() { let (tx, rx) = mpsc::channel(); for _ in range(0, 10) { let tx = tx.clone(); Thread::spawn(move || { let answer = 42u32; tx.send(answer); }); } rx.recv().ok().expect("Could not recieve answer"); } ``` A `u32` is `Send` because we can make a copy. So we create a thread, ask it to calculate the answer, and then it `send()`s us the answer over the channel. ## Panics A `panic!` will crash the currently executing thread. You can use Rust's threads as a simple isolation mechanism: ``` use std::thread::Thread; let result = Thread::scoped(move || { panic!("oops!"); }).join(); assert!(result.is_err()); ``` Our `Thread` gives us a `Result` back, which allows us to check if the thread has panicked or not. </ins>