Change:
The ABI string for is validated while being parsed, meaning one can get errors about in 'd off modules: (Compiled without .) This isn't necessarily wrong, but it is weird and somewhat annoying if one needs it. (It can be worked-around by hiding the block behind a macro: .)
Any ideas where we could move the check into? Any of borrowck, typeck, lints, privacy and resolve don’t exactly fit. I think trans thematically is the best place to have it, but it is a shame to have it error out so late for such an easy to detect and obvious error. I’m personally fine keeping it a parse error, IMO there’s no reason to have cfg blocks with code that does not compile.
NB. we can add a special pass if necessary (i.e. there's no reason for us to compromise by putting the error in trans). Yeah, of course. However, there are cases when the d code does compile, e.g. I encountered this in where I an ABI and had to use it in inside a module. Similarly, if we add ABIs in future, someone might have code designed to compile with Rust 1.0.0, but can take advantage of the newer ABI if it is available.
The block might be to gate nightly-only code. The code within the gated block is compiled only when a cargo feature is enabled; the code outside it works both on stable and nightly. I hit it myself; I'm playing with the SIMD work from pull request, but I want to keep the crate working on stable. .

Discussion:
} // Determine if a node with the given attributes should be included in this configuation. <del> fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { </del> <ins> pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { </ins> attrs.iter().all(|attr| { // When not compiling with --test we should not compile the #[test] functions if !self.should_test && is_test_or_bench(attr) {

/// Parse a `mod <foo> { ... }` or `mod <foo>;` item fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { <del> let outer_attrs = ::config::StripUnconfigured { config: &self.cfg, sess: self.sess, should_test: false, // irrelevant features: None, // don't perform gated feature checking }.process_cfg_attrs(outer_attrs.to_owned()); </del> <ins> let (in_cfg, outer_attrs) = { let mut strip_unconfigured = ::config::StripUnconfigured { config: &self.cfg, sess: self.sess, should_test: false, // irrelevant features: None, // don't perform gated feature checking }; let outer_attrs = strip_unconfigured.process_cfg_attrs(outer_attrs.to_owned()); (strip_unconfigured.in_cfg(&outer_attrs), outer_attrs) }; </ins> let id_span = self.span; let id = self.parse_ident()?; if self.check(&token::Semi) { self.bump(); <del> // This mod is in an external file. Let's go get it! let (m, attrs) = self.eval_src_mod(id, &outer_attrs, id_span)?; Ok((id, m, Some(attrs))) </del> <ins> if in_cfg { // This mod is in an external file. Let's go get it! let (m, attrs) = self.eval_src_mod(id, &outer_attrs, id_span)?; Ok((id, m, Some(attrs))) } else { let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() }; Ok((id, ItemKind::Mod(placeholder), None)) } </ins> } else { let directory = self.directory.clone(); self.push_directory(id, &outer_attrs);

fn the(&self); } } <ins> #[cfg(any())] mod nonexistent_file; // Check that unconfigured non-inline modules are not loaded or parsed. </ins>