diff --git a/configure b/configure index 9e65bc789b4c5..d0c85c0a008be 100755 --- a/configure +++ b/configure @@ -1635,8 +1635,8 @@ do ("ccache gcc") LLVM_CXX_32="ccache" LLVM_CC_32="ccache" - LLVM_CXX_32_ARG1="clang++" - LLVM_CC_32_ARG1="clang" + LLVM_CXX_32_ARG1="g++" + LLVM_CC_32_ARG1="gcc" LLVM_CXX_64="ccache" LLVM_CC_64="ccache" diff --git a/src/doc/reference.md b/src/doc/reference.md index 08ff982d4d73b..84f459bf8724f 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2472,8 +2472,7 @@ The currently implemented features of the reference compiler are: * - `default_type_parameter_fallback` - Allows type parameter defaults to influence type inference. -* - `stmt_expr_attributes` - Allows attributes on expressions and - non-item statements. +* - `stmt_expr_attributes` - Allows attributes on expressions. * - `type_ascription` - Allows type ascription expressions `expr: Type`. diff --git a/src/libcore/any.rs b/src/libcore/any.rs index a3018a46eea22..f7edcb998a927 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -73,7 +73,6 @@ use fmt; use intrinsics; -use marker::Reflect; /////////////////////////////////////////////////////////////////////////////// // Any trait @@ -86,7 +85,7 @@ use marker::Reflect; /// /// [mod]: index.html #[stable(feature = "rust1", since = "1.0.0")] -pub trait Any: Reflect + 'static { +pub trait Any: 'static { /// Gets the `TypeId` of `self`. /// /// # Examples @@ -112,7 +111,7 @@ pub trait Any: Reflect + 'static { } #[stable(feature = "rust1", since = "1.0.0")] -impl Any for T { +impl Any for T { fn get_type_id(&self) -> TypeId { TypeId::of::() } } @@ -366,7 +365,7 @@ impl TypeId { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn of() -> TypeId { + pub fn of() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::() }, } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1ae4cf8e5ef5f..28101d21fc25e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -89,7 +89,7 @@ #![feature(specialization)] #![feature(staged_api)] #![feature(unboxed_closures)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(never_type)] #![feature(prelude_import)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 99c24e4c48d44..6e08abd346143 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -255,6 +255,9 @@ macro_rules! debug_assert_ne { /// Helper macro for reducing boilerplate code for matching `Result` together /// with converting downstream errors. /// +/// Prefer using `?` syntax to `try!`. `?` is built in to the language and is +/// more succinct than `try!`. It is the standard method for error propagation. +/// /// `try!` matches the given `Result`. In case of the `Ok` variant, the /// expression has the value of the wrapped value. /// diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 5a1a034a36358..03d8af1563d6d 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -587,6 +587,7 @@ mod impls { #[unstable(feature = "reflect_marker", reason = "requires RFC and more experience", issue = "27749")] +#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")] #[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \ ensure all type parameters are bounded by `Any`"] pub trait Reflect {} @@ -594,4 +595,6 @@ pub trait Reflect {} #[unstable(feature = "reflect_marker", reason = "requires RFC and more experience", issue = "27749")] +#[rustc_deprecated(since = "1.14.0", reason = "Specialization makes parametricity impossible")] +#[allow(deprecated)] impl Reflect for .. { } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 74cc498a7df23..95c46ec5715e7 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -295,7 +295,7 @@ #![cfg_attr(not(stage0), deny(warnings))] #![feature(str_escape)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] use self::LabelText::*; diff --git a/src/liblibc b/src/liblibc index 5a17b4a733a22..ebeab042e6bb1 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 5a17b4a733a22d445fdd63326f826fcd8a584328 +Subproject commit ebeab042e6bb14a447627b57ed9a493e2cc0e095 diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index de68cc707ad7a..12a1a4255246a 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1327,30 +1327,6 @@ let x: i32 = "I am not a number!"; // | // type `i32` assigned to variable `x` ``` - -Another situation in which this occurs is when you attempt to use the `try!` -macro inside a function that does not return a `Result`: - -```compile_fail,E0308 -use std::fs::File; - -fn main() { - let mut f = try!(File::create("foo.txt")); -} -``` - -This code gives an error like this: - -```text -:5:8: 6:42 error: mismatched types: - expected `()`, - found `core::result::Result<_, _>` - (expected (), - found enum `core::result::Result`) [E0308] -``` - -`try!` returns a `Result`, and so the function must. But `main()` has -`()` as its return type, hence the error. "##, E0309: r##" diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index bca3ed9381202..137c6b58dc998 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -94,13 +94,7 @@ pub fn lower_crate(sess: &Session, let _ignore = sess.dep_graph.in_ignore(); LoweringContext { - crate_root: if std_inject::no_core(krate) { - None - } else if std_inject::no_std(krate) { - Some("core") - } else { - Some("std") - }, + crate_root: std_inject::injected_crate_name(krate), sess: sess, parent_def: None, resolver: resolver, diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index c34286f0195bf..25731df477853 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -40,7 +40,7 @@ #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![cfg_attr(test, feature(test))] extern crate arena; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index f706bab32c80a..d002aba595bca 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -118,6 +118,8 @@ pub struct PerfStats { pub incr_comp_hashes_time: Cell, // The number of incr. comp. hash computations performed pub incr_comp_hashes_count: Cell, + // The number of bytes hashed when computing ICH values + pub incr_comp_bytes_hashed: Cell, // The accumulated time spent on computing symbol hashes pub symbol_hash_time: Cell, } @@ -439,6 +441,11 @@ impl Session { duration_to_secs_str(self.perf_stats.incr_comp_hashes_time.get())); println!("Total number of incr. comp. hashes computed: {}", self.perf_stats.incr_comp_hashes_count.get()); + println!("Total number of bytes hashed for incr. comp.: {}", + self.perf_stats.incr_comp_bytes_hashed.get()); + println!("Average bytes hashed per incr. comp. HIR node: {}", + self.perf_stats.incr_comp_bytes_hashed.get() / + self.perf_stats.incr_comp_hashes_count.get()); println!("Total time spent computing symbol hashes: {}", duration_to_secs_str(self.perf_stats.symbol_hash_time.get())); } @@ -571,6 +578,7 @@ pub fn build_session_(sopts: config::Options, svh_time: Cell::new(Duration::from_secs(0)), incr_comp_hashes_time: Cell::new(Duration::from_secs(0)), incr_comp_hashes_count: Cell::new(0), + incr_comp_bytes_hashed: Cell::new(0), symbol_hash_time: Cell::new(Duration::from_secs(0)), } }; diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index c0f358ca8017b..e6d1982d31c2d 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -37,7 +37,7 @@ #![feature(rustc_private)] #![feature(staged_api)] #![feature(step_by)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![cfg_attr(test, feature(test, rand))] extern crate syntax; diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs index 91be50d11f952..f6260527039d0 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs @@ -12,6 +12,8 @@ use syntax::ast::NodeId; use rustc::mir::repr::{BasicBlock, Mir}; +use rustc_data_structures::bitslice::bits_to_string; +use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; use dot; @@ -27,8 +29,6 @@ use std::path::Path; use super::super::MoveDataParamEnv; use super::super::MirBorrowckCtxtPreDataflow; -use bitslice::bits_to_string; -use indexed_set::{IdxSet}; use super::{BitDenotation, DataflowState}; impl DataflowState { diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index 55dda8eda3a4a..dce167975cf34 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -10,6 +10,9 @@ use rustc::ty::TyCtxt; use rustc::mir::repr::{self, Mir, Location}; +use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. +use rustc_data_structures::bitslice::{BitwiseOperator}; +use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; use super::super::gather_moves::{MoveOutIndex, MovePathIndex}; @@ -21,10 +24,6 @@ use super::super::on_lookup_result_bits; use super::{BitDenotation, BlockSets, DataflowOperator}; -use bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. -use bitslice::{BitwiseOperator}; -use indexed_set::{IdxSet}; - // Dataflow analyses are built upon some interpretation of the // bitvectors attached to each basic block, represented via a // zero-sized structure. diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs index a9b4de450967c..0c510e95b67fe 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::bitslice::{bitwise, BitwiseOperator}; use rustc::ty::TyCtxt; use rustc::mir::repr::{self, Mir}; @@ -22,9 +24,6 @@ use std::usize; use super::MirBorrowckCtxtPreDataflow; use super::MoveDataParamEnv; -use bitslice::{bitwise, BitwiseOperator}; -use indexed_set::{IdxSet, IdxSetBuf}; - pub use self::sanity_check::sanity_check_via_rustc_peek; pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 188fce467be52..25986b85f7b3a 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use indexed_set::IdxSetBuf; use super::gather_moves::{MoveData, MovePathIndex, LookupResult}; use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use super::dataflow::{DataflowResults}; @@ -23,6 +22,7 @@ use rustc::mir::transform::{Pass, MirPass, MirSource}; use rustc::middle::const_val::ConstVal; use rustc::middle::lang_items; use rustc::util::nodemap::FnvHashMap; +use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; use syntax_pos::Span; diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 22b590592fe16..da899714e9351 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -26,7 +26,7 @@ #![feature(staged_api)] #![feature(associated_consts)] #![feature(nonzero)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; extern crate syntax_pos; @@ -50,8 +50,6 @@ pub use borrowck::{AnalysisData, BorrowckCtxt, ElaborateDrops}; pub mod diagnostics; mod borrowck; -mod bitslice; -mod indexed_set; pub mod graphviz; diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index d876b4b6fec2e..81dd642de5d27 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -732,6 +732,10 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir::BiBitOr => a | b, hir::BiEq => a == b, hir::BiNe => a != b, + hir::BiLt => a < b, + hir::BiLe => a <= b, + hir::BiGe => a >= b, + hir::BiGt => a > b, _ => signal!(e, InvalidOpForBools(op.node)), }) } diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index f926fef065ea6..7b40269ba56ad 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -27,7 +27,7 @@ #![feature(staged_api)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 741dd4107e001..31fccb41ce573 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -25,7 +25,7 @@ #![feature(rustc_private)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_borrowck/bitslice.rs b/src/librustc_data_structures/bitslice.rs similarity index 98% rename from src/librustc_borrowck/bitslice.rs rename to src/librustc_data_structures/bitslice.rs index 80fa86a007ed3..ba53578e57918 100644 --- a/src/librustc_borrowck/bitslice.rs +++ b/src/librustc_data_structures/bitslice.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: move this to `rustc_data_structures` and potentially merge -// with `bitvec` there. +// FIXME: merge with `bitvec` use std::mem; diff --git a/src/librustc_borrowck/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs similarity index 98% rename from src/librustc_borrowck/indexed_set.rs rename to src/librustc_data_structures/indexed_set.rs index 671aff97d20aa..2e9e054e97eaf 100644 --- a/src/librustc_borrowck/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -8,16 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: move this to `rustc_data_structures` - use std::fmt; use std::marker::PhantomData; use std::mem; use std::ops::{Deref, DerefMut, Range}; use bitslice::{BitSlice, Word}; use bitslice::{bitwise, Union, Subtract}; - -use rustc_data_structures::indexed_vec::Idx; +use indexed_vec::Idx; /// Represents a set (or packed family of sets), of some element type /// E, where each E is identified by some unique index type `T`. diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index e7da18cef10f9..c8f4d766153cf 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -41,9 +41,11 @@ extern crate serialize as rustc_serialize; // used by deriving #[cfg(unix)] extern crate libc; +pub mod bitslice; pub mod bitvec; pub mod graph; pub mod ivar; +pub mod indexed_set; pub mod indexed_vec; pub mod obligation_forest; pub mod snapshot_map; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ea42f7ba93e44..e8ab2f3a2405b 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -649,7 +649,7 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, let resolver_arenas = Resolver::arenas(); let mut resolver = Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas); - syntax_ext::register_builtins(&mut resolver, sess.features.borrow().quote); + syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote); krate = time(time_passes, "expansion", || { // Windows dlls do not have rpaths, so they don't know how to find their @@ -686,11 +686,17 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, ..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string()) }; let mut ecx = ExtCtxt::new(&sess.parse_sess, krate.config.clone(), cfg, &mut resolver); - let ret = syntax::ext::expand::expand_crate(&mut ecx, syntax_exts, krate); + let err_count = ecx.parse_sess.span_diagnostic.err_count(); + + let krate = ecx.monotonic_expander().expand_crate(krate); + + if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count { + ecx.parse_sess.span_diagnostic.abort_if_errors(); + } if cfg!(windows) { env::set_var("PATH", &old_path); } - ret + krate }); krate.exported_macros = mem::replace(&mut resolver.exported_macros, Vec::new()); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 492165e2f2a8e..f051c8692491f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -31,7 +31,7 @@ #![feature(rustc_private)] #![feature(set_stdio)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] extern crate arena; extern crate flate; @@ -1110,7 +1110,7 @@ pub fn monitor(f: F) { errors::Level::Note); } - println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap()); + writeln!(io::stderr(), "{}", str::from_utf8(&data.lock().unwrap()).unwrap()).unwrap(); } exit_on_err(); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index bc599a8207656..af8ac81b4fbb1 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -21,7 +21,7 @@ #![allow(unused_attributes)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(range_contains)] #![feature(libc)] #![feature(unicode)] diff --git a/src/librustc_incremental/calculate_svh/hasher.rs b/src/librustc_incremental/calculate_svh/hasher.rs new file mode 100644 index 0000000000000..28db39d667c4c --- /dev/null +++ b/src/librustc_incremental/calculate_svh/hasher.rs @@ -0,0 +1,46 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::hash::Hasher; +use std::collections::hash_map::DefaultHasher; + +#[derive(Debug)] +pub struct IchHasher { + // FIXME: this should use SHA1, not DefaultHasher. DefaultHasher is not + // built to avoid collisions. + state: DefaultHasher, + bytes_hashed: u64, +} + +impl IchHasher { + pub fn new() -> IchHasher { + IchHasher { + state: DefaultHasher::new(), + bytes_hashed: 0 + } + } + + pub fn bytes_hashed(&self) -> u64 { + self.bytes_hashed + } +} + +impl Hasher for IchHasher { + #[inline] + fn finish(&self) -> u64 { + self.state.finish() + } + + #[inline] + fn write(&mut self, bytes: &[u8]) { + self.state.write(bytes); + self.bytes_hashed += bytes.len() as u64; + } +} diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index a22b51ac04461..12627e02debd0 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -30,7 +30,6 @@ use syntax::ast; use std::cell::RefCell; use std::hash::{Hash, Hasher}; -use std::collections::hash_map::DefaultHasher; use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; @@ -43,10 +42,12 @@ use rustc::session::config::DebugInfoLevel::NoDebugInfo; use self::def_path_hash::DefPathHashes; use self::svh_visitor::StrictVersionHashVisitor; use self::caching_codemap_view::CachingCodemapView; +use self::hasher::IchHasher; mod def_path_hash; mod svh_visitor; mod caching_codemap_view; +mod hasher; pub struct IncrementalHashesMap { hashes: FnvHashMap, u64>, @@ -74,6 +75,10 @@ impl IncrementalHashesMap { pub fn iter<'a>(&'a self) -> ::std::collections::hash_map::Iter<'a, DepNode, u64> { self.hashes.iter() } + + pub fn len(&self) -> usize { + self.hashes.len() + } } impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { @@ -102,6 +107,9 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) |v| visit::walk_crate(v, krate)); krate.visit_all_items(&mut visitor); }); + + tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64); + record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash()); visitor.hashes } @@ -127,9 +135,7 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> { { assert!(def_id.is_local()); debug!("HashItemsVisitor::calculate(def_id={:?})", def_id); - // FIXME: this should use SHA1, not DefaultHasher. DefaultHasher is not - // built to avoid collisions. - let mut state = DefaultHasher::new(); + let mut state = IchHasher::new(); walk_op(&mut StrictVersionHashVisitor::new(&mut state, self.tcx, &mut self.def_path_hashes, @@ -138,12 +144,16 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> { let item_hash = state.finish(); self.hashes.insert(DepNode::Hir(def_id), item_hash); debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, item_hash); + + let bytes_hashed = self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() + + state.bytes_hashed(); + self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed); } fn compute_crate_hash(&mut self) { let krate = self.tcx.map.krate(); - let mut crate_state = DefaultHasher::new(); + let mut crate_state = IchHasher::new(); let crate_disambiguator = self.tcx.sess.local_crate_disambiguator(); "crate_disambiguator".hash(&mut crate_state); diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 3df68ac583d46..584e5598b9f9f 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -31,10 +31,10 @@ use rustc::hir::intravisit as visit; use rustc::ty::TyCtxt; use rustc_data_structures::fnv; use std::hash::Hash; -use std::collections::hash_map::DefaultHasher; use super::def_path_hash::DefPathHashes; use super::caching_codemap_view::CachingCodemapView; +use super::hasher::IchHasher; const IGNORED_ATTRIBUTES: &'static [&'static str] = &[ "cfg", @@ -48,7 +48,7 @@ const IGNORED_ATTRIBUTES: &'static [&'static str] = &[ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> { pub tcx: TyCtxt<'hash, 'tcx, 'tcx>, - pub st: &'a mut DefaultHasher, + pub st: &'a mut IchHasher, // collect a deterministic hash of def-ids that we have seen def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>, hash_spans: bool, @@ -56,7 +56,7 @@ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> { } impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { - pub fn new(st: &'a mut DefaultHasher, + pub fn new(st: &'a mut IchHasher, tcx: TyCtxt<'hash, 'tcx, 'tcx>, def_path_hashes: &'a mut DefPathHashes<'hash, 'tcx>, codemap: &'a mut CachingCodemapView<'tcx>, diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 2c1340e566dda..67104e912f90e 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -20,7 +20,7 @@ #![cfg_attr(not(stage0), deny(warnings))] #![feature(dotdot_in_tuple_patterns)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(rustc_private)] #![feature(staged_api)] #![feature(rand)] diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 84d65308f952f..acb92bec7c797 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -24,19 +24,21 @@ use rustc::hir::intravisit::FnKind; pub enum MethodLateContext { TraitDefaultImpl, TraitImpl, - PlainImpl + PlainImpl, } pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext { let def_id = cx.tcx.map.local_def_id(id); match cx.tcx.impl_or_trait_items.borrow().get(&def_id) { None => span_bug!(span, "missing method descriptor?!"), - Some(item) => match item.container() { - ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl, - ty::ImplContainer(cid) => { - match cx.tcx.impl_trait_ref(cid) { - Some(_) => MethodLateContext::TraitImpl, - None => MethodLateContext::PlainImpl + Some(item) => { + match item.container() { + ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl, + ty::ImplContainer(cid) => { + match cx.tcx.impl_trait_ref(cid) { + Some(_) => MethodLateContext::TraitImpl, + None => MethodLateContext::PlainImpl, + } } } } @@ -63,19 +65,20 @@ impl NonCamelCaseTypes { // start with a non-lowercase letter rather than non-uppercase // ones (some scripts don't have a concept of upper/lowercase) - !name.is_empty() && - !name.chars().next().unwrap().is_lowercase() && - !name.contains('_') + !name.is_empty() && !name.chars().next().unwrap().is_lowercase() && !name.contains('_') } fn to_camel_case(s: &str) -> String { - s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)| - if i == 0 { - c.to_uppercase().collect::() - } else { - c.to_lowercase().collect() - } - )).collect::>().concat() + s.split('_') + .flat_map(|word| { + word.chars().enumerate().map(|(i, c)| if i == 0 { + c.to_uppercase().collect::() + } else { + c.to_lowercase().collect() + }) + }) + .collect::>() + .concat() } let s = name.as_str(); @@ -83,9 +86,14 @@ impl NonCamelCaseTypes { if !is_camel_case(name) { let c = to_camel_case(&s); let m = if c.is_empty() { - format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s) + format!("{} `{}` should have a camel case name such as `CamelCase`", + sort, + s) } else { - format!("{} `{}` should have a camel case name such as `{}`", sort, s, c) + format!("{} `{}` should have a camel case name such as `{}`", + sort, + s, + c) }; cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]); } @@ -100,10 +108,14 @@ impl LintPass for NonCamelCaseTypes { impl LateLintPass for NonCamelCaseTypes { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - let extern_repr_count = it.attrs.iter().filter(|attr| { - attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter() - .any(|r| r == &attr::ReprExtern) - }).count(); + let extern_repr_count = it.attrs + .iter() + .filter(|attr| { + attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr) + .iter() + .any(|r| r == &attr::ReprExtern) + }) + .count(); let has_extern_repr = extern_repr_count > 0; if has_extern_repr { @@ -111,12 +123,10 @@ impl LateLintPass for NonCamelCaseTypes { } match it.node { - hir::ItemTy(..) | hir::ItemStruct(..) | hir::ItemUnion(..) => { - self.check_case(cx, "type", it.name, it.span) - } - hir::ItemTrait(..) => { - self.check_case(cx, "trait", it.name, it.span) - } + hir::ItemTy(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) => self.check_case(cx, "type", it.name, it.span), + hir::ItemTrait(..) => self.check_case(cx, "trait", it.name, it.span), hir::ItemEnum(ref enum_definition, _) => { if has_extern_repr { return; @@ -126,7 +136,7 @@ impl LateLintPass for NonCamelCaseTypes { self.check_case(cx, "variant", variant.node.name, variant.span); } } - _ => () + _ => (), } } @@ -165,9 +175,7 @@ impl NonSnakeCase { continue; } for ch in s.chars() { - if !buf.is_empty() && buf != "'" - && ch.is_uppercase() - && !last_upper { + if !buf.is_empty() && buf != "'" && ch.is_uppercase() && !last_upper { words.push(buf); buf = String::new(); } @@ -205,10 +213,11 @@ impl NonSnakeCase { let sc = NonSnakeCase::to_snake_case(name); let msg = if sc != name { format!("{} `{}` should have a snake case name such as `{}`", - sort, name, sc) + sort, + name, + sc) } else { - format!("{} `{}` should have a snake case name", - sort, name) + format!("{} `{}` should have a snake case name", sort, name) }; match span { Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg), @@ -226,8 +235,10 @@ impl LintPass for NonSnakeCase { impl LateLintPass for NonSnakeCase { fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) { - let attr_crate_name = cr.attrs.iter().find(|at| at.check_name("crate_name")) - .and_then(|at| at.value_str().map(|s| (at, s))); + let attr_crate_name = cr.attrs + .iter() + .find(|at| at.check_name("crate_name")) + .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref name) = cx.tcx.sess.opts.crate_name { self.check_snake_case(cx, "crate", name, None); } else if let Some((attr, ref name)) = attr_crate_name { @@ -235,22 +246,28 @@ impl LateLintPass for NonSnakeCase { } } - fn check_fn(&mut self, cx: &LateContext, - fk: FnKind, _: &hir::FnDecl, - _: &hir::Block, span: Span, id: ast::NodeId) { + fn check_fn(&mut self, + cx: &LateContext, + fk: FnKind, + _: &hir::FnDecl, + _: &hir::Block, + span: Span, + id: ast::NodeId) { match fk { - FnKind::Method(name, ..) => match method_context(cx, id, span) { - MethodLateContext::PlainImpl => { - self.check_snake_case(cx, "method", &name.as_str(), Some(span)) - }, - MethodLateContext::TraitDefaultImpl => { - self.check_snake_case(cx, "trait method", &name.as_str(), Some(span)) - }, - _ => (), - }, + FnKind::Method(name, ..) => { + match method_context(cx, id, span) { + MethodLateContext::PlainImpl => { + self.check_snake_case(cx, "method", &name.as_str(), Some(span)) + } + MethodLateContext::TraitDefaultImpl => { + self.check_snake_case(cx, "trait method", &name.as_str(), Some(span)) + } + _ => (), + } + } FnKind::ItemFn(name, ..) => { self.check_snake_case(cx, "function", &name.as_str(), Some(span)) - }, + } FnKind::Closure(_) => (), } } @@ -263,13 +280,17 @@ impl LateLintPass for NonSnakeCase { fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if let hir::MethodTraitItem(_, None) = trait_item.node { - self.check_snake_case(cx, "trait method", &trait_item.name.as_str(), + self.check_snake_case(cx, + "trait method", + &trait_item.name.as_str(), Some(trait_item.span)); } } fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) { - self.check_snake_case(cx, "lifetime", &t.lifetime.name.as_str(), + self.check_snake_case(cx, + "lifetime", + &t.lifetime.name.as_str(), Some(t.lifetime.span)); } @@ -282,8 +303,12 @@ impl LateLintPass for NonSnakeCase { } } - fn check_struct_def(&mut self, cx: &LateContext, s: &hir::VariantData, - _: ast::Name, _: &hir::Generics, _: ast::NodeId) { + fn check_struct_def(&mut self, + cx: &LateContext, + s: &hir::VariantData, + _: ast::Name, + _: &hir::Generics, + _: ast::NodeId) { for sf in s.fields() { self.check_snake_case(cx, "structure field", &sf.name.as_str(), Some(sf.span)); } @@ -306,13 +331,16 @@ impl NonUpperCaseGlobals { if s.chars().any(|c| c.is_lowercase()) { let uc = NonSnakeCase::to_snake_case(&s).to_uppercase(); if uc != &s[..] { - cx.span_lint(NON_UPPER_CASE_GLOBALS, span, - &format!("{} `{}` should have an upper case name such as `{}`", - sort, s, uc)); + cx.span_lint(NON_UPPER_CASE_GLOBALS, + span, + &format!("{} `{}` should have an upper case name such as `{}`", + sort, + s, + uc)); } else { - cx.span_lint(NON_UPPER_CASE_GLOBALS, span, - &format!("{} `{}` should have an upper case name", - sort, s)); + cx.span_lint(NON_UPPER_CASE_GLOBALS, + span, + &format!("{} `{}` should have an upper case name", sort, s)); } } } @@ -341,8 +369,7 @@ impl LateLintPass for NonUpperCaseGlobals { fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) { match ti.node { hir::ConstTraitItem(..) => { - NonUpperCaseGlobals::check_upper_case(cx, "associated constant", - ti.name, ti.span); + NonUpperCaseGlobals::check_upper_case(cx, "associated constant", ti.name, ti.span); } _ => {} } @@ -351,8 +378,7 @@ impl LateLintPass for NonUpperCaseGlobals { fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) { match ii.node { hir::ImplItemKind::Const(..) => { - NonUpperCaseGlobals::check_upper_case(cx, "associated constant", - ii.name, ii.span); + NonUpperCaseGlobals::check_upper_case(cx, "associated constant", ii.name, ii.span); } _ => {} } @@ -363,8 +389,10 @@ impl LateLintPass for NonUpperCaseGlobals { if let PatKind::Path(None, ref path) = p.node { if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() { if let Def::Const(..) = cx.tcx.expect_def(p.id) { - NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", - path.segments[0].name, path.span); + NonUpperCaseGlobals::check_upper_case(cx, + "constant in pattern", + path.segments[0].name, + path.span); } } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index b610a924a3396..3428ec8d4c960 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -37,15 +37,15 @@ use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::adjustment; use rustc::traits::{self, Reveal}; use rustc::hir::map as hir_map; -use util::nodemap::{NodeSet}; +use util::nodemap::NodeSet; use lint::{Level, LateContext, LintContext, LintArray, Lint}; use lint::{LintPass, LateLintPass}; use std::collections::HashSet; -use syntax::{ast}; +use syntax::ast; use syntax::attr; -use syntax_pos::{Span}; +use syntax_pos::Span; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::FnKind; @@ -75,7 +75,8 @@ impl LateLintPass for WhileTrue { if let hir::ExprWhile(ref cond, ..) = e.node { if let hir::ExprLit(ref lit) = cond.node { if let ast::LitKind::Bool(true) = lit.node { - cx.span_lint(WHILE_TRUE, e.span, + cx.span_lint(WHILE_TRUE, + e.span, "denote infinite loops with loop { ... }"); } } @@ -93,8 +94,7 @@ declare_lint! { pub struct BoxPointers; impl BoxPointers { - fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'a, 'tcx>, - span: Span, ty: Ty<'tcx>) { + fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) { for leaf_ty in ty.walk() { if let ty::TyBox(_) = leaf_ty.sty { let m = format!("type uses owned (Box type) pointers: {}", ty); @@ -117,10 +117,8 @@ impl LateLintPass for BoxPointers { hir::ItemTy(..) | hir::ItemEnum(..) | hir::ItemStruct(..) | - hir::ItemUnion(..) => - self.check_heap_type(cx, it.span, - cx.tcx.node_id_to_type(it.id)), - _ => () + hir::ItemUnion(..) => self.check_heap_type(cx, it.span, cx.tcx.node_id_to_type(it.id)), + _ => (), } // If it's a struct, we also have to check the fields' types @@ -128,11 +126,12 @@ impl LateLintPass for BoxPointers { hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { for struct_field in struct_def.fields() { - self.check_heap_type(cx, struct_field.span, + self.check_heap_type(cx, + struct_field.span, cx.tcx.node_id_to_type(struct_field.id)); } } - _ => () + _ => (), } } @@ -166,9 +165,11 @@ impl LateLintPass for NonShorthandFieldPatterns { } if let PatKind::Binding(_, ident, None) = fieldpat.node.pat.node { if ident.node == fieldpat.node.name { - cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, + cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, + fieldpat.span, &format!("the `{}:` in this pattern is redundant and can \ - be removed", ident.node)) + be removed", + ident.node)) } } } @@ -203,27 +204,35 @@ impl LateLintPass for UnsafeCode { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { - hir::ItemTrait(hir::Unsafety::Unsafe, ..) => - cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"), + hir::ItemTrait(hir::Unsafety::Unsafe, ..) => { + cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait") + } - hir::ItemImpl(hir::Unsafety::Unsafe, ..) => - cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait"), + hir::ItemImpl(hir::Unsafety::Unsafe, ..) => { + cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait") + } _ => return, } } - fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl, - _: &hir::Block, span: Span, _: ast::NodeId) { + fn check_fn(&mut self, + cx: &LateContext, + fk: FnKind, + _: &hir::FnDecl, + _: &hir::Block, + span: Span, + _: ast::NodeId) { match fk { - FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, ..) => - cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"), + FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, ..) => { + cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function") + } FnKind::Method(_, sig, ..) => { if sig.unsafety == hir::Unsafety::Unsafe { cx.span_lint(UNSAFE_CODE, span, "implementation of an `unsafe` method") } - }, + } _ => (), } @@ -232,7 +241,8 @@ impl LateLintPass for UnsafeCode { fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if let hir::MethodTraitItem(ref sig, None) = trait_item.node { if sig.unsafety == hir::Unsafety::Unsafe { - cx.span_lint(UNSAFE_CODE, trait_item.span, + cx.span_lint(UNSAFE_CODE, + trait_item.span, "declaration of an `unsafe` method") } } @@ -263,9 +273,9 @@ pub struct MissingDoc { impl MissingDoc { pub fn new() -> MissingDoc { MissingDoc { - struct_def_stack: vec!(), + struct_def_stack: vec![], in_variant: false, - doc_hidden_stack: vec!(false), + doc_hidden_stack: vec![false], private_traits: HashSet::new(), } } @@ -275,11 +285,11 @@ impl MissingDoc { } fn check_missing_docs_attrs(&self, - cx: &LateContext, - id: Option, - attrs: &[ast::Attribute], - sp: Span, - desc: &'static str) { + cx: &LateContext, + id: Option, + attrs: &[ast::Attribute], + sp: Span, + desc: &'static str) { // If we're building a test harness, then warning about // documentation is probably not really relevant right now. if cx.sess().opts.test { @@ -302,7 +312,8 @@ impl MissingDoc { let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc"); if !has_doc { - cx.span_lint(MISSING_DOCS, sp, + cx.span_lint(MISSING_DOCS, + sp, &format!("missing documentation for {}", desc)); } } @@ -316,8 +327,10 @@ impl LintPass for MissingDoc { impl LateLintPass for MissingDoc { fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) { - let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { - attr.check_name("doc") && match attr.meta_item_list() { + let doc_hidden = self.doc_hidden() || + attrs.iter().any(|attr| { + attr.check_name("doc") && + match attr.meta_item_list() { None => false, Some(l) => attr::list_contains_name(&l[..], "hidden"), } @@ -329,13 +342,21 @@ impl LateLintPass for MissingDoc { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_struct_def(&mut self, _: &LateContext, _: &hir::VariantData, - _: ast::Name, _: &hir::Generics, item_id: ast::NodeId) { + fn check_struct_def(&mut self, + _: &LateContext, + _: &hir::VariantData, + _: ast::Name, + _: &hir::Generics, + item_id: ast::NodeId) { self.struct_def_stack.push(item_id); } - fn check_struct_def_post(&mut self, _: &LateContext, _: &hir::VariantData, - _: ast::Name, _: &hir::Generics, item_id: ast::NodeId) { + fn check_struct_def_post(&mut self, + _: &LateContext, + _: &hir::VariantData, + _: ast::Name, + _: &hir::Generics, + item_id: ast::NodeId) { let popped = self.struct_def_stack.pop().expect("empty struct_def_stack"); assert!(popped == item_id); } @@ -358,10 +379,10 @@ impl LateLintPass for MissingDoc { for itm in items { self.private_traits.insert(itm.id); } - return + return; } "a trait" - }, + } hir::ItemTy(..) => "a type alias", hir::ItemImpl(.., Some(ref trait_ref), _, ref impl_items) => { // If the trait is private, add the impl items to private_traits so they don't get @@ -369,26 +390,30 @@ impl LateLintPass for MissingDoc { let real_trait = cx.tcx.expect_def(trait_ref.ref_id).def_id(); if let Some(node_id) = cx.tcx.map.as_local_node_id(real_trait) { match cx.tcx.map.find(node_id) { - Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited { - for itm in impl_items { - self.private_traits.insert(itm.id); + Some(hir_map::NodeItem(item)) => { + if item.vis == hir::Visibility::Inherited { + for itm in impl_items { + self.private_traits.insert(itm.id); + } } - }, - _ => { } + } + _ => {} } } - return - }, + return; + } hir::ItemConst(..) => "a constant", hir::ItemStatic(..) => "a static", - _ => return + _ => return, }; self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc); } fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { - if self.private_traits.contains(&trait_item.id) { return } + if self.private_traits.contains(&trait_item.id) { + return; + } let desc = match trait_item.node { hir::ConstTraitItem(..) => "an associated constant", @@ -396,9 +421,11 @@ impl LateLintPass for MissingDoc { hir::TypeTraitItem(..) => "an associated type", }; - self.check_missing_docs_attrs(cx, Some(trait_item.id), + self.check_missing_docs_attrs(cx, + Some(trait_item.id), &trait_item.attrs, - trait_item.span, desc); + trait_item.span, + desc); } fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) { @@ -412,26 +439,34 @@ impl LateLintPass for MissingDoc { hir::ImplItemKind::Method(..) => "a method", hir::ImplItemKind::Type(_) => "an associated type", }; - self.check_missing_docs_attrs(cx, Some(impl_item.id), + self.check_missing_docs_attrs(cx, + Some(impl_item.id), &impl_item.attrs, - impl_item.span, desc); + impl_item.span, + desc); } fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) { if !sf.is_positional() { if sf.vis == hir::Public || self.in_variant { - let cur_struct_def = *self.struct_def_stack.last() + let cur_struct_def = *self.struct_def_stack + .last() .expect("empty struct_def_stack"); - self.check_missing_docs_attrs(cx, Some(cur_struct_def), - &sf.attrs, sf.span, + self.check_missing_docs_attrs(cx, + Some(cur_struct_def), + &sf.attrs, + sf.span, "a struct field") } } } fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) { - self.check_missing_docs_attrs(cx, Some(v.node.data.id()), - &v.node.attrs, v.span, "a variant"); + self.check_missing_docs_attrs(cx, + Some(v.node.data.id()), + &v.node.attrs, + v.span, + "a variant"); assert!(!self.in_variant); self.in_variant = true; } @@ -486,7 +521,9 @@ impl LateLintPass for MissingCopyImplementations { } _ => return, }; - if def.has_dtor() { return; } + if def.has_dtor() { + return; + } let parameter_environment = cx.tcx.empty_parameter_environment(); // FIXME (@jroesch) should probably inver this so that the parameter env still impls this // method @@ -514,9 +551,7 @@ pub struct MissingDebugImplementations { impl MissingDebugImplementations { pub fn new() -> MissingDebugImplementations { - MissingDebugImplementations { - impling_types: None, - } + MissingDebugImplementations { impling_types: None } } } @@ -533,7 +568,9 @@ impl LateLintPass for MissingDebugImplementations { } match item.node { - hir::ItemStruct(..) | hir::ItemUnion(..) | hir::ItemEnum(..) => {}, + hir::ItemStruct(..) | + hir::ItemUnion(..) | + hir::ItemEnum(..) => {} _ => return, } @@ -585,12 +622,13 @@ pub struct Deprecated { impl Deprecated { pub fn new() -> Deprecated { - Deprecated { - current_item: ast::CRATE_NODE_ID, - } + Deprecated { current_item: ast::CRATE_NODE_ID } } - fn lint(&self, cx: &LateContext, _id: DefId, span: Span, + fn lint(&self, + cx: &LateContext, + _id: DefId, + span: Span, stability: &Option<&attr::Stability>, deprecation: &Option) { // Deprecated attributes apply in-crate and cross-crate. @@ -641,9 +679,10 @@ impl LintPass for Deprecated { impl LateLintPass for Deprecated { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { self.push_item(item.id); - stability::check_item(cx.tcx, item, false, - &mut |id, sp, stab, depr| - self.lint(cx, id, sp, &stab, &depr)); + stability::check_item(cx.tcx, + item, + false, + &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr)); } fn check_item_post(&mut self, cx: &LateContext, item: &hir::Item) { @@ -651,27 +690,30 @@ impl LateLintPass for Deprecated { } fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { - stability::check_expr(cx.tcx, e, - &mut |id, sp, stab, depr| - self.lint(cx, id, sp, &stab, &depr)); + stability::check_expr(cx.tcx, + e, + &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr)); } fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) { - stability::check_path(cx.tcx, path, id, - &mut |id, sp, stab, depr| - self.lint(cx, id, sp, &stab, &depr)); + stability::check_path(cx.tcx, + path, + id, + &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr)); } fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) { - stability::check_path_list_item(cx.tcx, item, - &mut |id, sp, stab, depr| - self.lint(cx, id, sp, &stab, &depr)); + stability::check_path_list_item(cx.tcx, + item, + &mut |id, sp, stab, depr| { + self.lint(cx, id, sp, &stab, &depr) + }); } fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) { - stability::check_pat(cx.tcx, pat, - &mut |id, sp, stab, depr| - self.lint(cx, id, sp, &stab, &depr)); + stability::check_pat(cx.tcx, + pat, + &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr)); } fn check_impl_item(&mut self, _: &LateContext, item: &hir::ImplItem) { @@ -716,15 +758,20 @@ impl LintPass for UnconditionalRecursion { } impl LateLintPass for UnconditionalRecursion { - fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl, - blk: &hir::Block, sp: Span, id: ast::NodeId) { + fn check_fn(&mut self, + cx: &LateContext, + fn_kind: FnKind, + _: &hir::FnDecl, + blk: &hir::Block, + sp: Span, + id: ast::NodeId) { let method = match fn_kind { FnKind::ItemFn(..) => None, FnKind::Method(..) => { cx.tcx.impl_or_trait_item(cx.tcx.map.local_def_id(id)).as_opt_method() } // closures can't recur, so they don't matter. - FnKind::Closure(_) => return + FnKind::Closure(_) => return, }; // Walk through this function (say `f`) looking to see if @@ -779,10 +826,8 @@ impl LateLintPass for UnconditionalRecursion { // is this a recursive call? let self_recursive = if node_id != ast::DUMMY_NODE_ID { match method { - Some(ref method) => { - expr_refers_to_this_method(cx.tcx, method, node_id) - } - None => expr_refers_to_this_fn(cx.tcx, id, node_id) + Some(ref method) => expr_refers_to_this_method(cx.tcx, method, node_id), + None => expr_refers_to_this_fn(cx.tcx, id, node_id), } } else { false @@ -808,7 +853,8 @@ impl LateLintPass for UnconditionalRecursion { // no break */ }`) shouldn't be linted unless it actually // recurs. if !reached_exit_without_self_call && !self_call_spans.is_empty() { - let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, sp, + let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION, + sp, "function cannot return without recurring"); // FIXME #19668: these could be span_lint_note's instead of this manual guard. @@ -829,23 +875,21 @@ impl LateLintPass for UnconditionalRecursion { // Functions for identifying if the given Expr NodeId `id` // represents a call to the function `fn_id`/method `method`. - fn expr_refers_to_this_fn(tcx: TyCtxt, - fn_id: ast::NodeId, - id: ast::NodeId) -> bool { + fn expr_refers_to_this_fn(tcx: TyCtxt, fn_id: ast::NodeId, id: ast::NodeId) -> bool { match tcx.map.get(id) { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { - tcx.expect_def_or_none(callee.id).map_or(false, |def| { - def.def_id() == tcx.map.local_def_id(fn_id) - }) + tcx.expect_def_or_none(callee.id) + .map_or(false, |def| def.def_id() == tcx.map.local_def_id(fn_id)) } - _ => false + _ => false, } } // Check if the expression `id` performs a call to `method`. fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, method: &ty::Method, - id: ast::NodeId) -> bool { + id: ast::NodeId) + -> bool { // Check for method calls and overloaded operators. let opt_m = tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)).cloned(); if let Some(m) = opt_m { @@ -859,9 +903,11 @@ impl LateLintPass for UnconditionalRecursion { if let Some(adjustment::AdjustDerefRef(adj)) = opt_adj { for i in 0..adj.autoderefs { let method_call = ty::MethodCall::autoderef(id, i as u32); - if let Some(m) = tcx.tables.borrow().method_map - .get(&method_call) - .cloned() { + if let Some(m) = tcx.tables + .borrow() + .method_map + .get(&method_call) + .cloned() { if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { return true; } @@ -877,13 +923,16 @@ impl LateLintPass for UnconditionalRecursion { match tcx.expect_def_or_none(callee.id) { Some(Def::Method(def_id)) => { let item_substs = tcx.node_id_item_substs(callee.id); - method_call_refers_to_method( - tcx, method, def_id, &item_substs.substs, id) + method_call_refers_to_method(tcx, + method, + def_id, + &item_substs.substs, + id) } - _ => false + _ => false, } } - _ => false + _ => false, } } @@ -893,15 +942,14 @@ impl LateLintPass for UnconditionalRecursion { method: &ty::Method, callee_id: DefId, callee_substs: &Substs<'tcx>, - expr_id: ast::NodeId) -> bool { + expr_id: ast::NodeId) + -> bool { let callee_item = tcx.impl_or_trait_item(callee_id); match callee_item.container() { // This is an inherent method, so the `def_id` refers // directly to the method definition. - ty::ImplContainer(_) => { - callee_id == method.def_id - } + ty::ImplContainer(_) => callee_id == method.def_id, // A trait method, from any number of possible sources. // Attempt to select a concrete impl before checking. @@ -939,13 +987,12 @@ impl LateLintPass for UnconditionalRecursion { let container = ty::ImplContainer(vtable_impl.impl_def_id); // It matches if it comes from the same impl, // and has the same method name. - container == method.container - && callee_item.name() == method.name + container == method.container && callee_item.name() == method.name } // There's no way to know if this call is // recursive, so we assume it's not. - _ => false + _ => false, } }) } @@ -992,7 +1039,8 @@ impl LateLintPass for PluginAsLibrary { }; if prfn.is_some() { - cx.span_lint(PLUGIN_AS_LIBRARY, it.span, + cx.span_lint(PLUGIN_AS_LIBRARY, + it.span, "compiler plugin used as an ordinary library"); } } @@ -1050,15 +1098,15 @@ impl LateLintPass for InvalidNoMangleItems { "generic functions must be mangled"); } } - }, + } hir::ItemStatic(..) => { if attr::contains_name(&it.attrs, "no_mangle") && - !cx.access_levels.is_reachable(it.id) { + !cx.access_levels.is_reachable(it.id) { let msg = format!("static {} is marked #[no_mangle], but not exported", it.name); cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg); } - }, + } hir::ItemConst(..) => { if attr::contains_name(&it.attrs, "no_mangle") { // Const items do not refer to a particular location in memory, and therefore @@ -1068,7 +1116,7 @@ impl LateLintPass for InvalidNoMangleItems { cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); } } - _ => {}, + _ => {} } } } @@ -1096,19 +1144,21 @@ impl LateLintPass for MutableTransmutes { consider instead using an UnsafeCell"; match get_transmute_from_to(cx, expr) { Some((&ty::TyRef(_, from_mt), &ty::TyRef(_, to_mt))) => { - if to_mt.mutbl == hir::Mutability::MutMutable - && from_mt.mutbl == hir::Mutability::MutImmutable { + if to_mt.mutbl == hir::Mutability::MutMutable && + from_mt.mutbl == hir::Mutability::MutImmutable { cx.span_lint(MUTABLE_TRANSMUTES, expr.span, msg); } } - _ => () + _ => (), } - fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) - -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { + fn get_transmute_from_to<'a, 'tcx> + (cx: &LateContext<'a, 'tcx>, + expr: &hir::Expr) + -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { match expr.node { hir::ExprPath(..) => (), - _ => return None + _ => return None, } if let Def::Fn(did) = cx.tcx.expect_def(expr.id) { if !def_id_is_transmute(cx, did) { @@ -1120,8 +1170,8 @@ impl LateLintPass for MutableTransmutes { let from = bare_fn.sig.0.inputs[0]; let to = bare_fn.sig.0.output; return Some((&from.sty, &to.sty)); - }, - _ => () + } + _ => (), } } None @@ -1130,7 +1180,7 @@ impl LateLintPass for MutableTransmutes { fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { match cx.tcx.lookup_item_type(def_id).ty.sty { ty::TyFnDef(.., ref bfty) if bfty.abi == RustIntrinsic => (), - _ => return false + _ => return false, } cx.tcx.item_name(def_id).as_str() == "transmute" } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 47d248fe2f241..74483b89cea22 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -48,10 +48,10 @@ extern crate rustc_back; extern crate rustc_const_eval; extern crate syntax_pos; -pub use rustc::lint as lint; -pub use rustc::middle as middle; -pub use rustc::session as session; -pub use rustc::util as util; +pub use rustc::lint; +pub use rustc::middle; +pub use rustc::session; +pub use rustc::util; use session::Session; use lint::LintId; @@ -139,13 +139,24 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { MissingDebugImplementations, ); - add_lint_group!(sess, "bad_style", - NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS); - - add_lint_group!(sess, "unused", - UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE, - UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE, - UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES); + add_lint_group!(sess, + "bad_style", + NON_CAMEL_CASE_TYPES, + NON_SNAKE_CASE, + NON_UPPER_CASE_GLOBALS); + + add_lint_group!(sess, + "unused", + UNUSED_IMPORTS, + UNUSED_VARIABLES, + UNUSED_ASSIGNMENTS, + DEAD_CODE, + UNUSED_MUT, + UNREACHABLE_CODE, + UNUSED_MUST_USE, + UNUSED_UNSAFE, + PATH_STATEMENTS, + UNUSED_ATTRIBUTES); // Guidelines for creating a future incompatibility lint: // @@ -155,7 +166,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { // and include the full URL. // - Later, change lint to error // - Eventually, remove lint - store.register_future_incompatible(sess, vec![ + store.register_future_incompatible(sess, + vec![ FutureIncompatibleInfo { id: LintId::of(PRIVATE_IN_PUBLIC), reference: "issue #34537 ", @@ -204,11 +216,13 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { // Register renamed and removed lints store.register_renamed("unknown_features", "unused_features"); - store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); + store.register_removed("unsigned_negation", + "replaced by negate_unsigned feature gate"); store.register_removed("negate_unsigned", "cast a signed value instead"); store.register_removed("raw_pointer_derive", "using derive with raw pointers is ok"); // This was renamed to raw_pointer_derive, which was then removed, // so it is also considered removed - store.register_removed("raw_pointer_deriving", "using derive with raw pointers is ok"); + store.register_removed("raw_pointer_deriving", + "using derive with raw pointers is ok"); store.register_removed("drop_with_repr_extern", "drop flags have been removed"); } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 4caf7a04fe058..9464bf30b693f 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -18,7 +18,7 @@ use rustc::traits::Reveal; use middle::const_val::ConstVal; use rustc_const_eval::eval_const_expr_partial; use rustc_const_eval::EvalHint::ExprTypeChecked; -use util::nodemap::{FnvHashSet}; +use util::nodemap::FnvHashSet; use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass}; @@ -91,15 +91,15 @@ pub struct TypeLimits { impl TypeLimits { pub fn new() -> TypeLimits { - TypeLimits { - negated_expr_id: ast::DUMMY_NODE_ID, - } + TypeLimits { negated_expr_id: ast::DUMMY_NODE_ID } } } impl LintPass for TypeLimits { fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) + lint_array!(UNUSED_COMPARISONS, + OVERFLOWING_LITERALS, + EXCEEDING_BITSHIFTS) } } @@ -111,13 +111,13 @@ impl LateLintPass for TypeLimits { match lit.node { ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)) => { forbid_unsigned_negation(cx, e.span); - }, + } ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty { forbid_unsigned_negation(cx, e.span); } - }, - _ => () + } + _ => (), } } else { let t = cx.tcx.node_id_to_type(expr.id); @@ -129,10 +129,11 @@ impl LateLintPass for TypeLimits { if self.negated_expr_id != e.id { self.negated_expr_id = expr.id; } - }, + } hir::ExprBinary(binop, ref l, ref r) => { if is_comparison(binop) && !check_limits(cx.tcx, binop, &l, &r) { - cx.span_lint(UNUSED_COMPARISONS, e.span, + cx.span_lint(UNUSED_COMPARISONS, + e.span, "comparison is useless due to type limits"); } @@ -140,30 +141,35 @@ impl LateLintPass for TypeLimits { let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty { ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), - _ => None + _ => None, }; if let Some(bits) = opt_ty_bits { let exceeding = if let hir::ExprLit(ref lit) = r.node { - if let ast::LitKind::Int(shift, _) = lit.node { shift >= bits } - else { false } + if let ast::LitKind::Int(shift, _) = lit.node { + shift >= bits + } else { + false + } } else { match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked, None) { Ok(ConstVal::Integral(i)) => { - i.is_negative() || i.to_u64() - .map(|i| i >= bits) - .unwrap_or(true) - }, - _ => { false } + i.is_negative() || + i.to_u64() + .map(|i| i >= bits) + .unwrap_or(true) + } + _ => false, } }; if exceeding { - cx.span_lint(EXCEEDING_BITSHIFTS, e.span, + cx.span_lint(EXCEEDING_BITSHIFTS, + e.span, "bitshift exceeds the type's number of bits"); } }; } - }, + } hir::ExprLit(ref lit) => { match cx.tcx.node_id_to_type(e.id).sty { ty::TyInt(t) => { @@ -182,14 +188,15 @@ impl LateLintPass for TypeLimits { // avoiding use of -min to prevent overflow/panic if (negative && v > max as u64 + 1) || (!negative && v > max as u64) { - cx.span_lint(OVERFLOWING_LITERALS, e.span, + cx.span_lint(OVERFLOWING_LITERALS, + e.span, &format!("literal out of range for {:?}", t)); return; } } - _ => bug!() + _ => bug!(), }; - }, + } ty::TyUint(t) => { let uint_type = if let ast::UintTy::Us = t { cx.sess().target.uint_type @@ -201,13 +208,14 @@ impl LateLintPass for TypeLimits { // _v is u8, within range by definition ast::LitKind::Byte(_v) => return, ast::LitKind::Int(v, _) => v, - _ => bug!() + _ => bug!(), }; if lit_val < min || lit_val > max { - cx.span_lint(OVERFLOWING_LITERALS, e.span, + cx.span_lint(OVERFLOWING_LITERALS, + e.span, &format!("literal out of range for {:?}", t)); } - }, + } ty::TyFloat(t) => { let (min, max) = float_ty_range(t); let lit_val: f64 = match lit.node { @@ -215,70 +223,71 @@ impl LateLintPass for TypeLimits { ast::LitKind::FloatUnsuffixed(ref v) => { match v.parse() { Ok(f) => f, - Err(_) => return + Err(_) => return, } } - _ => bug!() + _ => bug!(), }; if lit_val < min || lit_val > max { - cx.span_lint(OVERFLOWING_LITERALS, e.span, + cx.span_lint(OVERFLOWING_LITERALS, + e.span, &format!("literal out of range for {:?}", t)); } - }, - _ => () + } + _ => (), }; - }, - _ => () + } + _ => (), }; - fn is_valid(binop: hir::BinOp, v: T, - min: T, max: T) -> bool { + fn is_valid(binop: hir::BinOp, v: T, min: T, max: T) -> bool { match binop.node { - hir::BiLt => v > min && v <= max, - hir::BiLe => v >= min && v < max, - hir::BiGt => v >= min && v < max, - hir::BiGe => v > min && v <= max, + hir::BiLt => v > min && v <= max, + hir::BiLe => v >= min && v < max, + hir::BiGt => v >= min && v < max, + hir::BiGe => v > min && v <= max, hir::BiEq | hir::BiNe => v >= min && v <= max, - _ => bug!() + _ => bug!(), } } fn rev_binop(binop: hir::BinOp) -> hir::BinOp { - codemap::respan(binop.span, match binop.node { - hir::BiLt => hir::BiGt, - hir::BiLe => hir::BiGe, - hir::BiGt => hir::BiLt, - hir::BiGe => hir::BiLe, - _ => return binop - }) + codemap::respan(binop.span, + match binop.node { + hir::BiLt => hir::BiGt, + hir::BiLe => hir::BiGe, + hir::BiGt => hir::BiLt, + hir::BiGe => hir::BiLe, + _ => return binop, + }) } // for isize & usize, be conservative with the warnings, so that the // warnings are consistent between 32- and 64-bit platforms fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) { match int_ty { - ast::IntTy::Is => (i64::MIN, i64::MAX), - ast::IntTy::I8 => (i8::MIN as i64, i8::MAX as i64), - ast::IntTy::I16 => (i16::MIN as i64, i16::MAX as i64), - ast::IntTy::I32 => (i32::MIN as i64, i32::MAX as i64), - ast::IntTy::I64 => (i64::MIN, i64::MAX) + ast::IntTy::Is => (i64::MIN, i64::MAX), + ast::IntTy::I8 => (i8::MIN as i64, i8::MAX as i64), + ast::IntTy::I16 => (i16::MIN as i64, i16::MAX as i64), + ast::IntTy::I32 => (i32::MIN as i64, i32::MAX as i64), + ast::IntTy::I64 => (i64::MIN, i64::MAX), } } fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) { match uint_ty { - ast::UintTy::Us => (u64::MIN, u64::MAX), - ast::UintTy::U8 => (u8::MIN as u64, u8::MAX as u64), - ast::UintTy::U16 => (u16::MIN as u64, u16::MAX as u64), - ast::UintTy::U32 => (u32::MIN as u64, u32::MAX as u64), - ast::UintTy::U64 => (u64::MIN, u64::MAX) + ast::UintTy::Us => (u64::MIN, u64::MAX), + ast::UintTy::U8 => (u8::MIN as u64, u8::MAX as u64), + ast::UintTy::U16 => (u16::MIN as u64, u16::MAX as u64), + ast::UintTy::U32 => (u32::MIN as u64, u32::MAX as u64), + ast::UintTy::U64 => (u64::MIN, u64::MAX), } } fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) { match float_ty { ast::FloatTy::F32 => (f32::MIN as f64, f32::MAX as f64), - ast::FloatTy::F64 => (f64::MIN, f64::MAX) + ast::FloatTy::F64 => (f64::MIN, f64::MAX), } } @@ -305,60 +314,60 @@ impl LateLintPass for TypeLimits { fn check_limits<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, binop: hir::BinOp, l: &hir::Expr, - r: &hir::Expr) -> bool { + r: &hir::Expr) + -> bool { let (lit, expr, swap) = match (&l.node, &r.node) { (&hir::ExprLit(_), _) => (l, r, true), (_, &hir::ExprLit(_)) => (r, l, false), - _ => return true + _ => return true, }; // Normalize the binop so that the literal is always on the RHS in // the comparison - let norm_binop = if swap { - rev_binop(binop) - } else { - binop - }; + let norm_binop = if swap { rev_binop(binop) } else { binop }; match tcx.node_id_to_type(expr.id).sty { ty::TyInt(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i64 = match lit.node { - hir::ExprLit(ref li) => match li.node { - ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | - ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i64, - _ => return true - }, - _ => bug!() + hir::ExprLit(ref li) => { + match li.node { + ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | + ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i64, + _ => return true, + } + } + _ => bug!(), }; is_valid(norm_binop, lit_val, min, max) } ty::TyUint(uint_ty) => { let (min, max): (u64, u64) = uint_ty_range(uint_ty); let lit_val: u64 = match lit.node { - hir::ExprLit(ref li) => match li.node { - ast::LitKind::Int(v, _) => v, - _ => return true - }, - _ => bug!() + hir::ExprLit(ref li) => { + match li.node { + ast::LitKind::Int(v, _) => v, + _ => return true, + } + } + _ => bug!(), }; is_valid(norm_binop, lit_val, min, max) } - _ => true + _ => true, } } fn is_comparison(binop: hir::BinOp) -> bool { match binop.node { - hir::BiEq | hir::BiLt | hir::BiLe | - hir::BiNe | hir::BiGe | hir::BiGt => true, - _ => false + hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => true, + _ => false, } } fn forbid_unsigned_negation(cx: &LateContext, span: Span) { cx.sess() - .struct_span_err_with_code(span, "unary negation of unsigned integer", "E0519") - .span_help(span, "use a cast or the `!` operator") - .emit(); + .struct_span_err_with_code(span, "unary negation of unsigned integer", "E0519") + .span_help(span, "use a cast or the `!` operator") + .emit(); } } } @@ -370,7 +379,7 @@ declare_lint! { } struct ImproperCTypesVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx> + cx: &'a LateContext<'a, 'tcx>, } enum FfiResult { @@ -403,9 +412,13 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if def.variants[data_idx].fields.len() == 1 { match def.variants[data_idx].fields[0].ty(tcx, substs).sty { - ty::TyFnPtr(_) => { return true; } - ty::TyRef(..) => { return true; } - _ => { } + ty::TyFnPtr(_) => { + return true; + } + ty::TyRef(..) => { + return true; + } + _ => {} } } } @@ -415,10 +428,7 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Check if the given type is "ffi-safe" (has a stable, well-defined /// representation which can be exported to C code). - fn check_type_for_ffi(&self, - cache: &mut FnvHashSet>, - ty: Ty<'tcx>) - -> FfiResult { + fn check_type_for_ffi(&self, cache: &mut FnvHashSet>, ty: Ty<'tcx>) -> FfiResult { use self::FfiResult::*; let cx = self.cx.tcx; @@ -431,112 +441,118 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match ty.sty { - ty::TyAdt(def, substs) => match def.adt_kind() { - AdtKind::Struct => { - if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) { - return FfiUnsafe( - "found struct without foreign-function-safe \ - representation annotation in foreign module, \ - consider adding a #[repr(C)] attribute to \ - the type"); - } + ty::TyAdt(def, substs) => { + match def.adt_kind() { + AdtKind::Struct => { + if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) { + return FfiUnsafe("found struct without foreign-function-safe \ + representation annotation in foreign module, \ + consider adding a #[repr(C)] attribute to the type"); + } - // We can't completely trust repr(C) markings; make sure the - // fields are actually safe. - if def.struct_variant().fields.is_empty() { - return FfiUnsafe( - "found zero-size struct in foreign module, consider \ - adding a member to this struct"); - } + // We can't completely trust repr(C) markings; make sure the + // fields are actually safe. + if def.struct_variant().fields.is_empty() { + return FfiUnsafe("found zero-size struct in foreign module, consider \ + adding a member to this struct"); + } - for field in &def.struct_variant().fields { - let field_ty = cx.normalize_associated_type(&field.ty(cx, substs)); - let r = self.check_type_for_ffi(cache, field_ty); - match r { - FfiSafe => {} - FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; } - FfiUnsafe(s) => { return FfiBadStruct(def.did, s); } + for field in &def.struct_variant().fields { + let field_ty = cx.normalize_associated_type(&field.ty(cx, substs)); + let r = self.check_type_for_ffi(cache, field_ty); + match r { + FfiSafe => {} + FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { + return r; + } + FfiUnsafe(s) => { + return FfiBadStruct(def.did, s); + } + } } + FfiSafe } - FfiSafe - } - AdtKind::Union => { - if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) { - return FfiUnsafe( - "found union without foreign-function-safe \ - representation annotation in foreign module, \ - consider adding a #[repr(C)] attribute to \ - the type"); - } + AdtKind::Union => { + if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) { + return FfiUnsafe("found union without foreign-function-safe \ + representation annotation in foreign module, \ + consider adding a #[repr(C)] attribute to the type"); + } - for field in &def.struct_variant().fields { - let field_ty = cx.normalize_associated_type(&field.ty(cx, substs)); - let r = self.check_type_for_ffi(cache, field_ty); - match r { - FfiSafe => {} - FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; } - FfiUnsafe(s) => { return FfiBadUnion(def.did, s); } + for field in &def.struct_variant().fields { + let field_ty = cx.normalize_associated_type(&field.ty(cx, substs)); + let r = self.check_type_for_ffi(cache, field_ty); + match r { + FfiSafe => {} + FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { + return r; + } + FfiUnsafe(s) => { + return FfiBadUnion(def.did, s); + } + } } + FfiSafe } - FfiSafe - } - AdtKind::Enum => { - if def.variants.is_empty() { - // Empty enums are okay... although sort of useless. - return FfiSafe - } + AdtKind::Enum => { + if def.variants.is_empty() { + // Empty enums are okay... although sort of useless. + return FfiSafe; + } - // Check for a repr() attribute to specify the size of the - // discriminant. - let repr_hints = cx.lookup_repr_hints(def.did); - match &repr_hints[..] { - &[] => { - // Special-case types like `Option`. - if !is_repr_nullable_ptr(cx, def, substs) { - return FfiUnsafe( - "found enum without foreign-function-safe \ - representation annotation in foreign module, \ - consider adding a #[repr(...)] attribute to \ - the type") + // Check for a repr() attribute to specify the size of the + // discriminant. + let repr_hints = cx.lookup_repr_hints(def.did); + match &repr_hints[..] { + &[] => { + // Special-case types like `Option`. + if !is_repr_nullable_ptr(cx, def, substs) { + return FfiUnsafe("found enum without foreign-function-safe \ + representation annotation in foreign \ + module, consider adding a #[repr(...)] \ + attribute to the type"); + } } - } - &[ref hint] => { - if !hint.is_ffi_safe() { + &[ref hint] => { + if !hint.is_ffi_safe() { + // FIXME: This shouldn't be reachable: we should check + // this earlier. + return FfiUnsafe("enum has unexpected #[repr(...)] attribute"); + } + + // Enum with an explicitly sized discriminant; either + // a C-style enum or a discriminated union. + + // The layout of enum variants is implicitly repr(C). + // FIXME: Is that correct? + } + _ => { // FIXME: This shouldn't be reachable: we should check // this earlier. - return FfiUnsafe( - "enum has unexpected #[repr(...)] attribute") + return FfiUnsafe("enum has too many #[repr(...)] attributes"); } - - // Enum with an explicitly sized discriminant; either - // a C-style enum or a discriminated union. - - // The layout of enum variants is implicitly repr(C). - // FIXME: Is that correct? } - _ => { - // FIXME: This shouldn't be reachable: we should check - // this earlier. - return FfiUnsafe( - "enum has too many #[repr(...)] attributes"); - } - } - // Check the contained variants. - for variant in &def.variants { - for field in &variant.fields { - let arg = cx.normalize_associated_type(&field.ty(cx, substs)); - let r = self.check_type_for_ffi(cache, arg); - match r { - FfiSafe => {} - FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; } - FfiUnsafe(s) => { return FfiBadEnum(def.did, s); } + // Check the contained variants. + for variant in &def.variants { + for field in &variant.fields { + let arg = cx.normalize_associated_type(&field.ty(cx, substs)); + let r = self.check_type_for_ffi(cache, arg); + match r { + FfiSafe => {} + FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { + return r; + } + FfiUnsafe(s) => { + return FfiBadEnum(def.did, s); + } + } } } + FfiSafe } - FfiSafe } - }, + } ty::TyChar => { FfiUnsafe("found Rust type `char` in foreign module, while \ @@ -544,8 +560,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } // Primitive types with a stable representation. - ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | - ty::TyFloat(..) | ty::TyNever => FfiSafe, + ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyNever => FfiSafe, ty::TyBox(..) => { FfiUnsafe("found Rust type Box<_> in foreign module, \ @@ -572,24 +587,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { consider using a struct instead") } - ty::TyRawPtr(ref m) | ty::TyRef(_, ref m) => { - self.check_type_for_ffi(cache, m.ty) - } + ty::TyRawPtr(ref m) | + ty::TyRef(_, ref m) => self.check_type_for_ffi(cache, m.ty), - ty::TyArray(ty, _) => { - self.check_type_for_ffi(cache, ty) - } + ty::TyArray(ty, _) => self.check_type_for_ffi(cache, ty), ty::TyFnPtr(bare_fn) => { match bare_fn.abi { - Abi::Rust | - Abi::RustIntrinsic | - Abi::PlatformIntrinsic | - Abi::RustCall => { - return FfiUnsafe( - "found function pointer with Rust calling \ - convention in foreign module; consider using an \ - `extern` function pointer") + Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => { + return FfiUnsafe("found function pointer with Rust calling convention in \ + foreign module; consider using an `extern` function \ + pointer") } _ => {} } @@ -599,24 +607,30 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let r = self.check_type_for_ffi(cache, sig.output); match r { FfiSafe => {} - _ => { return r; } + _ => { + return r; + } } } for arg in sig.inputs { let r = self.check_type_for_ffi(cache, arg); match r { FfiSafe => {} - _ => { return r; } + _ => { + return r; + } } } FfiSafe } - ty::TyParam(..) | ty::TyInfer(..) | ty::TyError | - ty::TyClosure(..) | ty::TyProjection(..) | ty::TyAnon(..) | - ty::TyFnDef(..) => { - bug!("Unexpected type in foreign function") - } + ty::TyParam(..) | + ty::TyInfer(..) | + ty::TyError | + ty::TyClosure(..) | + ty::TyProjection(..) | + ty::TyAnon(..) | + ty::TyFnDef(..) => bug!("Unexpected type in foreign function"), } } @@ -633,23 +647,28 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiResult::FfiBadStruct(_, s) => { // FIXME: This diagnostic is difficult to read, and doesn't // point at the relevant field. - self.cx.span_lint(IMPROPER_CTYPES, sp, - &format!("found non-foreign-function-safe member in \ - struct marked #[repr(C)]: {}", s)); + self.cx.span_lint(IMPROPER_CTYPES, + sp, + &format!("found non-foreign-function-safe member in struct \ + marked #[repr(C)]: {}", + s)); } FfiResult::FfiBadUnion(_, s) => { // FIXME: This diagnostic is difficult to read, and doesn't // point at the relevant field. - self.cx.span_lint(IMPROPER_CTYPES, sp, - &format!("found non-foreign-function-safe member in \ - union marked #[repr(C)]: {}", s)); + self.cx.span_lint(IMPROPER_CTYPES, + sp, + &format!("found non-foreign-function-safe member in union \ + marked #[repr(C)]: {}", + s)); } FfiResult::FfiBadEnum(_, s) => { // FIXME: This diagnostic is difficult to read, and doesn't // point at the relevant variant. - self.cx.span_lint(IMPROPER_CTYPES, sp, - &format!("found non-foreign-function-safe member in \ - enum: {}", s)); + self.cx.span_lint(IMPROPER_CTYPES, + sp, + &format!("found non-foreign-function-safe member in enum: {}", + s)); } } } @@ -719,13 +738,13 @@ impl LintPass for VariantSizeDifferences { impl LateLintPass for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemEnum(ref enum_definition, ref gens) = it.node { - if gens.ty_params.is_empty() { // sizes only make sense for non-generic types + if gens.ty_params.is_empty() { + // sizes only make sense for non-generic types let t = cx.tcx.node_id_to_type(it.id); let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { let ty = cx.tcx.erase_regions(&t); - ty.layout(&infcx).unwrap_or_else(|e| { - bug!("failed to get layout for `{}`: {}", t, e) - }) + ty.layout(&infcx) + .unwrap_or_else(|e| bug!("failed to get layout for `{}`: {}", t, e)) }); if let Layout::General { ref variants, ref size, discr, .. } = *layout { @@ -738,23 +757,21 @@ impl LateLintPass for VariantSizeDifferences { .zip(variants) .map(|(variant, variant_layout)| { // Subtract the size of the enum discriminant - let bytes = variant_layout.min_size.bytes() - .saturating_sub(discr_size); + let bytes = variant_layout.min_size + .bytes() + .saturating_sub(discr_size); debug!("- variant `{}` is {} bytes large", variant.node.name, bytes); bytes }) .enumerate() - .fold((0, 0, 0), - |(l, s, li), (idx, size)| - if size > l { - (size, l, idx) - } else if size > s { - (l, size, li) - } else { - (l, s, li) - } - ); + .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l { + (size, l, idx) + } else if size > s { + (l, size, li) + } else { + (l, s, li) + }); // we only warn if the largest variant is at least thrice as large as // the second-largest. @@ -762,7 +779,8 @@ impl LateLintPass for VariantSizeDifferences { cx.span_lint(VARIANT_SIZE_DIFFERENCES, enum_definition.variants[largest_index].span, &format!("enum variant is more than three times larger \ - ({} bytes) than the next largest", largest)); + ({} bytes) than the next largest", + largest)); } } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d31f16df69356..a29ff18ab5318 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -49,8 +49,12 @@ impl UnusedMut { if let hir::BindByValue(hir::MutMutable) = mode { if !name.as_str().starts_with("_") { match mutables.entry(name.0 as usize) { - Vacant(entry) => { entry.insert(vec![id]); }, - Occupied(mut entry) => { entry.get_mut().push(id); }, + Vacant(entry) => { + entry.insert(vec![id]); + } + Occupied(mut entry) => { + entry.get_mut().push(id); + } } } } @@ -60,7 +64,8 @@ impl UnusedMut { let used_mutables = cx.tcx.used_mut_nodes.borrow(); for (_, v) in &mutables { if !v.iter().any(|e| used_mutables.contains(e)) { - cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]), + cx.span_lint(UNUSED_MUT, + cx.tcx.map.span(v[0]), "variable does not need to be mutable"); } } @@ -90,9 +95,13 @@ impl LateLintPass for UnusedMut { } } - fn check_fn(&mut self, cx: &LateContext, - _: FnKind, decl: &hir::FnDecl, - _: &hir::Block, _: Span, _: ast::NodeId) { + fn check_fn(&mut self, + cx: &LateContext, + _: FnKind, + decl: &hir::FnDecl, + _: &hir::Block, + _: Span, + _: ast::NodeId) { for a in &decl.inputs { self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat)); } @@ -124,7 +133,7 @@ impl LateLintPass for UnusedResults { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { hir::StmtSemi(ref expr, _) => &**expr, - _ => return + _ => return, }; if let hir::ExprRet(..) = expr.node { @@ -184,8 +193,8 @@ impl LateLintPass for UnusedUnsafe { if let hir::ExprBlock(ref blk) = e.node { // Don't warn about generated blocks, that'll just pollute the output. if blk.rules == hir::UnsafeBlock(hir::UserProvided) && - !cx.tcx.used_unsafe.borrow().contains(&blk.id) { - cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block"); + !cx.tcx.used_unsafe.borrow().contains(&blk.id) { + cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block"); } } } @@ -210,8 +219,7 @@ impl LateLintPass for PathStatements { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { if let hir::StmtSemi(ref expr, _) = s.node { if let hir::ExprPath(..) = expr.node { - cx.span_lint(PATH_STATEMENTS, s.span, - "path statement with no effect"); + cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect"); } } } @@ -242,8 +250,8 @@ impl LateLintPass for UnusedAttributes { AttributeType::Whitelisted if attr.check_name(name) => { debug!("{:?} is Whitelisted", name); break; - }, - _ => () + } + _ => (), } } @@ -259,24 +267,22 @@ impl LateLintPass for UnusedAttributes { debug!("Emitting warning for: {:?}", attr); cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); // Is it a builtin attribute that must be used at the crate level? - let known_crate = KNOWN_ATTRIBUTES.iter().find(|&&(name, ty, _)| { - attr.name() == name && - ty == AttributeType::CrateLevel - }).is_some(); + let known_crate = KNOWN_ATTRIBUTES.iter() + .find(|&&(name, ty, _)| attr.name() == name && ty == AttributeType::CrateLevel) + .is_some(); // Has a plugin registered this attribute as one which must be used at // the crate level? let plugin_crate = plugin_attributes.iter() - .find(|&&(ref x, t)| { - &*attr.name() == x && - AttributeType::CrateLevel == t - }).is_some(); - if known_crate || plugin_crate { + .find(|&&(ref x, t)| &*attr.name() == x && AttributeType::CrateLevel == t) + .is_some(); + if known_crate || plugin_crate { let msg = match attr.node.style { - ast::AttrStyle::Outer => "crate-level attribute should be an inner \ - attribute: add an exclamation mark: #![foo]", - ast::AttrStyle::Inner => "crate-level attribute should be in the \ - root module", + ast::AttrStyle::Outer => { + "crate-level attribute should be an inner attribute: add an exclamation \ + mark: #![foo]" + } + ast::AttrStyle::Inner => "crate-level attribute should be in the root module", }; cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg); } @@ -296,12 +302,16 @@ declare_lint! { pub struct UnusedParens; impl UnusedParens { - fn check_unused_parens_core(&self, cx: &EarlyContext, value: &ast::Expr, msg: &str, + fn check_unused_parens_core(&self, + cx: &EarlyContext, + value: &ast::Expr, + msg: &str, struct_lit_needs_parens: bool) { if let ast::ExprKind::Paren(ref inner) = value.node { let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&inner); if !necessary { - cx.span_lint(UNUSED_PARENS, value.span, + cx.span_lint(UNUSED_PARENS, + value.span, &format!("unnecessary parentheses around {}", msg)) } } @@ -319,8 +329,7 @@ impl UnusedParens { ast::ExprKind::AssignOp(_, ref lhs, ref rhs) | ast::ExprKind::Binary(_, ref lhs, ref rhs) => { // X { y: 1 } + X { y: 2 } - contains_exterior_struct_lit(&lhs) || - contains_exterior_struct_lit(&rhs) + contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) } ast::ExprKind::Unary(_, ref x) | ast::ExprKind::Cast(ref x, _) | @@ -337,7 +346,7 @@ impl UnusedParens { contains_exterior_struct_lit(&exprs[0]) } - _ => false + _ => false, } } } @@ -363,18 +372,20 @@ impl EarlyLintPass for UnusedParens { Assign(_, ref value) => (value, "assigned value", false), AssignOp(.., ref value) => (value, "assigned value", false), InPlace(_, ref value) => (value, "emplacement value", false), - _ => return + _ => return, }; self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens); } fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { let (value, msg) = match s.node { - ast::StmtKind::Local(ref local) => match local.init { - Some(ref value) => (value, "assigned value"), - None => return - }, - _ => return + ast::StmtKind::Local(ref local) => { + match local.init { + Some(ref value) => (value, "assigned value"), + None => return, + } + } + _ => return, }; self.check_unused_parens_core(cx, &value, msg, false); } @@ -427,23 +438,24 @@ impl LateLintPass for UnusedAllocation { fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprBox(_) => {} - _ => return + _ => return, } if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) { - if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef { - ref autoref, .. - }) = *adjustment { + if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef { ref autoref, .. }) = + *adjustment { match autoref { &Some(adjustment::AutoPtr(_, hir::MutImmutable)) => { - cx.span_lint(UNUSED_ALLOCATION, e.span, + cx.span_lint(UNUSED_ALLOCATION, + e.span, "unnecessary allocation, use & instead"); } &Some(adjustment::AutoPtr(_, hir::MutMutable)) => { - cx.span_lint(UNUSED_ALLOCATION, e.span, + cx.span_lint(UNUSED_ALLOCATION, + e.span, "unnecessary allocation, use &mut instead"); } - _ => () + _ => (), } } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 579a97138f250..bdb4d383cee7d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -32,6 +32,7 @@ use rustc_const_math::ConstInt; use rustc::mir::repr::Mir; +use std::borrow::Cow; use std::cell::Ref; use std::io; use std::mem; @@ -202,7 +203,7 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> { read_f64 -> f64; read_f32 -> f32; read_char -> char; - read_str -> String; + read_str -> Cow; } fn error(&mut self, err: &str) -> Self::Error { diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index acaafb35425d0..3d8a10f6c31fc 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -23,7 +23,7 @@ #![feature(dotdot_in_tuple_patterns)] #![feature(proc_macro_internals)] #![feature(proc_macro_lib)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 12f1eb8535a3e..02f15602d708b 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -26,7 +26,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #[macro_use] extern crate log; extern crate graphviz as dot; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9149202c1c1bb..5600669d45fb9 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -13,7 +13,7 @@ //! Here we build the "reduced graph": the graph of the module tree without //! any imports resolved. -use macros; +use macros::{InvocationData, LegacyScope}; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport}; use {Module, ModuleS, ModuleKind}; use Namespace::{self, TypeNS, ValueNS}; @@ -200,16 +200,16 @@ impl<'b> Resolver<'b> { LoadedMacroKind::Def(mut def) => { let name = def.ident.name; if def.use_locally { - let ext = macro_rules::compile(&self.session.parse_sess, &def); - let shadowing = - self.resolve_macro_name(Mark::root(), name, false).is_some(); - self.expansion_data[&Mark::root()].module.macros.borrow_mut() - .insert(name, macros::NameBinding { - ext: Rc::new(ext), - expansion: expansion, - shadowing: shadowing, - span: loaded_macro.import_site, - }); + let ext = + Rc::new(macro_rules::compile(&self.session.parse_sess, &def)); + if self.builtin_macros.insert(name, ext).is_some() && + expansion != Mark::root() { + let msg = format!("`{}` is already in scope", name); + self.session.struct_span_err(loaded_macro.import_site, &msg) + .note("macro-expanded `#[macro_use]`s may not shadow \ + existing macros (see RFC 1560)") + .emit(); + } self.macro_names.insert(name); } if def.export { @@ -250,7 +250,6 @@ impl<'b> Resolver<'b> { attr::contains_name(&item.attrs, "no_implicit_prelude") }, normal_ancestor_id: Some(item.id), - macros_escape: self.contains_macro_use(&item.attrs), ..ModuleS::new(Some(parent), ModuleKind::Def(def, name)) }); self.define(parent, name, TypeNS, (module, sp, vis)); @@ -520,22 +519,26 @@ impl<'b> Resolver<'b> { pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { pub resolver: &'a mut Resolver<'b>, + pub legacy_scope: LegacyScope<'b>, pub expansion: Mark, } impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { - fn visit_invoc(&mut self, id: ast::NodeId) { - self.resolver.expansion_data.get_mut(&Mark::from_placeholder_id(id)).unwrap().module = - self.resolver.current_module; + fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { + let invocation = self.resolver.invocations[&Mark::from_placeholder_id(id)]; + invocation.module.set(self.resolver.current_module); + invocation.legacy_scope.set(self.legacy_scope); + invocation } } macro_rules! method { ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => { fn $visit(&mut self, node: &$ty) { - match node.node { - $invoc(..) => self.visit_invoc(node.id), - _ => visit::$walk(self, node), + if let $invoc(..) = node.node { + self.visit_invoc(node.id); + } else { + visit::$walk(self, node); } } } @@ -543,22 +546,35 @@ macro_rules! method { impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item); - method!(visit_stmt: ast::Stmt, ast::StmtKind::Mac, walk_stmt); method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty); fn visit_item(&mut self, item: &Item) { - match item.node { + let macro_use = match item.node { ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder - ItemKind::Mac(..) => return self.visit_invoc(item.id), - _ => {} - } + ItemKind::Mac(..) => { + return self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id)); + } + ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs), + _ => false, + }; - let parent = self.resolver.current_module; + let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); self.resolver.build_reduced_graph_for_item(item, self.expansion); visit::walk_item(self, item); self.resolver.current_module = parent; + if !macro_use { + self.legacy_scope = legacy_scope; + } + } + + fn visit_stmt(&mut self, stmt: &ast::Stmt) { + if let ast::StmtKind::Mac(..) = stmt.node { + self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(stmt.id)); + } else { + visit::walk_stmt(self, stmt); + } } fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { @@ -567,10 +583,11 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { } fn visit_block(&mut self, block: &Block) { - let parent = self.resolver.current_module; + let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); self.resolver.build_reduced_graph_for_block(block); visit::walk_block(self, block); self.resolver.current_module = parent; + self.legacy_scope = legacy_scope; } fn visit_trait_item(&mut self, item: &TraitItem) { @@ -578,7 +595,8 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> { let def_id = parent.def_id().unwrap(); if let TraitItemKind::Macro(_) = item.node { - return self.visit_invoc(item.id); + self.visit_invoc(item.id); + return } // Add the item to the trait info. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b573a78d3b327..6db844c1d0376 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -57,6 +57,7 @@ use syntax::ext::base::MultiItemModifier; use syntax::ext::hygiene::Mark; use syntax::ast::{self, FloatTy}; use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy}; +use syntax::ext::base::SyntaxExtension; use syntax::parse::token::{self, keywords}; use syntax::util::lev_distance::find_best_match_for_name; @@ -77,6 +78,7 @@ use std::mem::replace; use std::rc::Rc; use resolve_imports::{ImportDirective, NameResolution}; +use macros::{InvocationData, LegacyBinding, LegacyScope}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. @@ -791,9 +793,6 @@ pub struct ModuleS<'a> { // access the children must be preceded with a // `populate_module_if_necessary` call. populated: Cell, - - macros: RefCell>, - macros_escape: bool, } pub type Module<'a> = &'a ModuleS<'a>; @@ -811,8 +810,6 @@ impl<'a> ModuleS<'a> { globs: RefCell::new((Vec::new())), traits: RefCell::new(None), populated: Cell::new(true), - macros: RefCell::new(FnvHashMap()), - macros_escape: false, } } @@ -1076,7 +1073,7 @@ pub struct Resolver<'a> { privacy_errors: Vec>, ambiguity_errors: Vec>, - macro_shadowing_errors: FnvHashSet, + disallowed_shadowing: Vec<(Name, Span, LegacyScope<'a>)>, arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, @@ -1086,9 +1083,10 @@ pub struct Resolver<'a> { pub derive_modes: FnvHashMap>, crate_loader: &'a mut CrateLoader, macro_names: FnvHashSet, + builtin_macros: FnvHashMap>, // Maps the `Mark` of an expansion to its containing module or block. - expansion_data: FnvHashMap>, + invocations: FnvHashMap>, } pub struct ResolverArenas<'a> { @@ -1097,6 +1095,8 @@ pub struct ResolverArenas<'a> { name_bindings: arena::TypedArena>, import_directives: arena::TypedArena>, name_resolutions: arena::TypedArena>>, + invocation_data: arena::TypedArena>, + legacy_bindings: arena::TypedArena>, } impl<'a> ResolverArenas<'a> { @@ -1120,6 +1120,13 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_resolution(&'a self) -> &'a RefCell> { self.name_resolutions.alloc(Default::default()) } + fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>) + -> &'a InvocationData<'a> { + self.invocation_data.alloc(expansion_data) + } + fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> { + self.legacy_bindings.alloc(binding) + } } impl<'a> ty::NodeIdTree for Resolver<'a> { @@ -1205,8 +1212,9 @@ impl<'a> Resolver<'a> { let mut definitions = Definitions::new(); DefCollector::new(&mut definitions).collect_root(); - let mut expansion_data = FnvHashMap(); - expansion_data.insert(Mark::root(), macros::ExpansionData::root(graph_root)); + let mut invocations = FnvHashMap(); + invocations.insert(Mark::root(), + arenas.alloc_invocation_data(InvocationData::root(graph_root))); Resolver { session: session, @@ -1252,7 +1260,7 @@ impl<'a> Resolver<'a> { privacy_errors: Vec::new(), ambiguity_errors: Vec::new(), - macro_shadowing_errors: FnvHashSet(), + disallowed_shadowing: Vec::new(), arenas: arenas, dummy_binding: arenas.alloc_name_binding(NameBinding { @@ -1266,7 +1274,8 @@ impl<'a> Resolver<'a> { derive_modes: FnvHashMap(), crate_loader: crate_loader, macro_names: FnvHashSet(), - expansion_data: expansion_data, + builtin_macros: FnvHashMap(), + invocations: invocations, } } @@ -1277,6 +1286,8 @@ impl<'a> Resolver<'a> { name_bindings: arena::TypedArena::new(), import_directives: arena::TypedArena::new(), name_resolutions: arena::TypedArena::new(), + invocation_data: arena::TypedArena::new(), + legacy_bindings: arena::TypedArena::new(), } } @@ -3338,7 +3349,8 @@ impl<'a> Resolver<'a> { vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self) } - fn report_errors(&self) { + fn report_errors(&mut self) { + self.report_shadowing_errors(); let mut reported_spans = FnvHashSet(); for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors { @@ -3366,6 +3378,20 @@ impl<'a> Resolver<'a> { } } + fn report_shadowing_errors(&mut self) { + let mut reported_errors = FnvHashSet(); + for (name, span, scope) in replace(&mut self.disallowed_shadowing, Vec::new()) { + if self.resolve_macro_name(scope, name, false).is_some() && + reported_errors.insert((name, span)) { + let msg = format!("`{}` is already in scope", name); + self.session.struct_span_err(span, &msg) + .note("macro-expanded `macro_rules!`s may not shadow \ + existing macros (see RFC 1560)") + .emit(); + } + } + } + fn report_conflict(&self, parent: Module, name: Name, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3f6c69278bee8..86ab077191eef 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -12,47 +12,76 @@ use {Module, Resolver}; use build_reduced_graph::BuildReducedGraphVisitor; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefIndex}; use rustc::hir::map::{self, DefCollector}; +use rustc::util::nodemap::FnvHashMap; +use std::cell::Cell; use std::rc::Rc; use syntax::ast; use syntax::errors::DiagnosticBuilder; -use syntax::ext::base::{self, MultiModifier, MultiDecorator, MultiItemModifier}; +use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator, MultiItemModifier}; use syntax::ext::base::{NormalTT, SyntaxExtension}; use syntax::ext::expand::{Expansion, Invocation, InvocationKind}; -use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::parse::token::intern; use syntax::util::lev_distance::find_best_match_for_name; -use syntax_pos::{Span, DUMMY_SP}; - -// FIXME(jseyfried) Merge with `::NameBinding`. -pub struct NameBinding { - pub ext: Rc, - pub expansion: Mark, - pub shadowing: bool, - pub span: Span, -} +use syntax_pos::Span; #[derive(Clone)] -pub struct ExpansionData<'a> { - backtrace: SyntaxContext, - pub module: Module<'a>, +pub struct InvocationData<'a> { + pub module: Cell>, def_index: DefIndex, // True if this expansion is in a `const_integer` position, for example `[u32; m!()]`. // c.f. `DefCollector::visit_ast_const_integer`. const_integer: bool, + // The scope in which the invocation path is resolved. + pub legacy_scope: Cell>, + // The smallest scope that includes this invocation's expansion, + // or `Empty` if this invocation has not been expanded yet. + pub expansion: Cell>, } -impl<'a> ExpansionData<'a> { +impl<'a> InvocationData<'a> { pub fn root(graph_root: Module<'a>) -> Self { - ExpansionData { - backtrace: SyntaxContext::empty(), - module: graph_root, + InvocationData { + module: Cell::new(graph_root), def_index: CRATE_DEF_INDEX, const_integer: false, + legacy_scope: Cell::new(LegacyScope::Empty), + expansion: Cell::new(LegacyScope::Empty), + } + } +} + +#[derive(Copy, Clone)] +pub enum LegacyScope<'a> { + Empty, + Invocation(&'a InvocationData<'a>), // The scope of the invocation, not including its expansion + Expansion(&'a InvocationData<'a>), // The scope of the invocation, including its expansion + Binding(&'a LegacyBinding<'a>), +} + +impl<'a> LegacyScope<'a> { + fn simplify_expansion(mut invoc: &'a InvocationData<'a>) -> Self { + while let LegacyScope::Invocation(_) = invoc.expansion.get() { + match invoc.legacy_scope.get() { + LegacyScope::Expansion(new_invoc) => invoc = new_invoc, + LegacyScope::Binding(_) => break, + scope @ _ => return scope, + } } + LegacyScope::Expansion(invoc) } } +pub struct LegacyBinding<'a> { + parent: LegacyScope<'a>, + name: ast::Name, + ext: Rc, + span: Span, +} + +pub type LegacyImports = FnvHashMap, Span)>; + impl<'a> base::Resolver for Resolver<'a> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() @@ -61,19 +90,28 @@ impl<'a> base::Resolver for Resolver<'a> { fn get_module_scope(&mut self, id: ast::NodeId) -> Mark { let mark = Mark::fresh(); let module = self.module_map[&id]; - self.expansion_data.insert(mark, ExpansionData { - backtrace: SyntaxContext::empty(), - module: module, + self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData { + module: Cell::new(module), def_index: module.def_id().unwrap().index, const_integer: false, - }); + legacy_scope: Cell::new(LegacyScope::Empty), + expansion: Cell::new(LegacyScope::Empty), + })); mark } fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) { - self.collect_def_ids(mark, expansion); - self.current_module = self.expansion_data[&mark].module; - expansion.visit_with(&mut BuildReducedGraphVisitor { resolver: self, expansion: mark }); + let invocation = self.invocations[&mark]; + self.collect_def_ids(invocation, expansion); + + self.current_module = invocation.module.get(); + let mut visitor = BuildReducedGraphVisitor { + resolver: self, + legacy_scope: LegacyScope::Invocation(invocation), + expansion: mark, + }; + expansion.visit_with(&mut visitor); + invocation.expansion.set(visitor.legacy_scope); } fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) { @@ -81,17 +119,14 @@ impl<'a> base::Resolver for Resolver<'a> { self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`"); } if def.use_locally { - let ExpansionData { mut module, backtrace, .. } = self.expansion_data[&scope]; - while module.macros_escape { - module = module.parent.unwrap(); - } - let binding = NameBinding { + let invocation = self.invocations[&scope]; + let binding = self.arenas.alloc_legacy_binding(LegacyBinding { + parent: invocation.legacy_scope.get(), + name: def.ident.name, ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)), - expansion: backtrace.data().prev_ctxt.data().outer_mark, - shadowing: self.resolve_macro_name(scope, def.ident.name, false).is_some(), span: def.span, - }; - module.macros.borrow_mut().insert(def.ident.name, binding); + }); + invocation.legacy_scope.set(LegacyScope::Binding(binding)); self.macro_names.insert(def.ident.name); } if def.export { @@ -104,12 +139,7 @@ impl<'a> base::Resolver for Resolver<'a> { if let NormalTT(..) = *ext { self.macro_names.insert(ident.name); } - self.graph_root.macros.borrow_mut().insert(ident.name, NameBinding { - ext: ext, - expansion: Mark::root(), - shadowing: false, - span: DUMMY_SP, - }); + self.builtin_macros.insert(ident.name, ext); } fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec) { @@ -119,8 +149,8 @@ impl<'a> base::Resolver for Resolver<'a> { fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option { for i in 0..attrs.len() { let name = intern(&attrs[i].name()); - match self.expansion_data[&Mark::root()].module.macros.borrow().get(&name) { - Some(binding) => match *binding.ext { + match self.builtin_macros.get(&name) { + Some(ext) => match **ext { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) } @@ -132,7 +162,8 @@ impl<'a> base::Resolver for Resolver<'a> { None } - fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option> { + fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool) + -> Result, Determinacy> { let (name, span) = match invoc.kind { InvocationKind::Bang { ref mac, .. } => { let path = &mac.node.path; @@ -140,19 +171,27 @@ impl<'a> base::Resolver for Resolver<'a> { !path.segments[0].parameters.is_empty() { self.session.span_err(path.span, "expected macro name without module separators"); - return None; + return Err(Determinacy::Determined); } (path.segments[0].identifier.name, path.span) } InvocationKind::Attr { ref attr, .. } => (intern(&*attr.name()), attr.span), }; - self.resolve_macro_name(scope, name, true).or_else(|| { - let mut err = - self.session.struct_span_err(span, &format!("macro undefined: '{}!'", name)); - self.suggest_macro_name(&name.as_str(), &mut err); - err.emit(); - None + let invocation = self.invocations[&scope]; + if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() { + invocation.legacy_scope.set(LegacyScope::simplify_expansion(parent)); + } + self.resolve_macro_name(invocation.legacy_scope.get(), name, true).ok_or_else(|| { + if force { + let mut err = + self.session.struct_span_err(span, &format!("macro undefined: '{}!'", name)); + self.suggest_macro_name(&name.as_str(), &mut err); + err.emit(); + Determinacy::Determined + } else { + Determinacy::Undetermined + } }) } @@ -162,36 +201,40 @@ impl<'a> base::Resolver for Resolver<'a> { } impl<'a> Resolver<'a> { - pub fn resolve_macro_name(&mut self, scope: Mark, name: ast::Name, record_used: bool) + pub fn resolve_macro_name(&mut self, + mut scope: LegacyScope<'a>, + name: ast::Name, + record_used: bool) -> Option> { - let ExpansionData { mut module, backtrace, .. } = self.expansion_data[&scope]; + let mut relative_depth: u32 = 0; loop { - if let Some(binding) = module.macros.borrow().get(&name) { - let mut backtrace = backtrace.data(); - while binding.expansion != backtrace.outer_mark { - if backtrace.outer_mark != Mark::root() { - backtrace = backtrace.prev_ctxt.data(); - continue + scope = match scope { + LegacyScope::Empty => break, + LegacyScope::Expansion(invocation) => { + if let LegacyScope::Empty = invocation.expansion.get() { + invocation.legacy_scope.get() + } else { + relative_depth += 1; + invocation.expansion.get() } - - if record_used && binding.shadowing && - self.macro_shadowing_errors.insert(binding.span) { - let msg = format!("`{}` is already in scope", name); - self.session.struct_span_err(binding.span, &msg) - .note("macro-expanded `macro_rules!`s and `#[macro_use]`s \ - may not shadow existing macros (see RFC 1560)") - .emit(); + } + LegacyScope::Invocation(invocation) => { + relative_depth = relative_depth.saturating_sub(1); + invocation.legacy_scope.get() + } + LegacyScope::Binding(binding) => { + if binding.name == name { + if record_used && relative_depth > 0 { + self.disallowed_shadowing.push((name, binding.span, binding.parent)); + } + return Some(binding.ext.clone()); } - break + binding.parent } - return Some(binding.ext.clone()); - } - match module.parent { - Some(parent) => module = parent, - None => break, - } + }; } - None + + self.builtin_macros.get(&name).cloned() } fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) { @@ -204,15 +247,19 @@ impl<'a> Resolver<'a> { } } - fn collect_def_ids(&mut self, mark: Mark, expansion: &Expansion) { - let expansion_data = &mut self.expansion_data; - let ExpansionData { backtrace, def_index, const_integer, module } = expansion_data[&mark]; + fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Expansion) { + let Resolver { ref mut invocations, arenas, graph_root, .. } = *self; + let InvocationData { def_index, const_integer, .. } = *invocation; + let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| { - expansion_data.entry(invoc.mark).or_insert(ExpansionData { - backtrace: backtrace.apply_mark(invoc.mark), - def_index: invoc.def_index, - const_integer: invoc.const_integer, - module: module, + invocations.entry(invoc.mark).or_insert_with(|| { + arenas.alloc_invocation_data(InvocationData { + def_index: invoc.def_index, + const_integer: invoc.const_integer, + module: Cell::new(graph_root), + expansion: Cell::new(LegacyScope::Empty), + legacy_scope: Cell::new(LegacyScope::Empty), + }) }); }; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 4689c4ded5c0a..0939e6f1644de 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use self::Determinacy::*; use self::ImportDirectiveSubclass::*; use Module; @@ -26,6 +25,7 @@ use rustc::lint::builtin::PRIVATE_IN_PUBLIC; use rustc::hir::def::*; use syntax::ast::{NodeId, Name}; +use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; @@ -37,12 +37,6 @@ impl<'a> Resolver<'a> { } } -#[derive(Copy, Clone, Debug)] -pub enum Determinacy { - Determined, - Undetermined, -} - /// Contains data for specific types of import directives. #[derive(Clone, Debug)] pub enum ImportDirectiveSubclass<'a> { @@ -197,7 +191,8 @@ impl<'a> Resolver<'a> { // If the resolution doesn't depend on glob definability, check privacy and return. if let Some(result) = self.try_result(&resolution, ns) { return result.and_then(|binding| { - if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) { + if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) || + binding.is_extern_crate() { // c.f. issue #37020 Success(binding) } else { Failed(None) diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 6ae5fc1657aa7..9b893e19894e8 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -114,7 +114,8 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) if tys.len() != 2 { return None; } - Some([tys[0], tys[1]]) + Some([ccx.tcx().normalize_associated_type(&tys[0]), + ccx.tcx().normalize_associated_type(&tys[1])]) } _ => None } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 41c8d565d418c..81c0c184f66b2 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -36,7 +36,7 @@ #![feature(slice_patterns)] #![feature(staged_api)] #![feature(unicode)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] use rustc::dep_graph::WorkProduct; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 1f34cee5143c6..cb9b162cabe11 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -82,7 +82,7 @@ This API is completely unstable and subject to change. #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 2ecb071fcc2a4..d78f00497ca55 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -11,64 +11,79 @@ use std::fs::File; use std::io::prelude::*; use std::io; -use std::path::{PathBuf, Path}; +use std::path::Path; use std::str; #[derive(Clone)] pub struct ExternalHtml{ + /// Content that will be included inline in the section of a + /// rendered Markdown file or generated documentation pub in_header: String, + /// Content that will be included inline between and the content of + /// a rendered Markdown file or generated documentation pub before_content: String, + /// Content that will be included inline between the content and of + /// a rendered Markdown file or generated documentation pub after_content: String } impl ExternalHtml { pub fn load(in_header: &[String], before_content: &[String], after_content: &[String]) -> Option { - match (load_external_files(in_header), - load_external_files(before_content), - load_external_files(after_content)) { - (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml { - in_header: ih, - before_content: bc, - after_content: ac - }), - _ => None - } + load_external_files(in_header) + .and_then(|ih| + load_external_files(before_content) + .map(|bc| (ih, bc)) + ) + .and_then(|(ih, bc)| + load_external_files(after_content) + .map(|ac| (ih, bc, ac)) + ) + .map(|(ih, bc, ac)| + ExternalHtml { + in_header: ih, + before_content: bc, + after_content: ac, + } + ) } } -pub fn load_string(input: &Path) -> io::Result> { - let mut f = File::open(input)?; - let mut d = Vec::new(); - f.read_to_end(&mut d)?; - Ok(str::from_utf8(&d).map(|s| s.to_string()).ok()) +pub enum LoadStringError { + ReadFail, + BadUtf8, } -macro_rules! load_or_return { - ($input: expr, $cant_read: expr, $not_utf8: expr) => { - { - let input = PathBuf::from(&$input[..]); - match ::externalfiles::load_string(&input) { - Err(e) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: {}", input.display(), e); - return $cant_read; - } - Ok(None) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: not UTF-8", input.display()); - return $not_utf8; - } - Ok(Some(s)) => s - } +pub fn load_string>(file_path: P) -> Result { + let file_path = file_path.as_ref(); + let mut contents = vec![]; + let result = File::open(file_path) + .and_then(|mut f| f.read_to_end(&mut contents)); + if let Err(e) = result { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: {}", + file_path.display(), e); + return Err(LoadStringError::ReadFail); + } + match str::from_utf8(&contents) { + Ok(s) => Ok(s.to_string()), + Err(_) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: not UTF-8", + file_path.display()); + Err(LoadStringError::BadUtf8) } } } -pub fn load_external_files(names: &[String]) -> Option { +fn load_external_files(names: &[String]) -> Option { let mut out = String::new(); for name in names { - out.push_str(&*load_or_return!(&name, None, None)); + let s = match load_string(name) { + Ok(s) => s, + Err(_) => return None, + }; + out.push_str(&s); out.push('\n'); } Some(out) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 006dda7d66199..0be36eb3a8508 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -28,7 +28,7 @@ #![feature(staged_api)] #![feature(test)] #![feature(unicode)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] extern crate arena; extern crate getopts; diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 1421a3c78fc5a..f708aa5461999 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -19,7 +19,7 @@ use testing; use rustc::session::search_paths::SearchPaths; use rustc::session::config::Externs; -use externalfiles::ExternalHtml; +use externalfiles::{ExternalHtml, LoadStringError, load_string}; use html::render::reset_ids; use html::escape::Escape; @@ -58,7 +58,11 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, css.push_str(&s) } - let input_str = load_or_return!(input, 1, 2); + let input_str = match load_string(input) { + Ok(s) => s, + Err(LoadStringError::ReadFail) => return 1, + Err(LoadStringError::BadUtf8) => return 2, + }; let playground = matches.opt_str("markdown-playground-url"); if playground.is_some() { markdown::PLAYGROUND_KRATE.with(|s| { *s.borrow_mut() = Some(None); }); @@ -144,7 +148,11 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, /// Run any tests/code examples in the markdown file `input`. pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, mut test_args: Vec) -> isize { - let input_str = load_or_return!(input, 1, 2); + let input_str = match load_string(input) { + Ok(s) => s, + Err(LoadStringError::ReadFail) => return 1, + Err(LoadStringError::BadUtf8) => return 2, + }; let mut opts = TestOptions::default(); opts.no_crate_inject = true; diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 5e25c61bae995..3e976c9062830 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -199,6 +199,7 @@ use self::DecoderError::*; use self::ParserState::*; use self::InternalStackElement::*; +use std::borrow::Cow; use std::collections::{HashMap, BTreeMap}; use std::io::prelude::*; use std::io; @@ -2081,9 +2082,7 @@ impl Decoder { pub fn new(json: Json) -> Decoder { Decoder { stack: vec![json] } } -} -impl Decoder { fn pop(&mut self) -> Json { self.stack.pop().unwrap() } @@ -2182,8 +2181,8 @@ impl ::Decoder for Decoder { Err(ExpectedError("single character string".to_owned(), format!("{}", s))) } - fn read_str(&mut self) -> DecodeResult { - expect!(self.pop(), String) + fn read_str(&mut self) -> DecodeResult> { + expect!(self.pop(), String).map(Cow::Owned) } fn read_enum(&mut self, _name: &str, f: F) -> DecodeResult where diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 7cb02e2412c65..884f24ddc4c75 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -35,7 +35,7 @@ Core encoding and decoding interfaces. #![feature(specialization)] #![feature(staged_api)] #![feature(unicode)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![cfg_attr(test, feature(test))] // test harness access diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs index e97834f63cee4..a2c0ca954472c 100644 --- a/src/libserialize/opaque.rs +++ b/src/libserialize/opaque.rs @@ -9,6 +9,7 @@ // except according to those terms. use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128}; +use std::borrow::Cow; use std::io::{self, Write}; use serialize; @@ -246,11 +247,11 @@ impl<'a> serialize::Decoder for Decoder<'a> { Ok(::std::char::from_u32(bits).unwrap()) } - fn read_str(&mut self) -> Result { + fn read_str(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap(); self.position += len; - Ok(s.to_string()) + Ok(Cow::Borrowed(s)) } fn error(&mut self, err: &str) -> Self::Error { diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 6650a981884d8..c4613c661a84b 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -14,6 +14,7 @@ Core encoding and decoding interfaces. */ +use std::borrow::Cow; use std::intrinsics; use std::path; use std::rc::Rc; @@ -156,7 +157,7 @@ pub trait Decoder { fn read_f64(&mut self) -> Result; fn read_f32(&mut self) -> Result; fn read_char(&mut self) -> Result; - fn read_str(&mut self) -> Result; + fn read_str(&mut self) -> Result, Self::Error>; // Compound types: fn read_enum(&mut self, _name: &str, f: F) -> Result @@ -401,7 +402,7 @@ impl Encodable for String { impl Decodable for String { fn decode(d: &mut D) -> Result { - d.read_str() + Ok(d.read_str()?.into_owned()) } } diff --git a/src/libstd/error.rs b/src/libstd/error.rs index f1f62bc24c509..398bb55ea1bf6 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -55,7 +55,6 @@ use any::TypeId; use cell; use char; use fmt::{self, Debug, Display}; -use marker::Reflect; use mem::transmute; use num; use str; @@ -63,7 +62,7 @@ use string; /// Base functionality for all errors in Rust. #[stable(feature = "rust1", since = "1.0.0")] -pub trait Error: Debug + Display + Reflect { +pub trait Error: Debug + Display { /// A short description of the error. /// /// The description should not contain newlines or sentence-ending diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 93b2d34e27f92..39b64e723933b 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -12,7 +12,6 @@ use io::prelude::*; -use marker::Reflect; use cmp; use error; use fmt; @@ -578,7 +577,7 @@ impl From> for Error { } #[stable(feature = "rust1", since = "1.0.0")] -impl error::Error for IntoInnerError { +impl error::Error for IntoInnerError { fn description(&self) -> &str { error::Error::description(self.error()) } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 73105640cd26b..14d046ab0520b 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -12,18 +12,15 @@ //! //! The `std::io` module contains a number of common things you'll need //! when doing input and output. The most core part of this module is -//! the [`Read`][read] and [`Write`][write] traits, which provide the +//! the [`Read`] and [`Write`] traits, which provide the //! most general interface for reading and writing input and output. //! -//! [read]: trait.Read.html -//! [write]: trait.Write.html -//! //! # Read and Write //! -//! Because they are traits, `Read` and `Write` are implemented by a number +//! Because they are traits, [`Read`] and [`Write`] are implemented by a number //! of other types, and you can implement them for your types too. As such, //! you'll see a few different types of I/O throughout the documentation in -//! this module: `File`s, `TcpStream`s, and sometimes even `Vec`s. For +//! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec`]s. For //! example, `Read` adds a `read()` method, which we can use on `File`s: //! //! ``` @@ -43,15 +40,15 @@ //! # } //! ``` //! -//! `Read` and `Write` are so important, implementors of the two traits have a +//! [`Read`] and [`Write`] are so important, implementors of the two traits have a //! nickname: readers and writers. So you'll sometimes see 'a reader' instead -//! of 'a type that implements the `Read` trait'. Much easier! +//! of 'a type that implements the [`Read`] trait'. Much easier! //! //! ## Seek and BufRead //! -//! Beyond that, there are two important traits that are provided: [`Seek`][seek] -//! and [`BufRead`][bufread]. Both of these build on top of a reader to control -//! how the reading happens. `Seek` lets you control where the next byte is +//! Beyond that, there are two important traits that are provided: [`Seek`] +//! and [`BufRead`]. Both of these build on top of a reader to control +//! how the reading happens. [`Seek`] lets you control where the next byte is //! coming from: //! //! ``` @@ -75,21 +72,18 @@ //! # } //! ``` //! -//! [seek]: trait.Seek.html -//! [bufread]: trait.BufRead.html -//! -//! `BufRead` uses an internal buffer to provide a number of other ways to read, but +//! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but //! to show it off, we'll need to talk about buffers in general. Keep reading! //! //! ## BufReader and BufWriter //! //! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be //! making near-constant calls to the operating system. To help with this, -//! `std::io` comes with two structs, `BufReader` and `BufWriter`, which wrap +//! `std::io` comes with two structs, [`BufReader`] and [`BufWriter`], which wrap //! readers and writers. The wrapper uses a buffer, reducing the number of //! calls and providing nicer methods for accessing exactly what you want. //! -//! For example, `BufReader` works with the `BufRead` trait to add extra +//! For example, [`BufReader`] works with the [`BufRead`] trait to add extra //! methods to any reader: //! //! ``` @@ -111,8 +105,8 @@ //! # } //! ``` //! -//! `BufWriter` doesn't add any new ways of writing; it just buffers every call -//! to [`write()`][write()]: +//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call +//! to [`write()`]: //! //! ``` //! use std::io; @@ -134,8 +128,6 @@ //! # } //! ``` //! -//! [write()]: trait.Write.html#tymethod.write -//! //! ## Standard input and output //! //! A very common source of input is standard input: @@ -165,13 +157,13 @@ //! # } //! ``` //! -//! Of course, using `io::stdout()` directly is less common than something like -//! `println!`. +//! Of course, using [`io::stdout()`] directly is less common than something like +//! [`println!`]. //! //! ## Iterator types //! //! A large number of the structures provided by `std::io` are for various -//! ways of iterating over I/O. For example, `Lines` is used to split over +//! ways of iterating over I/O. For example, [`Lines`] is used to split over //! lines: //! //! ``` @@ -211,10 +203,10 @@ //! //! ## io::Result //! -//! Last, but certainly not least, is [`io::Result`][result]. This type is used +//! Last, but certainly not least, is [`io::Result`]. This type is used //! as the return type of many `std::io` functions that can cause an error, and //! can be returned from your own functions as well. Many of the examples in this -//! module use the [`try!`][try] macro: +//! module use the [`try!`] macro: //! //! ``` //! use std::io; @@ -230,14 +222,11 @@ //! } //! ``` //! -//! The return type of `read_input()`, `io::Result<()>`, is a very common type -//! for functions which don't have a 'real' return value, but do want to return -//! errors if they happen. In this case, the only purpose of this function is +//! The return type of `read_input()`, [`io::Result<()>`][`io::Result`], is a very +//! common type for functions which don't have a 'real' return value, but do want to +//! return errors if they happen. In this case, the only purpose of this function is //! to read the line and print it, so we use `()`. //! -//! [result]: type.Result.html -//! [try]: ../macro.try.html -//! //! ## Platform-specific behavior //! //! Many I/O functions throughout the standard library are documented to indicate @@ -246,6 +235,22 @@ //! any possibly unclear semantics. Note, however, that this is informative, not a binding //! contract. The implementation of many of these functions are subject to change over //! time and may call fewer or more syscalls/library functions. +//! +//! [`Read`]: trait.Read.html +//! [`Write`]: trait.Write.html +//! [`Seek`]: trait.Seek.html +//! [`BufRead`]: trait.BufRead.html +//! [`File`]: ../fs/struct.File.html +//! [`TcpStream`]: ../net/struct.TcpStream.html +//! [`Vec`]: ../vec/struct.Vec.html +//! [`BufReader`]: struct.BufReader.html +//! [`BufWriter`]: struct.BufWriter.html +//! [`write()`]: trait.Write.html#tymethod.write +//! [`io::stdout()`]: fn.stdout.html +//! [`println!`]: ../macro.println.html +//! [`Lines`]: struct.Lines.html +//! [`io::Result`]: type.Result.html +//! [`try!`]: ../macro.try.html #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index eee8579884125..c2f6a6f660c48 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -255,10 +255,9 @@ #![feature(panic_unwind)] #![feature(placement_in_syntax)] #![feature(prelude_import)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(rand)] #![feature(raw)] -#![feature(reflect_marker)] #![feature(repr_simd)] #![feature(rustc_attrs)] #![feature(shared)] diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 58daa7dbf8dc4..20dc5b3801ba4 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -93,6 +93,26 @@ impl SocketAddr { SocketAddr::V6(ref mut a) => a.set_port(new_port), } } + + /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address, + /// false if it's a valid IPv6 address. + #[unstable(feature = "sockaddr_checker", issue = "36949")] + pub fn is_ipv4(&self) -> bool { + match *self { + SocketAddr::V4(_) => true, + SocketAddr::V6(_) => false, + } + } + + /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address, + /// false if it's a valid IPv4 address. + #[unstable(feature = "sockaddr_checker", issue = "36949")] + pub fn is_ipv6(&self) -> bool { + match *self { + SocketAddr::V4(_) => false, + SocketAddr::V6(_) => true, + } + } } impl SocketAddrV4 { @@ -631,4 +651,19 @@ mod tests { v6.set_scope_id(20); assert_eq!(v6.scope_id(), 20); } + + #[test] + fn is_v4() { + let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)); + assert!(v4.is_ipv4()); + assert!(!v4.is_ipv6()); + } + + #[test] + fn is_v6() { + let v6 = SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0)); + assert!(!v6.is_ipv4()); + assert!(v6.is_ipv6()); + } } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 6d37f1605901a..fce640e7c7a2c 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -270,7 +270,6 @@ use error; use fmt; use mem; use cell::UnsafeCell; -use marker::Reflect; use time::{Duration, Instant}; #[unstable(feature = "mpsc_select", issue = "27800")] @@ -1163,7 +1162,7 @@ impl fmt::Display for SendError { } #[stable(feature = "rust1", since = "1.0.0")] -impl error::Error for SendError { +impl error::Error for SendError { fn description(&self) -> &str { "sending on a closed channel" } @@ -1198,7 +1197,7 @@ impl fmt::Display for TrySendError { } #[stable(feature = "rust1", since = "1.0.0")] -impl error::Error for TrySendError { +impl error::Error for TrySendError { fn description(&self) -> &str { match *self { diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys/common/poison.rs index 55212bf35d698..bdc727f1dfcfe 100644 --- a/src/libstd/sys/common/poison.rs +++ b/src/libstd/sys/common/poison.rs @@ -10,7 +10,6 @@ use error::{Error}; use fmt; -use marker::Reflect; use sync::atomic::{AtomicBool, Ordering}; use thread; @@ -117,7 +116,7 @@ impl fmt::Display for PoisonError { } #[stable(feature = "rust1", since = "1.0.0")] -impl Error for PoisonError { +impl Error for PoisonError { fn description(&self) -> &str { "poisoned lock: another task failed inside" } @@ -174,7 +173,7 @@ impl fmt::Display for TryLockError { } #[stable(feature = "rust1", since = "1.0.0")] -impl Error for TryLockError { +impl Error for TryLockError { fn description(&self) -> &str { match *self { TryLockError::Poisoned(ref p) => p.description(), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index fcf2d32ded960..30fc4c3dd8045 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -71,7 +71,7 @@ impl Encodable for Name { impl Decodable for Name { fn decode(d: &mut D) -> Result { - Ok(token::intern(&d.read_str()?[..])) + Ok(token::intern(&d.read_str()?)) } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 94a7f6030b937..3b81ea4917f2b 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -153,7 +153,7 @@ impl<'a> StripUnconfigured<'a> { } // Visit attributes on expression and statements (but not attributes on items in blocks). - fn visit_stmt_or_expr_attrs(&mut self, attrs: &[ast::Attribute]) { + fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) { // flag the offending attributes for attr in attrs.iter() { if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { @@ -227,7 +227,7 @@ impl<'a> StripUnconfigured<'a> { } pub fn configure_expr(&mut self, expr: P) -> P { - self.visit_stmt_or_expr_attrs(expr.attrs()); + self.visit_expr_attrs(expr.attrs()); // If an expr is valid to cfg away it will have been removed by the // outer stmt or expression folder before descending in here. @@ -245,7 +245,6 @@ impl<'a> StripUnconfigured<'a> { } pub fn configure_stmt(&mut self, stmt: ast::Stmt) -> Option { - self.visit_stmt_or_expr_attrs(stmt.attrs()); self.configure(stmt) } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b56018e1e9dcd..f7c88073c9d40 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -22,7 +22,6 @@ use parse::{self, parser}; use parse::token; use parse::token::{InternedString, str_to_ident}; use ptr::P; -use std_inject; use util::small_vector::SmallVector; use std::path::PathBuf; @@ -523,10 +522,17 @@ pub trait Resolver { fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec); fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; - fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option>; + fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool) + -> Result, Determinacy>; fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option>; } +#[derive(Copy, Clone, Debug)] +pub enum Determinacy { + Determined, + Undetermined, +} + pub struct DummyResolver; impl Resolver for DummyResolver { @@ -540,8 +546,9 @@ impl Resolver for DummyResolver { fn find_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option> { None } - fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation) -> Option> { - None + fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation, _force: bool) + -> Result, Determinacy> { + Err(Determinacy::Determined) } } @@ -737,28 +744,6 @@ impl<'a> ExtCtxt<'a> { pub fn name_of(&self, st: &str) -> ast::Name { token::intern(st) } - - pub fn initialize(&mut self, user_exts: Vec, krate: &ast::Crate) { - if std_inject::no_core(&krate) { - self.crate_root = None; - } else if std_inject::no_std(&krate) { - self.crate_root = Some("core"); - } else { - self.crate_root = Some("std"); - } - - for (name, extension) in user_exts { - let ident = ast::Ident::with_empty_ctxt(name); - self.resolver.add_ext(ident, Rc::new(extension)); - } - - let mut module = ModuleData { - mod_path: vec![token::str_to_ident(&self.ecfg.crate_name)], - directory: PathBuf::from(self.parse_sess.codemap().span_to_filename(krate.span)), - }; - module.directory.pop(); - self.current_expansion.module = Rc::new(module); - } } /// Extract a string literal from the macro expanded version of `expr`, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3abe7626efc6e..363ceebf0f475 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{Block, Crate, Ident, Mac_, PatKind}; +use ast::{Block, Ident, Mac_, PatKind}; use ast::{Name, MacStmtStyle, StmtKind, ItemKind}; use ast; use ext::hygiene::Mark; @@ -26,6 +26,7 @@ use parse::parser::Parser; use parse::token::{self, intern, keywords}; use print::pprust; use ptr::P; +use std_inject; use tokenstream::{TokenTree, TokenStream}; use util::small_vector::SmallVector; use visit::Visitor; @@ -186,8 +187,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { MacroExpander { cx: cx, monotonic: monotonic } } - fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { - let err_count = self.cx.parse_sess.span_diagnostic.err_count(); + pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { + self.cx.crate_root = std_inject::injected_crate_name(&krate); + let mut module = ModuleData { + mod_path: vec![token::str_to_ident(&self.cx.ecfg.crate_name)], + directory: PathBuf::from(self.cx.codemap().span_to_filename(krate.span)), + }; + module.directory.pop(); + self.cx.current_expansion.module = Rc::new(module); let krate_item = Expansion::Items(SmallVector::one(P(ast::Item { attrs: krate.attrs, @@ -206,10 +213,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; - if self.cx.parse_sess.span_diagnostic.err_count() - self.cx.resolve_err_count > err_count { - self.cx.parse_sess.span_diagnostic.abort_if_errors(); - } - krate } @@ -221,25 +224,47 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let (expansion, mut invocations) = self.collect_invocations(expansion); invocations.reverse(); - let mut expansions = vec![vec![(0, expansion)]]; - while let Some(invoc) = invocations.pop() { + let mut expansions = Vec::new(); + let mut undetermined_invocations = Vec::new(); + let (mut progress, mut force) = (false, !self.monotonic); + loop { + let invoc = if let Some(invoc) = invocations.pop() { + invoc + } else if undetermined_invocations.is_empty() { + break + } else { + invocations = mem::replace(&mut undetermined_invocations, Vec::new()); + force = !mem::replace(&mut progress, false); + continue + }; + + let scope = + if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; + let ext = match self.cx.resolver.resolve_invoc(scope, &invoc, force) { + Ok(ext) => Some(ext), + Err(Determinacy::Determined) => None, + Err(Determinacy::Undetermined) => { + undetermined_invocations.push(invoc); + continue + } + }; + + progress = true; let ExpansionData { depth, mark, .. } = invoc.expansion_data; self.cx.current_expansion = invoc.expansion_data.clone(); - let scope = if self.monotonic { mark } else { orig_expansion_data.mark }; self.cx.current_expansion.mark = scope; - let expansion = match self.cx.resolver.resolve_invoc(scope, &invoc) { + let expansion = match ext { Some(ext) => self.expand_invoc(invoc, ext), None => invoc.expansion_kind.dummy(invoc.span()), }; - self.cx.current_expansion.depth = depth + 1; let (expansion, new_invocations) = self.collect_invocations(expansion); - if expansions.len() == depth { + if expansions.len() < depth { expansions.push(Vec::new()); } - expansions[depth].push((mark.as_u32(), expansion)); + expansions[depth - 1].push((mark.as_u32(), expansion)); if !self.cx.ecfg.single_step { invocations.extend(new_invocations.into_iter().rev()); } @@ -250,12 +275,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expansions) = expansions.pop() { for (mark, expansion) in expansions.into_iter().rev() { - let expansion = expansion.fold_with(&mut placeholder_expander); placeholder_expander.add(ast::NodeId::from_u32(mark), expansion); } } - placeholder_expander.remove(ast::NodeId::from_u32(0)) + expansion.fold_with(&mut placeholder_expander) } fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec) { @@ -538,7 +562,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { self.invocations.push(Invocation { kind: kind, expansion_kind: expansion_kind, - expansion_data: ExpansionData { mark: mark, ..self.cx.current_expansion.clone() }, + expansion_data: ExpansionData { + mark: mark, + depth: self.cx.current_expansion.depth + 1, + ..self.cx.current_expansion.clone() + }, }); placeholder(expansion_kind, ast::NodeId::from_u32(mark.as_u32())) } @@ -866,22 +894,6 @@ impl<'feat> ExpansionConfig<'feat> { } } -pub fn expand_crate(cx: &mut ExtCtxt, - user_exts: Vec, - c: Crate) -> Crate { - cx.initialize(user_exts, &c); - cx.monotonic_expander().expand_crate(c) -} - -// Expands crate using supplied MacroExpander - allows for -// non-standard expansion behaviour (e.g. step-wise). -pub fn expand_crate_with_expander(expander: &mut MacroExpander, - user_exts: Vec, - c: Crate) -> Crate { - expander.cx.initialize(user_exts, &c); - expander.expand_crate(c) -} - // A Marker adds the given mark to the syntax context and // sets spans' `expn_id` to the given expn_id (unless it is `None`). struct Marker { mark: Mark, expn_id: Option } diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 0ede6dd98e5b8..e323dd2f62327 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -88,10 +88,11 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } pub fn add(&mut self, id: ast::NodeId, expansion: Expansion) { + let expansion = expansion.fold_with(self); self.expansions.insert(id, expansion); } - pub fn remove(&mut self, id: ast::NodeId) -> Expansion { + fn remove(&mut self, id: ast::NodeId) -> Expansion { self.expansions.remove(&id).unwrap() } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9eed1d61244a4..62b88888fc878 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -253,9 +253,6 @@ declare_features! ( // a...b and ...b (active, inclusive_range_syntax, "1.7.0", Some(28237)), - // `expr?` - (active, question_mark, "1.9.0", Some(31436)), - // impl specialization (RFC 1210) (active, specialization, "1.7.0", Some(31844)), @@ -348,6 +345,8 @@ declare_features! ( (accepted, while_let, "1.0.0", None), // Allows `#[deprecated]` attribute (accepted, deprecated, "1.9.0", Some(29935)), + // `expr?` + (accepted, question_mark, "1.14.0", Some(31436)), ); // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -1072,9 +1071,6 @@ impl<'a> Visitor for PostExpansionVisitor<'a> { e.span, "inclusive range syntax is experimental"); } - ast::ExprKind::Try(..) => { - gate_feature_post!(&self, question_mark, e.span, "the `?` operator is not stable"); - } ast::ExprKind::InPlace(..) => { gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN); } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 118ceb17ab4a4..6e671c9efdcf8 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -31,7 +31,7 @@ #![feature(staged_api)] #![feature(str_escape)] #![feature(unicode)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(rustc_diagnostic_macros)] #![feature(specialization)] diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 09bc5607946de..73d9695a9906b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -566,7 +566,7 @@ impl PartialEq for str { impl Decodable for InternedString { fn decode(d: &mut D) -> Result { - Ok(intern(d.read_str()?.as_ref()).as_str()) + Ok(intern(&d.read_str()?).as_str()) } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3c106970232cd..ecb437f31a5ad 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -112,7 +112,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, out, ann, is_expanded); - if is_expanded && !std_inject::no_std(krate) { + if is_expanded && !std_inject::injected_crate_name(krate).is_none() { // We need to print `#![no_std]` (and its feature gate) so that // compiling pretty-printed source won't inject libstd again. // However we don't want these attributes in the AST because diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index d1454ab06cbc8..1b63a2b70763a 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -34,23 +34,25 @@ fn ignored_span(sess: &ParseSess, sp: Span) -> Span { return sp; } -pub fn no_core(krate: &ast::Crate) -> bool { - attr::contains_name(&krate.attrs, "no_core") -} - -pub fn no_std(krate: &ast::Crate) -> bool { - attr::contains_name(&krate.attrs, "no_std") || no_core(krate) +pub fn injected_crate_name(krate: &ast::Crate) -> Option<&'static str> { + if attr::contains_name(&krate.attrs, "no_core") { + None + } else if attr::contains_name(&krate.attrs, "no_std") { + Some("core") + } else { + Some("std") + } } pub fn maybe_inject_crates_ref(sess: &ParseSess, mut krate: ast::Crate, alt_std_name: Option) -> ast::Crate { - if no_core(&krate) { - return krate; - } + let name = match injected_crate_name(&krate) { + Some(name) => name, + None => return krate, + }; - let name = if no_std(&krate) { "core" } else { "std" }; let crate_name = token::intern(&alt_std_name.unwrap_or(name.to_string())); krate.module.items.insert(0, P(ast::Item { diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index fdb10a2beb230..9f99919c89505 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -11,6 +11,7 @@ //! The compiler code necessary to implement the `#[derive]` extensions. use syntax::ast::{self, MetaItem}; +use syntax::attr::HasAttrs; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::feature_gate; @@ -104,13 +105,37 @@ pub fn expand_derive(cx: &mut ExtCtxt, } }; - if mitem.value_str().is_some() { - cx.span_err(mitem.span, "unexpected value in `derive`"); + let mut derive_attrs = Vec::new(); + item = item.map_attrs(|attrs| { + let partition = attrs.into_iter().partition(|attr| &attr.name() == "derive"); + derive_attrs = partition.0; + partition.1 + }); + + // Expand `#[derive]`s after other attribute macro invocations. + if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() { + return vec![Annotatable::Item(item.map_attrs(|mut attrs| { + attrs.push(cx.attribute(span, P(mitem.clone()))); + attrs.extend(derive_attrs); + attrs + }))]; } - let mut traits = mitem.meta_item_list().unwrap_or(&[]).to_owned(); - if traits.is_empty() { - cx.span_warn(mitem.span, "empty trait list in `derive`"); + let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| { + if mitem.value_str().is_some() { + cx.span_err(mitem.span, "unexpected value in `derive`"); + } + + let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned(); + if traits.is_empty() { + cx.span_warn(mitem.span, "empty trait list in `derive`"); + } + traits + }; + + let mut traits = get_traits(mitem, cx); + for derive_attr in derive_attrs { + traits.extend(get_traits(&derive_attr.node.value, cx)); } // First, weed out malformed #[derive] diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index e9d2c0a503be9..f336b26ae41f2 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -50,20 +50,23 @@ pub mod deriving; use std::rc::Rc; use syntax::ast; -use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier}; +use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier, NamedSyntaxExtension}; use syntax::ext::tt::macro_rules::MacroRulesExpander; use syntax::parse::token::intern; -pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, enable_quotes: bool) { +pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, + user_exts: Vec, + enable_quotes: bool) { let mut register = |name, ext| { - resolver.add_ext(ast::Ident::with_empty_ctxt(intern(name)), Rc::new(ext)); + resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext)); }; - register("macro_rules", IdentTT(Box::new(MacroRulesExpander), None, false)); + register(intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false)); macro_rules! register { ($( $name:ident: $f:expr, )*) => { $( - register(stringify!($name), NormalTT(Box::new($f as MacroExpanderFn), None, false)); + register(intern(stringify!($name)), + NormalTT(Box::new($f as MacroExpanderFn), None, false)); )* } } @@ -108,7 +111,11 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, enable_quot } // format_args uses `unstable` things internally. - register("format_args", NormalTT(Box::new(format::expand_format_args), None, true)); + register(intern("format_args"), NormalTT(Box::new(format::expand_format_args), None, true)); - register("derive", MultiModifier(Box::new(deriving::expand_derive))); + register(intern("derive"), MultiModifier(Box::new(deriving::expand_derive))); + + for (name, ext) in user_exts { + register(name, ext); + } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 13dcf7b188b70..e3feaee5369d1 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -27,7 +27,7 @@ #![allow(unused_attributes)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(specialization)] use std::cell::{Cell, RefCell}; diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 0244e26579693..caef808f474ec 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -59,7 +59,7 @@ #![cfg_attr(windows, feature(libc))] // Handle rustfmt skips #![feature(custom_attribute)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![allow(unused_attributes)] use std::io::prelude::*; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index bb42351d3b7c8..625666e641c6b 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -38,7 +38,7 @@ #![feature(rustc_private)] #![feature(set_stdio)] #![feature(staged_api)] -#![feature(question_mark)] +#![cfg_attr(stage0, feature(question_mark))] #![feature(panic_unwind)] extern crate getopts; diff --git a/src/test/compile-fail/issue-32709.rs b/src/test/compile-fail/issue-32709.rs index f9d11f3a171c2..09538818dcdf9 100644 --- a/src/test/compile-fail/issue-32709.rs +++ b/src/test/compile-fail/issue-32709.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(question_mark)] - // Make sure that the span of try shorthand does not include the trailing // semicolon; fn a() -> Result { - Err(5)?; //~ ERROR 16:5: 16:12 + Err(5)?; //~ ERROR 14:5: 14:12 Ok(1) } diff --git a/src/test/compile-fail/issue-33876.rs b/src/test/compile-fail/issue-33876.rs index d95890730a0f2..87747d2851f5e 100644 --- a/src/test/compile-fail/issue-33876.rs +++ b/src/test/compile-fail/issue-33876.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(reflect_marker)] - -use std::marker::Reflect; use std::any::Any; struct Foo; diff --git a/src/test/compile-fail/macro-shadowing.rs b/src/test/compile-fail/macro-shadowing.rs index 22463825ef98f..8381dc34a6a15 100644 --- a/src/test/compile-fail/macro-shadowing.rs +++ b/src/test/compile-fail/macro-shadowing.rs @@ -12,31 +12,28 @@ macro_rules! foo { () => {} } macro_rules! macro_one { () => {} } +#[macro_use(macro_two)] extern crate two_macros; macro_rules! m1 { () => { macro_rules! foo { () => {} } //~ ERROR `foo` is already in scope - //~^ NOTE macro-expanded `macro_rules!`s and `#[macro_use]`s may not shadow existing macros + //~^ NOTE macro-expanded `macro_rules!`s may not shadow existing macros - #[macro_use] //~ ERROR `macro_one` is already in scope - //~^ NOTE macro-expanded `macro_rules!`s and `#[macro_use]`s may not shadow existing macros - extern crate two_macros; + #[macro_use] //~ ERROR `macro_two` is already in scope + //~^ NOTE macro-expanded `#[macro_use]`s may not shadow existing macros + extern crate two_macros as __; }} m1!(); //~ NOTE in this expansion //~| NOTE in this expansion //~| NOTE in this expansion //~| NOTE in this expansion -fn f() { macro_one!(); } foo!(); macro_rules! m2 { () => { macro_rules! foo { () => {} } - #[macro_use] extern crate two_macros as __; - - fn g() { macro_one!(); } foo!(); }} m2!(); -//^ Since `foo` and `macro_one` are not used outside this expansion, they are not shadowing errors. +//^ Since `foo` is not used outside this expansion, it is not a shadowing error. fn main() {} diff --git a/src/test/compile-fail/macro-use-scope.rs b/src/test/compile-fail/macro-use-scope.rs index 5256396a242c9..9d389413ba9ad 100644 --- a/src/test/compile-fail/macro-use-scope.rs +++ b/src/test/compile-fail/macro-use-scope.rs @@ -19,10 +19,10 @@ fn f() { #[macro_use(macro_one)] // Check that this macro is usable in the above function extern crate two_macros; +fn g() { + macro_two!(); +} macro_rules! m { () => { - fn g() { - macro_two!(); - } #[macro_use(macro_two)] // Check that this macro is usable in the above function extern crate two_macros as _two_macros; } } diff --git a/src/test/compile-fail/mir-dataflow/def-inits-1.rs b/src/test/compile-fail/mir-dataflow/def-inits-1.rs index a133ddc15f1ac..1ba1bb35bb5f3 100644 --- a/src/test/compile-fail/mir-dataflow/def-inits-1.rs +++ b/src/test/compile-fail/mir-dataflow/def-inits-1.rs @@ -11,7 +11,6 @@ // General test of maybe_uninits state computed by MIR dataflow. #![feature(rustc_attrs)] -#![feature(stmt_expr_attributes)] use std::intrinsics::rustc_peek; use std::mem::{drop, replace}; diff --git a/src/test/compile-fail/mir-dataflow/inits-1.rs b/src/test/compile-fail/mir-dataflow/inits-1.rs index 949688098f622..c8cf44adb9719 100644 --- a/src/test/compile-fail/mir-dataflow/inits-1.rs +++ b/src/test/compile-fail/mir-dataflow/inits-1.rs @@ -11,7 +11,6 @@ // General test of maybe_inits state computed by MIR dataflow. #![feature(rustc_attrs)] -#![feature(stmt_expr_attributes)] use std::intrinsics::rustc_peek; use std::mem::{drop, replace}; diff --git a/src/test/compile-fail/mir-dataflow/uninits-1.rs b/src/test/compile-fail/mir-dataflow/uninits-1.rs index c13daae24f35d..a82bfc8969880 100644 --- a/src/test/compile-fail/mir-dataflow/uninits-1.rs +++ b/src/test/compile-fail/mir-dataflow/uninits-1.rs @@ -11,7 +11,6 @@ // General test of maybe_uninits state computed by MIR dataflow. #![feature(rustc_attrs)] -#![feature(stmt_expr_attributes)] use std::intrinsics::rustc_peek; use std::mem::{drop, replace}; diff --git a/src/test/compile-fail/mir-dataflow/uninits-2.rs b/src/test/compile-fail/mir-dataflow/uninits-2.rs index 94f812a40a9b5..8cfdae506625e 100644 --- a/src/test/compile-fail/mir-dataflow/uninits-2.rs +++ b/src/test/compile-fail/mir-dataflow/uninits-2.rs @@ -11,7 +11,6 @@ // General test of maybe_uninits state computed by MIR dataflow. #![feature(rustc_attrs)] -#![feature(stmt_expr_attributes)] use std::intrinsics::rustc_peek; use std::mem::{drop, replace}; diff --git a/src/test/compile-fail/stmt_expr_attrs_no_feature.rs b/src/test/compile-fail/stmt_expr_attrs_no_feature.rs index 68338b115950c..2fda2ee0900c7 100644 --- a/src/test/compile-fail/stmt_expr_attrs_no_feature.rs +++ b/src/test/compile-fail/stmt_expr_attrs_no_feature.rs @@ -21,15 +21,15 @@ fn main() { #[attr] fn a() {} - #[attr] //~ ERROR 15701 + #[attr] { } - #[attr] //~ ERROR 15701 + #[attr] 5; - #[attr] //~ ERROR 15701 + #[attr] stmt_mac!(); } @@ -43,7 +43,7 @@ fn c() { #[cfg(not(unset))] fn j() { - #[attr] //~ ERROR 15701 + #[attr] 5; } @@ -55,7 +55,7 @@ fn d() { #[cfg_attr(not(unset), cfg(not(unset)))] fn i() { - #[attr] //~ ERROR 15701 + #[attr] 8; } @@ -64,7 +64,7 @@ fn i() { macro_rules! item_mac { ($e:ident) => { fn $e() { - #[attr] //~ ERROR 15701 + #[attr] 42; #[cfg(unset)] @@ -75,7 +75,7 @@ macro_rules! item_mac { #[cfg(not(unset))] fn k() { - #[attr] //~ ERROR 15701 + #[attr] 5; } @@ -87,7 +87,7 @@ macro_rules! item_mac { #[cfg_attr(not(unset), cfg(not(unset)))] fn h() { - #[attr] //~ ERROR 15701 + #[attr] 8; } diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index 74c7797be2ab8..2d79987823f20 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -236,3 +236,74 @@ struct Visibility; #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")] pub struct Visibility; + + + + +struct ReferencedType1; +struct ReferencedType2; + +// Tuple Struct Change Field Type Indirectly ----------------------------------- +mod tuple_struct_change_field_type_indirectly { + #[cfg(cfail1)] + use super::ReferencedType1 as FieldType; + #[cfg(not(cfail1))] + use super::ReferencedType2 as FieldType; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + struct TupleStruct(FieldType); +} + + +// Record Struct Change Field Type Indirectly ----------------------------------- +mod record_struct_change_field_type_indirectly { + #[cfg(cfail1)] + use super::ReferencedType1 as FieldType; + #[cfg(not(cfail1))] + use super::ReferencedType2 as FieldType; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + struct RecordStruct { + _x: FieldType + } +} + + + + +trait ReferencedTrait1 {} +trait ReferencedTrait2 {} + +// Change Trait Bound Indirectly ----------------------------------------------- +mod change_trait_bound_indirectly { + #[cfg(cfail1)] + use super::ReferencedTrait1 as Trait; + #[cfg(not(cfail1))] + use super::ReferencedTrait2 as Trait; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + struct Struct(T); +} + +// Change Trait Bound Indirectly In Where Clause ------------------------------- +mod change_trait_bound_indirectly_in_where_clause { + #[cfg(cfail1)] + use super::ReferencedTrait1 as Trait; + #[cfg(not(cfail1))] + use super::ReferencedTrait2 as Trait; + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + struct Struct(T) where T : Trait; +} diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs index fe2317aabea68..9b2e36c8cea15 100644 --- a/src/test/run-pass-fulldeps/macro-crate.rs +++ b/src/test/run-pass-fulldeps/macro-crate.rs @@ -17,8 +17,8 @@ #[macro_use] #[no_link] extern crate macro_crate_test; -#[into_multi_foo] #[derive(PartialEq, Clone, Debug)] +#[into_multi_foo] fn foo() -> AnotherFakeTypeThatHadBetterGoAway {} // Check that the `#[into_multi_foo]`-generated `foo2` is configured away diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs index b9e31fc332959..a942adc4c8020 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-atob.rs @@ -21,6 +21,6 @@ use proc_macro::TokenStream; #[proc_macro_derive(AToB)] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert_eq!(input, "struct A;\n"); + assert_eq!(input, "#[derive(Copy, Clone)]\nstruct A;\n"); "struct B;".parse().unwrap() } diff --git a/src/test/run-pass-fulldeps/proc-macro/load-two.rs b/src/test/run-pass-fulldeps/proc-macro/load-two.rs index 56f9768764c17..431c8c5902749 100644 --- a/src/test/run-pass-fulldeps/proc-macro/load-two.rs +++ b/src/test/run-pass-fulldeps/proc-macro/load-two.rs @@ -18,6 +18,7 @@ extern crate derive_atob; #[macro_use] extern crate derive_ctod; +#[derive(Copy, Clone)] #[derive(AToB)] struct A; diff --git a/src/test/run-pass/const-err.rs b/src/test/run-pass/const-err.rs index 9f4ae1ad927d7..a1c9ff8a21edb 100644 --- a/src/test/run-pass/const-err.rs +++ b/src/test/run-pass/const-err.rs @@ -17,4 +17,8 @@ const X: *const u8 = b"" as _; fn main() { let _ = ((-1 as i8) << 8 - 1) as f32; let _ = 0u8 as char; + let _ = true > false; + let _ = true >= false; + let _ = true < false; + let _ = true >= false; } diff --git a/src/test/run-pass/const-negation.rs b/src/test/run-pass/const-negation.rs index 96f4217e4cb80..012fe0d95ec49 100644 --- a/src/test/run-pass/const-negation.rs +++ b/src/test/run-pass/const-negation.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(stmt_expr_attributes)] - #[deny(const_err)] fn main() { diff --git a/src/test/run-pass/enum-discrim-autosizing.rs b/src/test/run-pass/enum-discrim-autosizing.rs index 53c44f2bb24b5..c85ab535fc16b 100644 --- a/src/test/run-pass/enum-discrim-autosizing.rs +++ b/src/test/run-pass/enum-discrim-autosizing.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(stmt_expr_attributes)] - use std::mem::size_of; enum Ei8 { diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 8b5536de12e49..0ebe1ca07c771 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -14,7 +14,6 @@ #![allow(unused_must_use)] #![allow(unused_features)] #![feature(box_syntax)] -#![feature(question_mark)] use std::fmt::{self, Write}; use std::usize; diff --git a/src/test/run-pass/impl-trait/example-st.rs b/src/test/run-pass/impl-trait/example-st.rs index 461d4cf4ff053..e9326ed286aff 100644 --- a/src/test/run-pass/impl-trait/example-st.rs +++ b/src/test/run-pass/impl-trait/example-st.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(conservative_impl_trait, question_mark)] +#![feature(conservative_impl_trait)] struct State; type Error = (); diff --git a/src/test/run-pass/issue-17121.rs b/src/test/run-pass/issue-17121.rs index b3c80041ef88b..dcbcc2d44b5dd 100644 --- a/src/test/run-pass/issue-17121.rs +++ b/src/test/run-pass/issue-17121.rs @@ -10,8 +10,6 @@ // pretty-expanded FIXME #23616 -#![feature(question_mark)] - use std::fs::File; use std::io::{self, BufReader, Read}; diff --git a/src/test/run-pass/issue-19404.rs b/src/test/run-pass/issue-19404.rs index 0eea6ba22cae8..c0f13b0b6c7ad 100644 --- a/src/test/run-pass/issue-19404.rs +++ b/src/test/run-pass/issue-19404.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(reflect_marker)] - use std::any::TypeId; -use std::marker::Reflect; use std::rc::Rc; type Fp = Rc; struct Engine; -trait Component: 'static + Reflect {} +trait Component: 'static {} impl Component for Engine {} trait Env { diff --git a/src/test/run-pass/issue-20797.rs b/src/test/run-pass/issue-20797.rs index de95243665082..e45582dc2d39a 100644 --- a/src/test/run-pass/issue-20797.rs +++ b/src/test/run-pass/issue-20797.rs @@ -10,8 +10,6 @@ // Regression test for #20797. -#![feature(question_mark)] - use std::default::Default; use std::io; use std::fs; diff --git a/src/test/run-pass/issue-21400.rs b/src/test/run-pass/issue-21400.rs index 0d1be964748bb..6715b71a5f506 100644 --- a/src/test/run-pass/issue-21400.rs +++ b/src/test/run-pass/issue-21400.rs @@ -11,8 +11,6 @@ // Regression test for #21400 which itself was extracted from // stackoverflow.com/questions/28031155/is-my-borrow-checker-drunk/28031580 -#![feature(question_mark)] - fn main() { let mut t = Test; assert_eq!(t.method1("one"), Ok(1)); diff --git a/src/test/compile-fail/feature-gate-try-operator.rs b/src/test/run-pass/issue-37020.rs similarity index 72% rename from src/test/compile-fail/feature-gate-try-operator.rs rename to src/test/run-pass/issue-37020.rs index b05c7323962c5..7d0d20269aba7 100644 --- a/src/test/compile-fail/feature-gate-try-operator.rs +++ b/src/test/run-pass/issue-37020.rs @@ -8,11 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -macro_rules! id { - ($e:expr) => { $e } +#![allow(private_in_public)] + +mod foo { + pub mod bar { + extern crate core; + } +} + +mod baz { + pub use foo::bar::core; } fn main() { - id!(x?); //~ error: the `?` operator is not stable (see issue #31436) - y?; //~ error: the `?` operator is not stable (see issue #31436) + baz::core::cell::Cell::new(0u32); } diff --git a/src/test/run-pass/issue-37109.rs b/src/test/run-pass/issue-37109.rs new file mode 100644 index 0000000000000..1c893071d5589 --- /dev/null +++ b/src/test/run-pass/issue-37109.rs @@ -0,0 +1,25 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait ToRef<'a> { + type Ref: 'a; +} + +impl<'a, U: 'a> ToRef<'a> for U { + type Ref = &'a U; +} + +fn example<'a, T>(value: &'a T) -> (>::Ref, u32) { + (value, 0) +} + +fn main() { + example(&0); +} diff --git a/src/test/run-pass/issue-8460.rs b/src/test/run-pass/issue-8460.rs index 8d15fe30a1b07..f16057ccab16c 100644 --- a/src/test/run-pass/issue-8460.rs +++ b/src/test/run-pass/issue-8460.rs @@ -11,7 +11,7 @@ // ignore-emscripten no threads support // ignore-pretty : (#23623) problems when ending with // comments -#![feature(rustc_attrs, stmt_expr_attributes, zero_one)] +#![feature(rustc_attrs, zero_one)] use std::num::Zero; use std::thread; diff --git a/src/test/run-pass/try-operator-hygiene.rs b/src/test/run-pass/try-operator-hygiene.rs index ae622df498f94..53d6185020a02 100644 --- a/src/test/run-pass/try-operator-hygiene.rs +++ b/src/test/run-pass/try-operator-hygiene.rs @@ -18,8 +18,6 @@ // This test verifies that the expansion is hygienic, i.e. it's not affected by other `val` and // `err` bindings that may be in scope. -#![feature(question_mark)] - use std::num::ParseIntError; fn main() { diff --git a/src/test/run-pass/try-operator.rs b/src/test/run-pass/try-operator.rs index de5ccf09c5923..29de6364bf147 100644 --- a/src/test/run-pass/try-operator.rs +++ b/src/test/run-pass/try-operator.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(question_mark)] - use std::fs::File; use std::io::{Read, self}; use std::num::ParseIntError; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index b81258bd6d702..81478c18d7b24 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -13,7 +13,6 @@ #![feature(box_syntax)] #![feature(rustc_private)] #![feature(test)] -#![feature(question_mark)] #![feature(libc)] #![deny(warnings)] diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 2c734c8e3e4d4..7bdf1343aa9cc 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(rustc_private, rustdoc)] -#![feature(question_mark)] extern crate syntax; extern crate rustdoc; diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 3e2bc9032a1cc..f79cc76e67d00 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -24,8 +24,6 @@ //! A few whitelisted exceptions are allowed as there's known bugs in rustdoc, //! but this should catch the majority of "broken link" cases. -#![feature(question_mark)] - extern crate url; use std::env; diff --git a/src/tools/rustbook/main.rs b/src/tools/rustbook/main.rs index 436dc11975336..906251db1c2f2 100644 --- a/src/tools/rustbook/main.rs +++ b/src/tools/rustbook/main.rs @@ -12,7 +12,6 @@ #![feature(rustc_private)] #![feature(rustdoc)] -#![feature(question_mark)] extern crate rustdoc; extern crate rustc_back;