authorbors <bors@rust-lang.org> 2019-10-08 21:32:07 UTC
committerbors <bors@rust-lang.org> 2019-10-08 21:32:07 UTC
logb5bd31ec6db6a249311888a93fc176f06dcb6aa6
tree8d6c88672d85193d1a53f3a72c703f886b501071
parent2748a9fd93dd1a00a4521f4f16de5befbf77f6cd
parentff51611c42d160f95a01d556045d32f0539d8989

Auto merge of #65223 - Centril:rollup-5sdvdni, r=Centril

Rollup of 7 pull requests Successful merges: - #64284 (Warn if include macro fails to include entire file) - #65081 (Remove -Zprofile-queries) - #65133 (typeck: prohibit foreign statics w/ generics) - #65135 (Add check for missing tests for error codes) - #65141 (Replace code of conduct with link) - #65194 (Use structured suggestion for removal of `as_str()` call) - #65213 (Ignore `ExprKind::DropTemps` for some ref suggestions) Failed merges: r? @ghost

49 files changed, 582 insertions(+), 1053 deletions(-)

CODE_OF_CONDUCT.md+1-38
......@@ -1,40 +1,3 @@
11# The Rust Code of Conduct
22
3A version of this document [can be found online](https://www.rust-lang.org/conduct.html).
4
5## Conduct
6
7**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org)
8
9* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic.
10* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all.
11* Please be kind and courteous. There's no need to be mean or rude.
12* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
13* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
14* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the <a href="http://citizencodeofconduct.org/">Citizen Code of Conduct</a>; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
15* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
16* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.
17
18## Moderation
19
20
21These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team].
22
231. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.)
242. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.
253. Moderators will first respond to such remarks with a warning.
264. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off.
275. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded.
286. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology.
297. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed.
308. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others.
31
32In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely.
33
34And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust.
35
36The enforcement policies listed above apply to all official Rust venues; including all communication channels (Rust Discord server, Rust Zulip server); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
37
38*Adapted from the [Node.js Policy on Trolling](https://blog.izs.me/2012/08/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
39
40[mod_team]: https://www.rust-lang.org/team.html#Moderation-team
3The Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html).
src/librustc/dep_graph/graph.rs-9
......@@ -9,7 +9,6 @@ use std::hash::Hash;
99use std::collections::hash_map::Entry;
1010use std::mem;
1111use crate::ty::{self, TyCtxt};
12use crate::util::common::{ProfileQueriesMsg, profq_msg};
1312use parking_lot::{Mutex, Condvar};
1413
1514use crate::ich::{StableHashingContext, StableHashingContextProvider, Fingerprint};
......@@ -256,10 +255,6 @@ impl DepGraph {
256255 // - we can get an idea of the runtime cost.
257256 let mut hcx = cx.get_stable_hashing_context();
258257
259 if cfg!(debug_assertions) {
260 profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone()))
261 };
262
263258 let result = if no_tcx {
264259 task(cx, arg)
265260 } else {
......@@ -275,10 +270,6 @@ impl DepGraph {
275270 })
276271 };
277272
278 if cfg!(debug_assertions) {
279 profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd)
280 };
281
282273 let current_fingerprint = hash_result(&mut hcx, &result);
283274
284275 let dep_node_index = finish_task_and_alloc_depnode(
src/librustc/error_codes.rs+11-7
......@@ -466,7 +466,6 @@ fn main() {
466466```
467467"##,
468468
469
470469E0139: r##"
471470#### Note: this error code is no longer emitted by the compiler.
472471
......@@ -1562,7 +1561,9 @@ fn transmute_lifetime<'a, T>(t: &'a (T,)) -> &'a T {
15621561"##,
15631562
15641563E0496: r##"
1565A lifetime name is shadowing another lifetime name. Erroneous code example:
1564A lifetime name is shadowing another lifetime name.
1565
1566Erroneous code example:
15661567
15671568```compile_fail,E0496
15681569struct Foo<'a> {
......@@ -1594,8 +1595,11 @@ fn main() {
15941595"##,
15951596
15961597E0497: r##"
1597A stability attribute was used outside of the standard library. Erroneous code
1598example:
1598#### Note: this error code is no longer emitted by the compiler.
1599
1600A stability attribute was used outside of the standard library.
1601
1602Erroneous code example:
15991603
16001604```compile_fail
16011605#[stable] // error: stability attributes may not be used outside of the
......@@ -2125,7 +2129,7 @@ rejected in your own crates.
21252129// E0272, // on_unimplemented #0
21262130// E0273, // on_unimplemented #1
21272131// E0274, // on_unimplemented #2
2128 E0278, // requirement is not satisfied
2132// E0278, // requirement is not satisfied
21292133 E0279, // requirement is not satisfied
21302134 E0280, // requirement is not satisfied
21312135// E0285, // overflow evaluation builtin bounds
......@@ -2165,10 +2169,10 @@ rejected in your own crates.
21652169 E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
21662170 E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
21672171 E0697, // closures cannot be static
2168 E0707, // multiple elided lifetimes used in arguments of `async fn`
2172// E0707, // multiple elided lifetimes used in arguments of `async fn`
21692173 E0708, // `async` non-`move` closures with parameters are not currently
21702174 // supported
2171 E0709, // multiple different lifetimes used in arguments of `async fn`
2175// E0709, // multiple different lifetimes used in arguments of `async fn`
21722176 E0710, // an unknown tool name found in scoped lint
21732177 E0711, // a feature has been declared with conflicting stability attributes
21742178// E0702, // replaced with a generic attribute input check
src/librustc/hir/mod.rs+13
......@@ -1548,6 +1548,19 @@ impl Expr {
15481548 }
15491549 }
15501550 }
1551
1552 /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps`
1553 /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically
1554 /// silent, only signaling the ownership system. By doing this, suggestions that check the
1555 /// `ExprKind` of any given `Expr` for presentation don't have to care about `DropTemps`
1556 /// beyond remembering to call this function before doing analysis on it.
1557 pub fn peel_drop_temps(&self) -> &Self {
1558 let mut expr = self;
1559 while let ExprKind::DropTemps(inner) = &expr.kind {
1560 expr = inner;
1561 }
1562 expr
1563 }
15511564}
15521565
15531566impl fmt::Debug for Expr {
src/librustc/lint/builtin.rs+6
......@@ -368,6 +368,12 @@ pub mod parser {
368368 Allow,
369369 "possible meta-variable misuse at macro definition"
370370 }
371
372 declare_lint! {
373 pub INCOMPLETE_INCLUDE,
374 Deny,
375 "trailing content in included file"
376 }
371377}
372378
373379declare_lint! {
src/librustc/lint/mod.rs+2
......@@ -28,6 +28,7 @@ use crate::hir::intravisit;
2828use crate::hir;
2929use crate::lint::builtin::BuiltinLintDiagnostics;
3030use crate::lint::builtin::parser::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
31use crate::lint::builtin::parser::INCOMPLETE_INCLUDE;
3132use crate::session::{Session, DiagnosticMessageId};
3233use crate::ty::TyCtxt;
3334use crate::ty::query::Providers;
......@@ -83,6 +84,7 @@ impl Lint {
8384 match lint_id {
8485 BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT,
8586 BufferedEarlyLintId::MetaVariableMisuse => META_VARIABLE_MISUSE,
87 BufferedEarlyLintId::IncompleteInclude => INCOMPLETE_INCLUDE,
8688 }
8789 }
8890
src/librustc/session/config.rs-4
......@@ -1316,10 +1316,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
13161316 "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
13171317 query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
13181318 "enable queries of the dependency graph for regression testing"),
1319 profile_queries: bool = (false, parse_bool, [UNTRACKED],
1320 "trace and profile the queries of the incremental compilation framework"),
1321 profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED],
1322 "trace and profile the queries and keys of the incremental compilation framework"),
13231319 no_analysis: bool = (false, parse_bool, [UNTRACKED],
13241320 "parse and expand the source, but run no analysis"),
13251321 extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
src/librustc/session/mod.rs+1-13
......@@ -11,7 +11,6 @@ use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath};
1111use crate::session::search_paths::{PathKind, SearchPath};
1212use crate::util::nodemap::{FxHashMap, FxHashSet};
1313use crate::util::common::{duration_to_secs_str, ErrorReported};
14use crate::util::common::ProfileQueriesMsg;
1514
1615use rustc_data_structures::base_n;
1716use rustc_data_structures::sync::{
......@@ -46,7 +45,7 @@ use std::fmt;
4645use std::io::Write;
4746use std::path::PathBuf;
4847use std::time::Duration;
49use std::sync::{Arc, mpsc};
48use std::sync::Arc;
5049
5150mod code_stats;
5251pub mod config;
......@@ -125,9 +124,6 @@ pub struct Session {
125124 /// `-Zquery-dep-graph` is specified.
126125 pub cgu_reuse_tracker: CguReuseTracker,
127126
128 /// Used by `-Z profile-queries` in `util::common`.
129 pub profile_channel: Lock<Option<mpsc::Sender<ProfileQueriesMsg>>>,
130
131127 /// Used by `-Z self-profile`.
132128 pub prof: SelfProfilerRef,
133129
......@@ -509,13 +505,6 @@ impl Session {
509505 pub fn time_extended(&self) -> bool {
510506 self.opts.debugging_opts.time_passes
511507 }
512 pub fn profile_queries(&self) -> bool {
513 self.opts.debugging_opts.profile_queries
514 || self.opts.debugging_opts.profile_queries_and_keys
515 }
516 pub fn profile_queries_and_keys(&self) -> bool {
517 self.opts.debugging_opts.profile_queries_and_keys
518 }
519508 pub fn instrument_mcount(&self) -> bool {
520509 self.opts.debugging_opts.instrument_mcount
521510 }
......@@ -1234,7 +1223,6 @@ fn build_session_(
12341223 incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
12351224 cgu_reuse_tracker,
12361225 prof: SelfProfilerRef::new(self_profiler),
1237 profile_channel: Lock::new(None),
12381226 perf_stats: PerfStats {
12391227 symbol_hash_time: Lock::new(Duration::from_secs(0)),
12401228 decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
src/librustc/ty/query/on_disk_cache.rs+1-1
......@@ -1075,7 +1075,7 @@ where
10751075 let desc = &format!("encode_query_results for {}",
10761076 ::std::any::type_name::<Q>());
10771077
1078 time_ext(tcx.sess.time_extended(), Some(tcx.sess), desc, || {
1078 time_ext(tcx.sess.time_extended(), desc, || {
10791079 let shards = Q::query_cache(tcx).lock_shards();
10801080 assert!(shards.iter().all(|shard| shard.active.is_empty()));
10811081 for (key, entry) in shards.iter().flat_map(|shard| shard.results.iter()) {
src/librustc/ty/query/plumbing.rs-49
......@@ -9,8 +9,6 @@ use crate::ty::query::Query;
99use crate::ty::query::config::{QueryConfig, QueryDescription};
1010use crate::ty::query::job::{QueryJob, QueryResult, QueryInfo};
1111
12use crate::util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
13
1412use errors::DiagnosticBuilder;
1513use errors::Level;
1614use errors::Diagnostic;
......@@ -62,33 +60,6 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> {
6260 }
6361}
6462
65// If enabled, sends a message to the profile-queries thread.
66macro_rules! profq_msg {
67 ($tcx:expr, $msg:expr) => {
68 if cfg!(debug_assertions) {
69 if $tcx.sess.profile_queries() {
70 profq_msg($tcx.sess, $msg)
71 }
72 }
73 }
74}
75
76// If enabled, formats a key using its debug string, which can be
77// expensive to compute (in terms of time).
78macro_rules! profq_query_msg {
79 ($query:expr, $tcx:expr, $key:expr) => {{
80 let msg = if cfg!(debug_assertions) {
81 if $tcx.sess.profile_queries_and_keys() {
82 Some(format!("{:?}", $key))
83 } else { None }
84 } else { None };
85 QueryMsg {
86 query: $query,
87 msg,
88 }
89 }}
90}
91
9263/// A type representing the responsibility to execute the job in the `job` field.
9364/// This will poison the relevant query if dropped.
9465pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> {
......@@ -111,7 +82,6 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
11182 loop {
11283 let mut lock = cache.get_shard_by_value(key).lock();
11384 if let Some(value) = lock.results.get(key) {
114 profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
11585 tcx.prof.query_cache_hit(Q::NAME);
11686 let result = (value.value.clone(), value.index);
11787 #[cfg(debug_assertions)]
......@@ -358,13 +328,6 @@ impl<'tcx> TyCtxt<'tcx> {
358328 key,
359329 span);
360330
361 profq_msg!(self,
362 ProfileQueriesMsg::QueryBegin(
363 span.data(),
364 profq_query_msg!(Q::NAME.as_str(), self, key),
365 )
366 );
367
368331 let job = match JobOwner::try_get(self, span, &key) {
369332 TryGetJob::NotYetStarted(job) => job,
370333 TryGetJob::Cycle(result) => return result,
......@@ -383,7 +346,6 @@ impl<'tcx> TyCtxt<'tcx> {
383346
384347 if Q::ANON {
385348
386 profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
387349 let prof_timer = self.prof.query_provider(Q::NAME);
388350
389351 let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
......@@ -395,7 +357,6 @@ impl<'tcx> TyCtxt<'tcx> {
395357 });
396358
397359 drop(prof_timer);
398 profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
399360
400361 self.dep_graph.read_index(dep_node_index);
401362
......@@ -468,7 +429,6 @@ impl<'tcx> TyCtxt<'tcx> {
468429 };
469430
470431 let result = if let Some(result) = result {
471 profq_msg!(self, ProfileQueriesMsg::CacheHit);
472432 result
473433 } else {
474434 // We could not load a result from the on-disk cache, so
......@@ -542,7 +502,6 @@ impl<'tcx> TyCtxt<'tcx> {
542502 - dep-node: {:?}",
543503 key, dep_node);
544504
545 profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
546505 let prof_timer = self.prof.query_provider(Q::NAME);
547506
548507 let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
......@@ -564,7 +523,6 @@ impl<'tcx> TyCtxt<'tcx> {
564523 });
565524
566525 drop(prof_timer);
567 profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
568526
569527 if unlikely!(!diagnostics.is_empty()) {
570528 if dep_node.kind != crate::dep_graph::DepKind::Null {
......@@ -606,19 +564,12 @@ impl<'tcx> TyCtxt<'tcx> {
606564
607565 let _ = self.get_query::<Q>(DUMMY_SP, key);
608566 } else {
609 profq_msg!(self, ProfileQueriesMsg::CacheHit);
610567 self.prof.query_cache_hit(Q::NAME);
611568 }
612569 }
613570
614571 #[allow(dead_code)]
615572 fn force_query<Q: QueryDescription<'tcx>>(self, key: Q::Key, span: Span, dep_node: DepNode) {
616 profq_msg!(
617 self,
618 ProfileQueriesMsg::QueryBegin(span.data(),
619 profq_query_msg!(Q::NAME.as_str(), self, key))
620 );
621
622573 // We may be concurrently trying both execute and force a query.
623574 // Ensure that only one of them runs the query.
624575 let job = match JobOwner::try_get(self, span, &key) {
src/librustc/util/common.rs+2-73
......@@ -6,11 +6,8 @@ use std::cell::Cell;
66use std::fmt::Debug;
77use std::time::{Duration, Instant};
88
9use std::sync::mpsc::{Sender};
10use syntax_pos::{SpanData};
119use syntax::symbol::{Symbol, sym};
1210use rustc_macros::HashStable;
13use crate::dep_graph::{DepNode};
1411use crate::session::Session;
1512
1613#[cfg(test)]
......@@ -26,17 +23,6 @@ pub struct ErrorReported;
2623
2724thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
2825
29/// Parameters to the `Dump` variant of type `ProfileQueriesMsg`.
30#[derive(Clone,Debug)]
31pub struct ProfQDumpParams {
32 /// A base path for the files we will dump.
33 pub path:String,
34 /// To ensure that the compiler waits for us to finish our dumps.
35 pub ack:Sender<()>,
36 /// Toggle dumping a log file with every `ProfileQueriesMsg`.
37 pub dump_profq_msg_log:bool,
38}
39
4026#[allow(nonstandard_style)]
4127#[derive(Clone, Debug, PartialEq, Eq)]
4228pub struct QueryMsg {
......@@ -44,53 +30,6 @@ pub struct QueryMsg {
4430 pub msg: Option<String>,
4531}
4632
47/// A sequence of these messages induce a trace of query-based incremental compilation.
48// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
49#[derive(Clone,Debug)]
50pub enum ProfileQueriesMsg {
51 /// Begin a timed pass.
52 TimeBegin(String),
53 /// End a timed pass.
54 TimeEnd,
55 /// Begin a task (see `dep_graph::graph::with_task`).
56 TaskBegin(DepNode),
57 /// End a task.
58 TaskEnd,
59 /// Begin a new query.
60 /// Cannot use `Span` because queries are sent to other thread.
61 QueryBegin(SpanData, QueryMsg),
62 /// Query is satisfied by using an already-known value for the given key.
63 CacheHit,
64 /// Query requires running a provider; providers may nest, permitting queries to nest.
65 ProviderBegin,
66 /// Query is satisfied by a provider terminating with a value.
67 ProviderEnd,
68 /// Dump a record of the queries to the given path.
69 Dump(ProfQDumpParams),
70 /// Halt the profiling/monitoring background thread.
71 Halt
72}
73
74/// If enabled, send a message to the profile-queries thread.
75pub fn profq_msg(sess: &Session, msg: ProfileQueriesMsg) {
76 if let Some(s) = sess.profile_channel.borrow().as_ref() {
77 s.send(msg).unwrap()
78 } else {
79 // Do nothing.
80 }
81}
82
83/// Set channel for profile queries channel.
84pub fn profq_set_chan(sess: &Session, s: Sender<ProfileQueriesMsg>) -> bool {
85 let mut channel = sess.profile_channel.borrow_mut();
86 if channel.is_none() {
87 *channel = Some(s);
88 true
89 } else {
90 false
91 }
92}
93
9433/// Read the current depth of `time()` calls. This is used to
9534/// encourage indentation across threads.
9635pub fn time_depth() -> usize {
......@@ -107,10 +46,10 @@ pub fn set_time_depth(depth: usize) {
10746pub fn time<T, F>(sess: &Session, what: &str, f: F) -> T where
10847 F: FnOnce() -> T,
10948{
110 time_ext(sess.time_passes(), Some(sess), what, f)
49 time_ext(sess.time_passes(), what, f)
11150}
11251
113pub fn time_ext<T, F>(do_it: bool, sess: Option<&Session>, what: &str, f: F) -> T where
52pub fn time_ext<T, F>(do_it: bool, what: &str, f: F) -> T where
11453 F: FnOnce() -> T,
11554{
11655 if !do_it { return f(); }
......@@ -121,19 +60,9 @@ pub fn time_ext<T, F>(do_it: bool, sess: Option<&Session>, what: &str, f: F) ->
12160 r
12261 });
12362
124 if let Some(sess) = sess {
125 if cfg!(debug_assertions) {
126 profq_msg(sess, ProfileQueriesMsg::TimeBegin(what.to_string()))
127 }
128 }
12963 let start = Instant::now();
13064 let rv = f();
13165 let dur = start.elapsed();
132 if let Some(sess) = sess {
133 if cfg!(debug_assertions) {
134 profq_msg(sess, ProfileQueriesMsg::TimeEnd)
135 }
136 }
13766
13867 print_time_passes_entry(true, what, dur);
13968
src/librustc_codegen_llvm/back/lto.rs+3-3
......@@ -116,7 +116,7 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
116116 info!("adding bytecode {}", name);
117117 let bc_encoded = data.data();
118118
119 let (bc, id) = time_ext(cgcx.time_passes, None, &format!("decode {}", name), || {
119 let (bc, id) = time_ext(cgcx.time_passes, &format!("decode {}", name), || {
120120 match DecodedBytecode::new(bc_encoded) {
121121 Ok(b) => Ok((b.bytecode(), b.identifier().to_string())),
122122 Err(e) => Err(diag_handler.fatal(&e)),
......@@ -295,7 +295,7 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
295295 for (bc_decoded, name) in serialized_modules {
296296 let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_link_module");
297297 info!("linking {:?}", name);
298 time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || {
298 time_ext(cgcx.time_passes, &format!("ll link {:?}", name), || {
299299 let data = bc_decoded.data();
300300 linker.add(&data).map_err(|()| {
301301 let msg = format!("failed to load bc of {:?}", name);
......@@ -590,7 +590,7 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext<LlvmCodegenBackend>,
590590 llvm::LLVMRustAddPass(pm, pass.unwrap());
591591 }
592592
593 time_ext(cgcx.time_passes, None, "LTO passes", ||
593 time_ext(cgcx.time_passes, "LTO passes", ||
594594 llvm::LLVMRunPassManager(pm, module.module_llvm.llmod()));
595595
596596 llvm::LLVMDisposePassManager(pm);
src/librustc_codegen_llvm/back/write.rs+1-3
......@@ -427,7 +427,6 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
427427 {
428428 let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_function_passes");
429429 time_ext(config.time_passes,
430 None,
431430 &format!("llvm function passes [{}]", module_name.unwrap()),
432431 || {
433432 llvm::LLVMRustRunFunctionPassManager(fpm, llmod)
......@@ -436,7 +435,6 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
436435 {
437436 let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_module_passes");
438437 time_ext(config.time_passes,
439 None,
440438 &format!("llvm module passes [{}]", module_name.unwrap()),
441439 || {
442440 llvm::LLVMRunPassManager(mpm, llmod)
......@@ -538,7 +536,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
538536 embed_bitcode(cgcx, llcx, llmod, None);
539537 }
540538
541 time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
539 time_ext(config.time_passes, &format!("codegen passes [{}]", module_name.unwrap()),
542540 || -> Result<(), FatalError> {
543541 if config.emit_ir {
544542 let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_ir");
src/librustc_codegen_ssa/back/link.rs+1-1
......@@ -1535,7 +1535,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
15351535 let name = cratepath.file_name().unwrap().to_str().unwrap();
15361536 let name = &name[3..name.len() - 5]; // chop off lib/.rlib
15371537
1538 time_ext(sess.time_extended(), Some(sess), &format!("altering {}.rlib", name), || {
1538 time_ext(sess.time_extended(), &format!("altering {}.rlib", name), || {
15391539 let mut archive = <B as ArchiveBuilder>::new(sess, &dst, Some(cratepath));
15401540 archive.update_symbols();
15411541
src/librustc_incremental/persist/load.rs+1-1
......@@ -160,7 +160,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
160160 }
161161
162162 MaybeAsync::Async(std::thread::spawn(move || {
163 time_ext(time_passes, None, "background load prev dep-graph", move || {
163 time_ext(time_passes, "background load prev dep-graph", move || {
164164 match load_data(report_incremental_info, &path) {
165165 LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
166166 LoadResult::Error { message } => LoadResult::Error { message },
src/librustc_interface/interface.rs+1-12
......@@ -1,6 +1,5 @@
11use crate::queries::Queries;
22use crate::util;
3use crate::profile;
43pub use crate::passes::BoxedResolver;
54
65use rustc::lint;
......@@ -115,17 +114,7 @@ where
115114 compiler.sess.diagnostic().print_error_count(&util::diagnostics_registry());
116115 });
117116
118 if compiler.sess.profile_queries() {
119 profile::begin(&compiler.sess);
120 }
121
122 let r = f(&compiler);
123
124 if compiler.sess.profile_queries() {
125 profile::dump(&compiler.sess, "profile_queries".to_string())
126 }
127
128 r
117 f(&compiler)
129118}
130119
131120pub fn run_compiler<F, R>(mut config: Config, f: F) -> R
src/librustc_interface/lib.rs-1
......@@ -16,6 +16,5 @@ mod passes;
1616mod queries;
1717pub mod util;
1818mod proc_macro_decls;
19mod profile;
2019
2120pub use interface::{run_compiler, Config};
src/librustc_interface/profile/mod.rs deleted-297
......@@ -1,297 +0,0 @@
1use log::debug;
2use rustc::dep_graph::DepNode;
3use rustc::session::Session;
4use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
5use std::sync::mpsc::{Receiver};
6use std::io::{Write};
7use std::time::{Duration, Instant};
8
9pub mod trace;
10
11/// begin a profile thread, if not already running
12pub fn begin(sess: &Session) {
13 use std::thread;
14 use std::sync::mpsc::{channel};
15 let (tx, rx) = channel();
16 if profq_set_chan(sess, tx) {
17 thread::spawn(move || profile_queries_thread(rx));
18 }
19}
20
21/// dump files with profiling information to the given base path, and
22/// wait for this dump to complete.
23///
24/// wraps the RPC (send/recv channel logic) of requesting a dump.
25pub fn dump(sess: &Session, path: String) {
26 use std::sync::mpsc::{channel};
27 let (tx, rx) = channel();
28 let params = ProfQDumpParams {
29 path,
30 ack: tx,
31 // FIXME: Add another compiler flag to toggle whether this log
32 // is written; false for now
33 dump_profq_msg_log: true,
34 };
35 profq_msg(sess, ProfileQueriesMsg::Dump(params));
36 let _ = rx.recv().unwrap();
37}
38
39// State for parsing recursive trace structure in separate thread, via messages
40#[derive(Clone, Eq, PartialEq)]
41enum ParseState {
42 // No (local) parse state; may be parsing a tree, focused on a
43 // sub-tree that could be anything.
44 Clear,
45 // Have Query information from the last message
46 HaveQuery(trace::Query, Instant),
47 // Have "time-begin" information from the last message (doit flag, and message)
48 HaveTimeBegin(String, Instant),
49 // Have "task-begin" information from the last message
50 HaveTaskBegin(DepNode, Instant),
51}
52struct StackFrame {
53 pub parse_st: ParseState,
54 pub traces: Vec<trace::Rec>,
55}
56
57fn total_duration(traces: &[trace::Rec]) -> Duration {
58 Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum()
59}
60
61// profiling thread; retains state (in local variables) and dump traces, upon request.
62fn profile_queries_thread(r: Receiver<ProfileQueriesMsg>) {
63 use self::trace::*;
64 use std::fs::File;
65
66 let mut profq_msgs: Vec<ProfileQueriesMsg> = vec![];
67 let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] };
68 let mut stack: Vec<StackFrame> = vec![];
69 loop {
70 let msg = r.recv();
71 if let Err(_recv_err) = msg {
72 // FIXME: Perhaps do something smarter than simply quitting?
73 break
74 };
75 let msg = msg.unwrap();
76 debug!("profile_queries_thread: {:?}", msg);
77
78 // Meta-level versus _actual_ queries messages
79 match msg {
80 ProfileQueriesMsg::Halt => return,
81 ProfileQueriesMsg::Dump(params) => {
82 assert!(stack.is_empty());
83 assert!(frame.parse_st == ParseState::Clear);
84
85 // write log of all messages
86 if params.dump_profq_msg_log {
87 let mut log_file =
88 File::create(format!("{}.log.txt", params.path)).unwrap();
89 for m in profq_msgs.iter() {
90 writeln!(&mut log_file, "{:?}", m).unwrap()
91 };
92 }
93
94 // write HTML file, and counts file
95 let html_path = format!("{}.html", params.path);
96 let mut html_file = File::create(&html_path).unwrap();
97
98 let counts_path = format!("{}.counts.txt", params.path);
99 let mut counts_file = File::create(&counts_path).unwrap();
100
101 writeln!(html_file,
102 "<html>\n<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">",
103 "profile_queries.css").unwrap();
104 writeln!(html_file, "<style>").unwrap();
105 trace::write_style(&mut html_file);
106 writeln!(html_file, "</style>\n</head>\n<body>").unwrap();
107 trace::write_traces(&mut html_file, &mut counts_file, &frame.traces);
108 writeln!(html_file, "</body>\n</html>").unwrap();
109
110 let ack_path = format!("{}.ack", params.path);
111 let ack_file = File::create(&ack_path).unwrap();
112 drop(ack_file);
113
114 // Tell main thread that we are done, e.g., so it can exit
115 params.ack.send(()).unwrap();
116 }
117 // Actual query message:
118 msg => {
119 // Record msg in our log
120 profq_msgs.push(msg.clone());
121 // Respond to the message, knowing that we've already handled Halt and Dump, above.
122 match (frame.parse_st.clone(), msg) {
123 (_, ProfileQueriesMsg::Halt) | (_, ProfileQueriesMsg::Dump(_)) => {
124 unreachable!();
125 },
126 // Parse State: Clear
127 (ParseState::Clear,
128 ProfileQueriesMsg::QueryBegin(span, querymsg)) => {
129 let start = Instant::now();
130 frame.parse_st = ParseState::HaveQuery
131 (Query { span, msg: querymsg }, start)
132 },
133 (ParseState::Clear,
134 ProfileQueriesMsg::CacheHit) => {
135 panic!("parse error: unexpected CacheHit; expected QueryBegin")
136 },
137 (ParseState::Clear,
138 ProfileQueriesMsg::ProviderBegin) => {
139 panic!("parse error: expected QueryBegin before beginning a provider")
140 },
141 (ParseState::Clear,
142 ProfileQueriesMsg::ProviderEnd) => {
143 let provider_extent = frame.traces;
144 match stack.pop() {
145 None =>
146 panic!("parse error: expected a stack frame; found an empty stack"),
147 Some(old_frame) => {
148 match old_frame.parse_st {
149 ParseState::HaveQuery(q, start) => {
150 let duration = start.elapsed();
151 frame = StackFrame{
152 parse_st: ParseState::Clear,
153 traces: old_frame.traces
154 };
155 let dur_extent = total_duration(&provider_extent);
156 let trace = Rec {
157 effect: Effect::QueryBegin(q, CacheCase::Miss),
158 extent: Box::new(provider_extent),
159 start: start,
160 dur_self: duration - dur_extent,
161 dur_total: duration,
162 };
163 frame.traces.push( trace );
164 },
165 _ => panic!("internal parse error: malformed parse stack")
166 }
167 }
168 }
169 },
170 (ParseState::Clear,
171 ProfileQueriesMsg::TimeBegin(msg)) => {
172 let start = Instant::now();
173 frame.parse_st = ParseState::HaveTimeBegin(msg, start);
174 stack.push(frame);
175 frame = StackFrame{parse_st: ParseState::Clear, traces: vec![]};
176 },
177 (_, ProfileQueriesMsg::TimeBegin(_)) => {
178 panic!("parse error; did not expect time begin here");
179 },
180 (ParseState::Clear,
181 ProfileQueriesMsg::TimeEnd) => {
182 let provider_extent = frame.traces;
183 match stack.pop() {
184 None =>
185 panic!("parse error: expected a stack frame; found an empty stack"),
186 Some(old_frame) => {
187 match old_frame.parse_st {
188 ParseState::HaveTimeBegin(msg, start) => {
189 let duration = start.elapsed();
190 frame = StackFrame{
191 parse_st: ParseState::Clear,
192 traces: old_frame.traces
193 };
194 let dur_extent = total_duration(&provider_extent);
195 let trace = Rec {
196 effect: Effect::TimeBegin(msg),
197 extent: Box::new(provider_extent),
198 start: start,
199 dur_total: duration,
200 dur_self: duration - dur_extent,
201 };
202 frame.traces.push( trace );
203 },
204 _ => panic!("internal parse error: malformed parse stack")
205 }
206 }
207 }
208 },
209 (_, ProfileQueriesMsg::TimeEnd) => {
210 panic!("parse error")
211 },
212 (ParseState::Clear,
213 ProfileQueriesMsg::TaskBegin(key)) => {
214 let start = Instant::now();
215 frame.parse_st = ParseState::HaveTaskBegin(key, start);
216 stack.push(frame);
217 frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] };
218 },
219 (_, ProfileQueriesMsg::TaskBegin(_)) => {
220 panic!("parse error; did not expect time begin here");
221 },
222 (ParseState::Clear,
223 ProfileQueriesMsg::TaskEnd) => {
224 let provider_extent = frame.traces;
225 match stack.pop() {
226 None =>
227 panic!("parse error: expected a stack frame; found an empty stack"),
228 Some(old_frame) => {
229 match old_frame.parse_st {
230 ParseState::HaveTaskBegin(key, start) => {
231 let duration = start.elapsed();
232 frame = StackFrame{
233 parse_st: ParseState::Clear,
234 traces: old_frame.traces
235 };
236 let dur_extent = total_duration(&provider_extent);
237 let trace = Rec {
238 effect: Effect::TaskBegin(key),
239 extent: Box::new(provider_extent),
240 start: start,
241 dur_total: duration,
242 dur_self: duration - dur_extent,
243 };
244 frame.traces.push( trace );
245 },
246 _ => panic!("internal parse error: malformed parse stack")
247 }
248 }
249 }
250 },
251 (_, ProfileQueriesMsg::TaskEnd) => {
252 panic!("parse error")
253 },
254 // Parse State: HaveQuery
255 (ParseState::HaveQuery(q,start),
256 ProfileQueriesMsg::CacheHit) => {
257 let duration = start.elapsed();
258 let trace : Rec = Rec{
259 effect: Effect::QueryBegin(q, CacheCase::Hit),
260 extent: Box::new(vec![]),
261 start: start,
262 dur_self: duration,
263 dur_total: duration,
264 };
265 frame.traces.push( trace );
266 frame.parse_st = ParseState::Clear;
267 },
268 (ParseState::HaveQuery(_, _),
269 ProfileQueriesMsg::ProviderBegin) => {
270 stack.push(frame);
271 frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] };
272 },
273
274 // Parse errors:
275
276 (ParseState::HaveQuery(q, _),
277 ProfileQueriesMsg::ProviderEnd) => {
278 panic!("parse error: unexpected ProviderEnd; \
279 expected something else to follow BeginQuery for {:?}", q)
280 },
281 (ParseState::HaveQuery(q1, _),
282 ProfileQueriesMsg::QueryBegin(span2, querymsg2)) => {
283 panic!("parse error: unexpected QueryBegin; \
284 earlier query is unfinished: {:?} and now {:?}",
285 q1, Query{span:span2, msg: querymsg2})
286 },
287 (ParseState::HaveTimeBegin(_, _), _) => {
288 unreachable!()
289 },
290 (ParseState::HaveTaskBegin(_, _), _) => {
291 unreachable!()
292 },
293 }
294 }
295 }
296 }
297}
src/librustc_interface/profile/trace.rs deleted-304
......@@ -1,304 +0,0 @@
1use super::*;
2use syntax_pos::SpanData;
3use rustc_data_structures::fx::FxHashMap;
4use rustc::util::common::QueryMsg;
5use std::fs::File;
6use std::time::{Duration, Instant};
7use rustc::dep_graph::{DepNode};
8
9#[derive(Debug, Clone, Eq, PartialEq)]
10pub struct Query {
11 pub span: SpanData,
12 pub msg: QueryMsg,
13}
14pub enum Effect {
15 QueryBegin(Query, CacheCase),
16 TimeBegin(String),
17 TaskBegin(DepNode),
18}
19pub enum CacheCase {
20 Hit, Miss
21}
22/// Recursive trace structure
23pub struct Rec {
24 pub effect: Effect,
25 pub start: Instant,
26 pub dur_self: Duration,
27 pub dur_total: Duration,
28 pub extent: Box<Vec<Rec>>,
29}
30pub struct QueryMetric {
31 pub count: usize,
32 pub dur_self: Duration,
33 pub dur_total: Duration,
34}
35
36fn cons(s: &str) -> String {
37 let first = s.split(|d| d == '(' || d == '{').next();
38 assert!(first.is_some() && first != Some(""));
39 first.unwrap().to_owned()
40}
41
42pub fn cons_of_query_msg(q: &trace::Query) -> String {
43 cons(&format!("{:?}", q.msg))
44}
45
46pub fn cons_of_key(k: &DepNode) -> String {
47 cons(&format!("{:?}", k))
48}
49
50// First return value is text; second return value is a CSS class
51pub fn html_of_effect(eff: &Effect) -> (String, String) {
52 match *eff {
53 Effect::TimeBegin(ref msg) => {
54 (msg.clone(),
55 "time-begin".to_string())
56 },
57 Effect::TaskBegin(ref key) => {
58 let cons = cons_of_key(key);
59 (cons.clone(), format!("{} task-begin", cons))
60 },
61 Effect::QueryBegin(ref qmsg, ref cc) => {
62 let cons = cons_of_query_msg(qmsg);
63 (cons.clone(),
64 format!("{} {}",
65 cons,
66 match *cc {
67 CacheCase::Hit => "hit",
68 CacheCase::Miss => "miss",
69 }))
70 }
71 }
72}
73
74// First return value is text; second return value is a CSS class
75fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) {
76 use rustc::util::common::duration_to_secs_str;
77 (duration_to_secs_str(dur.clone()), String::new())
78}
79
80fn html_of_fraction(frac: f64) -> (String, &'static str) {
81 let css = {
82 if frac > 0.50 { "frac-50" }
83 else if frac > 0.40 { "frac-40" }
84 else if frac > 0.30 { "frac-30" }
85 else if frac > 0.20 { "frac-20" }
86 else if frac > 0.10 { "frac-10" }
87 else if frac > 0.05 { "frac-05" }
88 else if frac > 0.02 { "frac-02" }
89 else if frac > 0.01 { "frac-01" }
90 else if frac > 0.001 { "frac-001" }
91 else { "frac-0" }
92 };
93 let percent = frac * 100.0;
94
95 if percent > 0.1 {
96 (format!("{:.1}%", percent), css)
97 } else {
98 ("< 0.1%".to_string(), css)
99 }
100}
101
102fn total_duration(traces: &[Rec]) -> Duration {
103 Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum()
104}
105
106fn duration_div(nom: Duration, den: Duration) -> f64 {
107 fn to_nanos(d: Duration) -> u64 {
108 d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64
109 }
110
111 to_nanos(nom) as f64 / to_nanos(den) as f64
112}
113
114fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usize) {
115 for t in traces {
116 let (eff_text, eff_css_classes) = html_of_effect(&t.effect);
117 let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total);
118 let fraction = duration_div(t.dur_total, total);
119 let percent = fraction * 100.0;
120 let (frc_text, frc_css_classes) = html_of_fraction(fraction);
121 writeln!(file, "<div class=\"trace depth-{} extent-{}{} {} {} {}\">",
122 depth,
123 t.extent.len(),
124 /* Heuristic for 'important' CSS class: */
125 if t.extent.len() > 5 || percent >= 1.0 { " important" } else { "" },
126 eff_css_classes,
127 dur_css_classes,
128 frc_css_classes,
129 ).unwrap();
130 writeln!(file, "<div class=\"eff\">{}</div>", eff_text).unwrap();
131 writeln!(file, "<div class=\"dur\">{}</div>", dur_text).unwrap();
132 writeln!(file, "<div class=\"frc\">{}</div>", frc_text).unwrap();
133 write_traces_rec(file, &t.extent, total, depth + 1);
134 writeln!(file, "</div>").unwrap();
135 }
136}
137
138fn compute_counts_rec(counts: &mut FxHashMap<String,QueryMetric>, traces: &[Rec]) {
139 counts.reserve(traces.len());
140 for t in traces.iter() {
141 match t.effect {
142 Effect::TimeBegin(ref msg) => {
143 let qm = match counts.get(msg) {
144 Some(_qm) => panic!("TimeBegin with non-unique, repeat message"),
145 None => QueryMetric {
146 count: 1,
147 dur_self: t.dur_self,
148 dur_total: t.dur_total,
149 }
150 };
151 counts.insert(msg.clone(), qm);
152 },
153 Effect::TaskBegin(ref key) => {
154 let cons = cons_of_key(key);
155 let qm = match counts.get(&cons) {
156 Some(qm) =>
157 QueryMetric {
158 count: qm.count + 1,
159 dur_self: qm.dur_self + t.dur_self,
160 dur_total: qm.dur_total + t.dur_total,
161 },
162 None => QueryMetric {
163 count: 1,
164 dur_self: t.dur_self,
165 dur_total: t.dur_total,
166 }
167 };
168 counts.insert(cons, qm);
169 },
170 Effect::QueryBegin(ref qmsg, ref _cc) => {
171 let qcons = cons_of_query_msg(qmsg);
172 let qm = match counts.get(&qcons) {
173 Some(qm) =>
174 QueryMetric {
175 count: qm.count + 1,
176 dur_total: qm.dur_total + t.dur_total,
177 dur_self: qm.dur_self + t.dur_self
178 },
179 None => QueryMetric {
180 count: 1,
181 dur_total: t.dur_total,
182 dur_self: t.dur_self,
183 }
184 };
185 counts.insert(qcons, qm);
186 }
187 }
188 compute_counts_rec(counts, &t.extent)
189 }
190}
191
192pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap<String, QueryMetric>) {
193 use rustc::util::common::duration_to_secs_str;
194 use std::cmp::Reverse;
195
196 let mut data = counts.iter().map(|(ref cons, ref qm)|
197 (cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone())
198 ).collect::<Vec<_>>();
199
200 data.sort_by_key(|k| Reverse(k.3));
201 for (cons, count, dur_total, dur_self) in data {
202 writeln!(count_file, "{}, {}, {}, {}",
203 cons, count,
204 duration_to_secs_str(dur_total),
205 duration_to_secs_str(dur_self)
206 ).unwrap();
207 }
208}
209
210pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &[Rec]) {
211 let capacity = traces.iter().fold(0, |acc, t| acc + 1 + t.extent.len());
212 let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
213 compute_counts_rec(&mut counts, traces);
214 write_counts(counts_file, &mut counts);
215
216 let total: Duration = total_duration(traces);
217 write_traces_rec(html_file, traces, total, 0)
218}
219
220pub fn write_style(html_file: &mut File) {
221 write!(html_file, "{}", "
222body {
223 font-family: sans-serif;
224 background: black;
225}
226.trace {
227 color: black;
228 display: inline-block;
229 border-style: solid;
230 border-color: red;
231 border-width: 1px;
232 border-radius: 5px;
233 padding: 0px;
234 margin: 1px;
235 font-size: 0px;
236}
237.task-begin {
238 border-width: 1px;
239 color: white;
240 border-color: #ff8;
241 font-size: 0px;
242}
243.miss {
244 border-color: red;
245 border-width: 1px;
246}
247.extent-0 {
248 padding: 2px;
249}
250.time-begin {
251 border-width: 4px;
252 font-size: 12px;
253 color: white;
254 border-color: #afa;
255}
256.important {
257 border-width: 3px;
258 font-size: 12px;
259 color: white;
260 border-color: #f77;
261}
262.hit {
263 padding: 0px;
264 border-color: blue;
265 border-width: 3px;
266}
267.eff {
268 color: #fff;
269 display: inline-block;
270}
271.frc {
272 color: #7f7;
273 display: inline-block;
274}
275.dur {
276 display: none
277}
278.frac-50 {
279 padding: 10px;
280 border-width: 10px;
281 font-size: 32px;
282}
283.frac-40 {
284 padding: 8px;
285 border-width: 8px;
286 font-size: 24px;
287}
288.frac-30 {
289 padding: 6px;
290 border-width: 6px;
291 font-size: 18px;
292}
293.frac-20 {
294 padding: 4px;
295 border-width: 6px;
296 font-size: 16px;
297}
298.frac-10 {
299 padding: 2px;
300 border-width: 6px;
301 font-size: 14px;
302}
303").unwrap();
304}
src/librustc_lint/error_codes.rs+1-1
......@@ -1,4 +1,4 @@
11syntax::register_diagnostics! {
22;
3 E0721, // `await` keyword
3// E0721, // `await` keyword
44}
src/librustc_mir/error_codes.rs+1-1
......@@ -953,7 +953,7 @@ https://doc.rust-lang.org/std/cell/
953953"##,
954954
955955E0388: r##"
956E0388 was removed and is no longer issued.
956#### Note: this error code is no longer emitted by the compiler.
957957"##,
958958
959959E0389: r##"
src/librustc_passes/error_codes.rs+21-4
......@@ -1,12 +1,15 @@
11syntax::register_diagnostics! {
2/*
32E0014: r##"
3#### Note: this error code is no longer emitted by the compiler.
4
45Constants can only be initialized by a constant value or, in a future
56version of Rust, a call to a const function. This error indicates the use
67of a path (like a::b, or x) denoting something other than one of these
7allowed items. Erroneous code xample:
8allowed items.
89
9```compile_fail
10Erroneous code example:
11
12```
1013const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
1114```
1215
......@@ -18,10 +21,10 @@ const FOO: i32 = { const X : i32 = 0; X };
1821const FOO2: i32 = { 0 }; // but brackets are useless here
1922```
2023"##,
21*/
2224
2325E0130: r##"
2426You declared a pattern as an argument in a foreign function declaration.
27
2528Erroneous code example:
2629
2730```compile_fail
......@@ -57,6 +60,20 @@ extern {
5760E0136: r##"
5861A binary can only have one entry point, and by default that entry point is the
5962function `main()`. If there are multiple such functions, please rename one.
63
64Erroneous code example:
65
66```compile_fail,E0136
67fn main() {
68 // ...
69}
70
71// ...
72
73fn main() { // error!
74 // ...
75}
76```
6077"##,
6178
6279E0137: r##"
src/librustc_privacy/error_codes.rs+17-6
......@@ -1,8 +1,9 @@
11syntax::register_diagnostics! {
22
33E0445: r##"
4A private trait was used on a public type parameter bound. Erroneous code
5examples:
4A private trait was used on a public type parameter bound.
5
6Erroneous code examples:
67
78```compile_fail,E0445
89#![deny(private_in_public)]
......@@ -32,7 +33,9 @@ pub fn foo<T: Foo> (t: T) {} // ok!
3233"##,
3334
3435E0446: r##"
35A private type was used in a public type signature. Erroneous code example:
36A private type was used in a public type signature.
37
38Erroneous code example:
3639
3740```compile_fail,E0446
3841#![deny(private_in_public)]
......@@ -65,7 +68,9 @@ mod Foo {
6568E0447: r##"
6669#### Note: this error code is no longer emitted by the compiler.
6770
68The `pub` keyword was used inside a function. Erroneous code example:
71The `pub` keyword was used inside a function.
72
73Erroneous code example:
6974
7075```
7176fn foo() {
......@@ -79,7 +84,11 @@ is invalid.
7984"##,
8085
8186E0448: r##"
82The `pub` keyword was used inside a public enum. Erroneous code example:
87#### Note: this error code is no longer emitted by the compiler.
88
89The `pub` keyword was used inside a public enum.
90
91Erroneous code example:
8392
8493```compile_fail
8594pub enum Foo {
......@@ -106,7 +115,9 @@ pub enum Foo {
106115"##,
107116
108117E0451: r##"
109A struct constructor with private fields was invoked. Erroneous code example:
118A struct constructor with private fields was invoked.
119
120Erroneous code example:
110121
111122```compile_fail,E0451
112123mod Bar {
src/librustc_resolve/diagnostics.rs+20-18
......@@ -20,7 +20,7 @@ use syntax_pos::{BytePos, Span, MultiSpan};
2020
2121use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
2222use crate::{path_names_to_string, KNOWN_TOOLS};
23use crate::{BindingError, CrateLint, LegacyScope, Module, ModuleOrUniformRoot};
23use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
2424use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};
2525
2626type Res = def::Res<ast::NodeId>;
......@@ -102,7 +102,7 @@ impl<'a> Resolver<'a> {
102102 &self, span: Span, resolution_error: ResolutionError<'_>
103103 ) -> DiagnosticBuilder<'_> {
104104 match resolution_error {
105 ResolutionError::GenericParamsFromOuterFunction(outer_res) => {
105 ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
106106 let mut err = struct_span_err!(self.session,
107107 span,
108108 E0401,
......@@ -148,22 +148,24 @@ impl<'a> Resolver<'a> {
148148 }
149149 }
150150
151 // Try to retrieve the span of the function signature and generate a new message
152 // with a local type or const parameter.
153 let sugg_msg = &format!("try using a local generic parameter instead");
154 if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
155 // Suggest the modification to the user
156 err.span_suggestion(
157 sugg_span,
158 sugg_msg,
159 new_snippet,
160 Applicability::MachineApplicable,
161 );
162 } else if let Some(sp) = cm.generate_fn_name_span(span) {
163 err.span_label(sp,
164 format!("try adding a local generic parameter in this method instead"));
165 } else {
166 err.help(&format!("try using a local generic parameter instead"));
151 if has_generic_params == HasGenericParams::Yes {
152 // Try to retrieve the span of the function signature and generate a new
153 // message with a local type or const parameter.
154 let sugg_msg = &format!("try using a local generic parameter instead");
155 if let Some((sugg_span, snippet)) = cm.generate_local_type_param_snippet(span) {
156 // Suggest the modification to the user
157 err.span_suggestion(
158 sugg_span,
159 sugg_msg,
160 snippet,
161 Applicability::MachineApplicable,
162 );
163 } else if let Some(sp) = cm.generate_fn_name_span(span) {
164 err.span_label(sp,
165 format!("try adding a local generic parameter in this method instead"));
166 } else {
167 err.help(&format!("try using a local generic parameter instead"));
168 }
167169 }
168170
169171 err
src/librustc_resolve/late.rs+116-139
......@@ -5,7 +5,6 @@
55//! If you wonder why there's no `early.rs`, that's because it's split into three files -
66//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`.
77
8use GenericParameters::*;
98use RibKind::*;
109
1110use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
......@@ -46,16 +45,6 @@ struct BindingInfo {
4645 binding_mode: BindingMode,
4746}
4847
49#[derive(Copy, Clone)]
50enum GenericParameters<'a, 'b> {
51 NoGenericParams,
52 HasGenericParams(// Type parameters.
53 &'b Generics,
54
55 // The kind of the rib used for type parameters.
56 RibKind<'a>),
57}
58
5948#[derive(Copy, Clone, PartialEq, Eq, Debug)]
6049enum PatternSource {
6150 Match,
......@@ -85,6 +74,10 @@ enum PatBoundCtx {
8574 Or,
8675}
8776
77/// Does this the item (from the item rib scope) allow generic parameters?
78#[derive(Copy, Clone, Debug, Eq, PartialEq)]
79crate enum HasGenericParams { Yes, No }
80
8881/// The rib kind restricts certain accesses,
8982/// e.g. to a `Res::Local` of an outer item.
9083#[derive(Copy, Clone, Debug)]
......@@ -103,7 +96,7 @@ crate enum RibKind<'a> {
10396 FnItemRibKind,
10497
10598 /// We passed through an item scope. Disallow upvars.
106 ItemRibKind,
99 ItemRibKind(HasGenericParams),
107100
108101 /// We're in a constant item. Can't refer to dynamic stuff.
109102 ConstantItemRibKind,
......@@ -134,7 +127,7 @@ impl RibKind<'_> {
134127 | ModuleRibKind(_)
135128 | MacroDefinition(_) => false,
136129 AssocItemRibKind
137 | ItemRibKind
130 | ItemRibKind(_)
138131 | ForwardTyParamBanRibKind
139132 | TyParamAsConstParamTy => true,
140133 }
......@@ -406,17 +399,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
406399 visit::walk_poly_trait_ref(self, tref, m);
407400 }
408401 fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
409 let generic_params = match foreign_item.kind {
402 match foreign_item.kind {
410403 ForeignItemKind::Fn(_, ref generics) => {
411 HasGenericParams(generics, ItemRibKind)
404 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
405 visit::walk_foreign_item(this, foreign_item);
406 });
412407 }
413 ForeignItemKind::Static(..) => NoGenericParams,
414 ForeignItemKind::Ty => NoGenericParams,
415 ForeignItemKind::Macro(..) => NoGenericParams,
416 };
417 self.with_generic_param_rib(generic_params, |this| {
418 visit::walk_foreign_item(this, foreign_item);
419 });
408 ForeignItemKind::Static(..) => {
409 self.with_item_rib(HasGenericParams::No, |this| {
410 visit::walk_foreign_item(this, foreign_item);
411 });
412 }
413 ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {
414 visit::walk_foreign_item(self, foreign_item);
415 }
416 }
420417 }
421418 fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) {
422419 debug!("(resolving function) entering function");
......@@ -660,7 +657,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
660657 fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
661658 debug!("resolve_adt");
662659 self.with_current_self_item(item, |this| {
663 this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
660 this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
664661 let item_def_id = this.r.definitions.local_def_id(item.id);
665662 this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| {
666663 visit::walk_item(this, item);
......@@ -719,10 +716,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
719716 ItemKind::TyAlias(_, ref generics) |
720717 ItemKind::OpaqueTy(_, ref generics) |
721718 ItemKind::Fn(_, _, ref generics, _) => {
722 self.with_generic_param_rib(
723 HasGenericParams(generics, ItemRibKind),
724 |this| visit::walk_item(this, item)
725 );
719 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes),
720 |this| visit::walk_item(this, item));
726721 }
727722
728723 ItemKind::Enum(_, ref generics) |
......@@ -740,7 +735,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
740735
741736 ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
742737 // Create a new rib for the trait-wide type parameters.
743 self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
738 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
744739 let local_def_id = this.r.definitions.local_def_id(item.id);
745740 this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
746741 this.visit_generics(generics);
......@@ -748,35 +743,32 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
748743
749744 for trait_item in trait_items {
750745 this.with_trait_items(trait_items, |this| {
751 let generic_params = HasGenericParams(
752 &trait_item.generics,
753 AssocItemRibKind,
754 );
755 this.with_generic_param_rib(generic_params, |this| {
756 match trait_item.kind {
757 TraitItemKind::Const(ref ty, ref default) => {
758 this.visit_ty(ty);
759
760 // Only impose the restrictions of
761 // ConstRibKind for an actual constant
762 // expression in a provided default.
763 if let Some(ref expr) = *default{
764 this.with_constant_rib(|this| {
765 this.visit_expr(expr);
766 });
746 this.with_generic_param_rib(&trait_item.generics, AssocItemRibKind,
747 |this| {
748 match trait_item.kind {
749 TraitItemKind::Const(ref ty, ref default) => {
750 this.visit_ty(ty);
751
752 // Only impose the restrictions of
753 // ConstRibKind for an actual constant
754 // expression in a provided default.
755 if let Some(ref expr) = *default{
756 this.with_constant_rib(|this| {
757 this.visit_expr(expr);
758 });
759 }
767760 }
768 }
769 TraitItemKind::Method(_, _) => {
770 visit::walk_trait_item(this, trait_item)
771 }
772 TraitItemKind::Type(..) => {
773 visit::walk_trait_item(this, trait_item)
774 }
775 TraitItemKind::Macro(_) => {
776 panic!("unexpanded macro in resolve!")
777 }
778 };
779 });
761 TraitItemKind::Method(_, _) => {
762 visit::walk_trait_item(this, trait_item)
763 }
764 TraitItemKind::Type(..) => {
765 visit::walk_trait_item(this, trait_item)
766 }
767 TraitItemKind::Macro(_) => {
768 panic!("unexpanded macro in resolve!")
769 }
770 };
771 });
780772 });
781773 }
782774 });
......@@ -785,7 +777,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
785777
786778 ItemKind::TraitAlias(ref generics, ref bounds) => {
787779 // Create a new rib for the trait-wide type parameters.
788 self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
780 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
789781 let local_def_id = this.r.definitions.local_def_id(item.id);
790782 this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
791783 this.visit_generics(generics);
......@@ -803,7 +795,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
803795 ItemKind::Static(ref ty, _, ref expr) |
804796 ItemKind::Const(ref ty, ref expr) => {
805797 debug!("resolve_item ItemKind::Const");
806 self.with_item_rib(|this| {
798 self.with_item_rib(HasGenericParams::No, |this| {
807799 this.visit_ty(ty);
808800 this.with_constant_rib(|this| {
809801 this.visit_expr(expr);
......@@ -824,91 +816,75 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
824816 }
825817 }
826818
827 fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters<'a, 'c>, f: F)
819 fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: RibKind<'a>, f: F)
828820 where F: FnOnce(&mut Self)
829821 {
830822 debug!("with_generic_param_rib");
831 match generic_params {
832 HasGenericParams(generics, rib_kind) => {
833 let mut function_type_rib = Rib::new(rib_kind);
834 let mut function_value_rib = Rib::new(rib_kind);
835 let mut seen_bindings = FxHashMap::default();
836 // We also can't shadow bindings from the parent item
837 if let AssocItemRibKind = rib_kind {
838 let mut add_bindings_for_ns = |ns| {
839 let parent_rib = self.ribs[ns].iter()
840 .rfind(|rib| if let ItemRibKind = rib.kind { true } else { false })
841 .expect("associated item outside of an item");
842 seen_bindings.extend(
843 parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)),
844 );
845 };
846 add_bindings_for_ns(ValueNS);
847 add_bindings_for_ns(TypeNS);
848 }
849 for param in &generics.params {
850 match param.kind {
851 GenericParamKind::Lifetime { .. } => {}
852 GenericParamKind::Type { .. } => {
853 let ident = param.ident.modern();
854 debug!("with_generic_param_rib: {}", param.id);
855
856 if seen_bindings.contains_key(&ident) {
857 let span = seen_bindings.get(&ident).unwrap();
858 let err = ResolutionError::NameAlreadyUsedInParameterList(
859 ident.name,
860 *span,
861 );
862 self.r.report_error(param.ident.span, err);
863 }
864 seen_bindings.entry(ident).or_insert(param.ident.span);
865
866 // Plain insert (no renaming).
867 let res = Res::Def(
868 DefKind::TyParam,
869 self.r.definitions.local_def_id(param.id),
870 );
871 function_type_rib.bindings.insert(ident, res);
872 self.r.record_partial_res(param.id, PartialRes::new(res));
873 }
874 GenericParamKind::Const { .. } => {
875 let ident = param.ident.modern();
876 debug!("with_generic_param_rib: {}", param.id);
877
878 if seen_bindings.contains_key(&ident) {
879 let span = seen_bindings.get(&ident).unwrap();
880 let err = ResolutionError::NameAlreadyUsedInParameterList(
881 ident.name,
882 *span,
883 );
884 self.r.report_error(param.ident.span, err);
885 }
886 seen_bindings.entry(ident).or_insert(param.ident.span);
887
888 let res = Res::Def(
889 DefKind::ConstParam,
890 self.r.definitions.local_def_id(param.id),
891 );
892 function_value_rib.bindings.insert(ident, res);
893 self.r.record_partial_res(param.id, PartialRes::new(res));
894 }
895 }
896 }
897 self.ribs[ValueNS].push(function_value_rib);
898 self.ribs[TypeNS].push(function_type_rib);
823 let mut function_type_rib = Rib::new(kind);
824 let mut function_value_rib = Rib::new(kind);
825 let mut seen_bindings = FxHashMap::default();
826
827 // We also can't shadow bindings from the parent item
828 if let AssocItemRibKind = kind {
829 let mut add_bindings_for_ns = |ns| {
830 let parent_rib = self.ribs[ns].iter()
831 .rfind(|r| if let ItemRibKind(_) = r.kind { true } else { false })
832 .expect("associated item outside of an item");
833 seen_bindings.extend(
834 parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)),
835 );
836 };
837 add_bindings_for_ns(ValueNS);
838 add_bindings_for_ns(TypeNS);
839 }
840
841 for param in &generics.params {
842 if let GenericParamKind::Lifetime { .. } = param.kind {
843 continue;
899844 }
900845
901 NoGenericParams => {
902 // Nothing to do.
846 let def_kind = match param.kind {
847 GenericParamKind::Type { .. } => DefKind::TyParam,
848 GenericParamKind::Const { .. } => DefKind::ConstParam,
849 _ => unreachable!(),
850 };
851
852 let ident = param.ident.modern();
853 debug!("with_generic_param_rib: {}", param.id);
854
855 if seen_bindings.contains_key(&ident) {
856 let span = seen_bindings.get(&ident).unwrap();
857 let err = ResolutionError::NameAlreadyUsedInParameterList(
858 ident.name,
859 *span,
860 );
861 self.r.report_error(param.ident.span, err);
862 }
863 seen_bindings.entry(ident).or_insert(param.ident.span);
864
865 // Plain insert (no renaming).
866 let res = Res::Def(def_kind, self.r.definitions.local_def_id(param.id));
867
868 match param.kind {
869 GenericParamKind::Type { .. } => {
870 function_type_rib.bindings.insert(ident, res);
871 self.r.record_partial_res(param.id, PartialRes::new(res));
872 }
873 GenericParamKind::Const { .. } => {
874 function_value_rib.bindings.insert(ident, res);
875 self.r.record_partial_res(param.id, PartialRes::new(res));
876 }
877 _ => unreachable!(),
903878 }
904879 }
905880
881 self.ribs[ValueNS].push(function_value_rib);
882 self.ribs[TypeNS].push(function_type_rib);
883
906884 f(self);
907885
908 if let HasGenericParams(..) = generic_params {
909 self.ribs[TypeNS].pop();
910 self.ribs[ValueNS].pop();
911 }
886 self.ribs[TypeNS].pop();
887 self.ribs[ValueNS].pop();
912888 }
913889
914890 fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
......@@ -917,8 +893,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
917893 self.label_ribs.pop();
918894 }
919895
920 fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
921 self.with_rib(ValueNS, ItemRibKind, |this| this.with_rib(TypeNS, ItemRibKind, f))
896 fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce(&mut Self)) {
897 let kind = ItemRibKind(has_generic_params);
898 self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
922899 }
923900
924901 fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
......@@ -1023,7 +1000,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
10231000 impl_items: &[ImplItem]) {
10241001 debug!("resolve_implementation");
10251002 // If applicable, create a rib for the type parameters.
1026 self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
1003 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
10271004 // Dummy self type for better errors if `Self` is used in the trait path.
10281005 this.with_self_rib(Res::SelfTy(None, None), |this| {
10291006 // Resolve the trait reference, if necessary.
......@@ -1044,9 +1021,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
10441021 debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
10451022 for impl_item in impl_items {
10461023 // We also need a new scope for the impl item type parameters.
1047 let generic_params = HasGenericParams(&impl_item.generics,
1048 AssocItemRibKind);
1049 this.with_generic_param_rib(generic_params, |this| {
1024 this.with_generic_param_rib(&impl_item.generics,
1025 AssocItemRibKind,
1026 |this| {
10501027 use crate::ResolutionError::*;
10511028 match impl_item.kind {
10521029 ImplItemKind::Const(..) => {
src/librustc_resolve/lib.rs+25-21
......@@ -61,7 +61,7 @@ use rustc_data_structures::fx::FxIndexMap;
6161
6262use diagnostics::{Suggestion, ImportSuggestion};
6363use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
64use late::{PathSource, Rib, RibKind::*};
64use late::{HasGenericParams, PathSource, Rib, RibKind::*};
6565use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
6666use macros::{LegacyBinding, LegacyScope};
6767
......@@ -178,7 +178,7 @@ impl Ord for BindingError {
178178
179179enum ResolutionError<'a> {
180180 /// Error E0401: can't use type or const parameters from outer function.
181 GenericParamsFromOuterFunction(Res),
181 GenericParamsFromOuterFunction(Res, HasGenericParams),
182182 /// Error E0403: the name is already used for a type or const parameter in this generic
183183 /// parameter list.
184184 NameAlreadyUsedInParameterList(Name, Span),
......@@ -2156,7 +2156,7 @@ impl<'a> Resolver<'a> {
21562156 ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
21572157 // Nothing to do. Continue.
21582158 }
2159 ItemRibKind | FnItemRibKind | AssocItemRibKind => {
2159 ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => {
21602160 // This was an attempt to access an upvar inside a
21612161 // named function item. This is not allowed, so we
21622162 // report an error.
......@@ -2184,22 +2184,23 @@ impl<'a> Resolver<'a> {
21842184 }
21852185 Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
21862186 for rib in ribs {
2187 match rib.kind {
2187 let has_generic_params = match rib.kind {
21882188 NormalRibKind | AssocItemRibKind |
21892189 ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
21902190 ConstantItemRibKind | TyParamAsConstParamTy => {
21912191 // Nothing to do. Continue.
2192 continue;
21922193 }
2193 ItemRibKind | FnItemRibKind => {
2194 // This was an attempt to use a type parameter outside its scope.
2195 if record_used {
2196 self.report_error(
2197 span, ResolutionError::GenericParamsFromOuterFunction(res)
2198 );
2199 }
2200 return Res::Err;
2201 }
2194 // This was an attempt to use a type parameter outside its scope.
2195 ItemRibKind(has_generic_params) => has_generic_params,
2196 FnItemRibKind => HasGenericParams::Yes,
2197 };
2198
2199 if record_used {
2200 self.report_error(span, ResolutionError::GenericParamsFromOuterFunction(
2201 res, has_generic_params));
22022202 }
2203 return Res::Err;
22032204 }
22042205 }
22052206 Res::Def(DefKind::ConstParam, _) => {
......@@ -2211,15 +2212,18 @@ impl<'a> Resolver<'a> {
22112212 ribs.next();
22122213 }
22132214 for rib in ribs {
2214 if let ItemRibKind | FnItemRibKind = rib.kind {
2215 // This was an attempt to use a const parameter outside its scope.
2216 if record_used {
2217 self.report_error(
2218 span, ResolutionError::GenericParamsFromOuterFunction(res)
2219 );
2220 }
2221 return Res::Err;
2215 let has_generic_params = match rib.kind {
2216 ItemRibKind(has_generic_params) => has_generic_params,
2217 FnItemRibKind => HasGenericParams::Yes,
2218 _ => continue,
2219 };
2220
2221 // This was an attempt to use a const parameter outside its scope.
2222 if record_used {
2223 self.report_error(span, ResolutionError::GenericParamsFromOuterFunction(
2224 res, has_generic_params));
22222225 }
2226 return Res::Err;
22232227 }
22242228 }
22252229 _ => {}
src/librustc_typeck/check/demand.rs+4
......@@ -115,6 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
115115 Err(e) => e
116116 };
117117
118 let expr = expr.peel_drop_temps();
118119 let cause = self.misc(expr.span);
119120 let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
120121 let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
......@@ -355,6 +356,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
355356 };
356357 let is_macro = sp.from_expansion() && !is_desugaring;
357358
359 // `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
360 let expr = expr.peel_drop_temps();
361
358362 match (&expr.kind, &expected.kind, &checked_ty.kind) {
359363 (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) {
360364 (&ty::Str, &ty::Array(arr, _)) |
src/librustc_typeck/check/expr.rs+1-5
......@@ -87,12 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8787 }
8888
8989 if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
90 let expr = expr.peel_drop_temps();
9091 self.suggest_ref_or_into(&mut err, expr, expected_ty, ty);
91
92 let expr = match &expr.kind {
93 ExprKind::DropTemps(expr) => expr,
94 _ => expr,
95 };
9692 extend_err(&mut err);
9793 // Error possibly reported in `check_assign` so avoid emitting error again.
9894 err.emit_unless(self.is_assign_to_bool(expr, expected_ty));
src/librustc_typeck/check/method/suggest.rs+19-6
......@@ -538,13 +538,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
538538 }
539539 }
540540
541 let mut fallback_span = true;
542 let msg = "remove this method call";
541543 if item_name.as_str() == "as_str" && actual.peel_refs().is_str() {
542 // FIXME: the span is not quite correct, it should point to ".as_str()" instead
543 // of just "as_str".
544 err.span_label(
545 span,
546 "try removing `as_str`"
547 );
544 if let SelfSource::MethodCall(expr) = source {
545 let call_expr = self.tcx.hir().expect_expr(
546 self.tcx.hir().get_parent_node(expr.hir_id),
547 );
548 if let Some(span) = call_expr.span.trim_start(expr.span) {
549 err.span_suggestion(
550 span,
551 msg,
552 String::new(),
553 Applicability::MachineApplicable,
554 );
555 fallback_span = false;
556 }
557 }
558 if fallback_span {
559 err.span_label(span, msg);
560 }
548561 } else if let Some(lev_candidate) = lev_candidate {
549562 let def_kind = lev_candidate.def_kind();
550563 err.span_suggestion(
src/librustc_typeck/check/mod.rs+5-4
......@@ -4216,20 +4216,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
42164216 pub fn suggest_mismatched_types_on_tail(
42174217 &self,
42184218 err: &mut DiagnosticBuilder<'tcx>,
4219 expression: &'tcx hir::Expr,
4219 expr: &'tcx hir::Expr,
42204220 expected: Ty<'tcx>,
42214221 found: Ty<'tcx>,
42224222 cause_span: Span,
42234223 blk_id: hir::HirId,
42244224 ) -> bool {
4225 self.suggest_missing_semicolon(err, expression, expected, cause_span);
4225 let expr = expr.peel_drop_temps();
4226 self.suggest_missing_semicolon(err, expr, expected, cause_span);
42264227 let mut pointing_at_return_type = false;
42274228 if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
42284229 pointing_at_return_type = self.suggest_missing_return_type(
42294230 err, &fn_decl, expected, found, can_suggest);
42304231 }
4231 self.suggest_ref_or_into(err, expression, expected, found);
4232 self.suggest_boxing_when_appropriate(err, expression, expected, found);
4232 self.suggest_ref_or_into(err, expr, expected, found);
4233 self.suggest_boxing_when_appropriate(err, expr, expected, found);
42334234 pointing_at_return_type
42344235 }
42354236
src/librustc_typeck/error_codes.rs+15-17
......@@ -1873,13 +1873,14 @@ This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
18731873differs from the behavior for `&T`, which is always `Copy`).
18741874"##,
18751875
1876/*
18771876E0205: r##"
1877#### Note: this error code is no longer emitted by the compiler.
1878
18781879An attempt to implement the `Copy` trait for an enum failed because one of the
18791880variants does not implement `Copy`. To fix this, you must implement `Copy` for
18801881the mentioned variant. Note that this may not be possible, as in the example of
18811882
1882```compile_fail,E0205
1883```compile_fail,E0204
18831884enum Foo {
18841885 Bar(Vec<u32>),
18851886 Baz,
......@@ -1892,7 +1893,7 @@ This fails because `Vec<T>` does not implement `Copy` for any `T`.
18921893
18931894Here's another example that will fail:
18941895
1895```compile_fail,E0205
1896```compile_fail,E0204
18961897#[derive(Copy)]
18971898enum Foo<'a> {
18981899 Bar(&'a mut bool),
......@@ -1903,7 +1904,6 @@ enum Foo<'a> {
19031904This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this
19041905differs from the behavior for `&T`, which is always `Copy`).
19051906"##,
1906*/
19071907
19081908E0206: r##"
19091909You can only implement `Copy` for a struct or enum. Both of the following
......@@ -2126,8 +2126,9 @@ For information on the design of the orphan rules, see [RFC 1023].
21262126[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
21272127"##,
21282128
2129/*
21302129E0211: r##"
2130#### Note: this error code is no longer emitted by the compiler.
2131
21312132You used a function or type which doesn't fit the requirements for where it was
21322133used. Erroneous code examples:
21332134
......@@ -2174,7 +2175,7 @@ extern "rust-intrinsic" {
21742175}
21752176```
21762177
2177The second case example is a bit particular : the main function must always
2178The second case example is a bit particular: the main function must always
21782179have this definition:
21792180
21802181```compile_fail
......@@ -2206,7 +2207,6 @@ impl Foo {
22062207}
22072208```
22082209"##,
2209 */
22102210
22112211E0220: r##"
22122212You used an associated type which isn't defined in the trait.
......@@ -2727,14 +2727,9 @@ impl<T, U> CoerceUnsized<MyType<U>> for MyType<T>
27272727[`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html
27282728"##,
27292729
2730/*
2731// Associated consts can now be accessed through generic type parameters, and
2732// this error is no longer emitted.
2733//
2734// FIXME: consider whether to leave it in the error index, or remove it entirely
2735// as associated consts is not stabilized yet.
2736
27372730E0329: r##"
2731#### Note: this error code is no longer emitted by the compiler.
2732
27382733An attempt was made to access an associated constant through either a generic
27392734type parameter or `Self`. This is not supported yet. An example causing this
27402735error is shown below:
......@@ -2765,12 +2760,15 @@ trait Foo {
27652760
27662761struct MyStruct;
27672762
2763impl Foo for MyStruct {
2764 const BAR: f64 = 0f64;
2765}
2766
27682767fn get_bar_good() -> f64 {
27692768 <MyStruct as Foo>::BAR
27702769}
27712770```
27722771"##,
2773*/
27742772
27752773E0366: r##"
27762774An attempt was made to implement `Drop` on a concrete specialization of a
......@@ -4973,7 +4971,7 @@ and the pin is required to keep it in the same place in memory.
49734971 // between structures with the same definition
49744972// E0558, // replaced with a generic attribute input check
49754973// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
4976 E0564, // only named lifetimes are allowed in `impl Trait`,
4974// E0564, // only named lifetimes are allowed in `impl Trait`,
49774975 // but `{}` was found in the type `{}`
49784976 E0587, // type has conflicting packed and align representation hints
49794977 E0588, // packed type cannot transitively contain a `[repr(align)]` type
......@@ -4986,7 +4984,7 @@ and the pin is required to keep it in the same place in memory.
49864984 E0634, // type has conflicting packed representaton hints
49874985 E0640, // infer outlives requirements
49884986 E0641, // cannot cast to/from a pointer with an unknown kind
4989 E0645, // trait aliases not finished
4987// E0645, // trait aliases not finished
49904988 E0719, // duplicate values for associated type binding
49914989 E0722, // Malformed `#[optimize]` attribute
49924990 E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
src/libsyntax/early_buffered_lints.rs+1
......@@ -11,6 +11,7 @@ use syntax_pos::MultiSpan;
1111pub enum BufferedEarlyLintId {
1212 IllFormedAttributeInput,
1313 MetaVariableMisuse,
14 IncompleteInclude,
1415}
1516
1617/// Stores buffered lint info which can later be passed to `librustc`.
src/libsyntax_ext/source_util.rs+11-1
......@@ -5,6 +5,7 @@ use syntax::print::pprust;
55use syntax::ptr::P;
66use syntax::symbol::Symbol;
77use syntax::tokenstream::TokenStream;
8use syntax::early_buffered_lints::BufferedEarlyLintId;
89
910use smallvec::SmallVec;
1011use syntax_pos::{self, Pos, Span};
......@@ -83,7 +84,16 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
8384 }
8485 impl<'a> base::MacResult for ExpandResult<'a> {
8586 fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
86 Some(panictry!(self.p.parse_expr()))
87 let r = panictry!(self.p.parse_expr());
88 if self.p.token != token::Eof {
89 self.p.sess.buffer_lint(
90 BufferedEarlyLintId::IncompleteInclude,
91 self.p.token.span,
92 ast::CRATE_NODE_ID,
93 "include macro expected single expression in source",
94 );
95 }
96 Some(r)
8797 }
8898
8999 fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
src/test/ui/if/if-no-match-bindings.stderr+4-4
......@@ -29,7 +29,7 @@ LL | if &true {}
2929 | ^^^^^
3030 | |
3131 | expected bool, found &bool
32 | help: consider dereferencing the borrow: `*&true`
32 | help: consider removing the borrow: `true`
3333 |
3434 = note: expected type `bool`
3535 found type `&bool`
......@@ -41,7 +41,7 @@ LL | if &mut true {}
4141 | ^^^^^^^^^
4242 | |
4343 | expected bool, found &mut bool
44 | help: consider dereferencing the borrow: `*&mut true`
44 | help: consider removing the borrow: `true`
4545 |
4646 = note: expected type `bool`
4747 found type `&mut bool`
......@@ -77,7 +77,7 @@ LL | while &true {}
7777 | ^^^^^
7878 | |
7979 | expected bool, found &bool
80 | help: consider dereferencing the borrow: `*&true`
80 | help: consider removing the borrow: `true`
8181 |
8282 = note: expected type `bool`
8383 found type `&bool`
......@@ -89,7 +89,7 @@ LL | while &mut true {}
8989 | ^^^^^^^^^
9090 | |
9191 | expected bool, found &mut bool
92 | help: consider dereferencing the borrow: `*&mut true`
92 | help: consider removing the borrow: `true`
9393 |
9494 = note: expected type `bool`
9595 found type `&mut bool`
src/test/ui/include-single-expr-helper-1.rs created+5
......@@ -0,0 +1,5 @@
1// ignore-test auxiliary file for include-single-expr.rs
2
30
4
5// trailing comment permitted
src/test/ui/include-single-expr-helper.rs created+5
......@@ -0,0 +1,5 @@
1// ignore-test auxiliary file for include-single-expr.rs
2
30
410
5100
src/test/ui/include-single-expr.rs created+6
......@@ -0,0 +1,6 @@
1// error-pattern include macro expected single expression
2
3fn main() {
4 include!("include-single-expr-helper.rs");
5 include!("include-single-expr-helper-1.rs");
6}
src/test/ui/include-single-expr.stderr created+10
......@@ -0,0 +1,10 @@
1error: include macro expected single expression in source
2 --> $DIR/include-single-expr-helper.rs:4:1
3 |
4LL | 10
5 | ^^
6 |
7 = note: `#[deny(incomplete_include)]` on by default
8
9error: aborting due to previous error
10
src/test/ui/inner-static-type-parameter.stderr+1-3
......@@ -2,9 +2,7 @@ error[E0401]: can't use generic parameters from outer function
22 --> $DIR/inner-static-type-parameter.rs:6:19
33 |
44LL | fn foo<T>() {
5 | --- - type parameter from outer function
6 | |
7 | try adding a local generic parameter in this method instead
5 | - type parameter from outer function
86LL | static a: Bar<T> = Bar::What;
97 | ^ use of generic parameter from outer function
108
src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs created+10
......@@ -0,0 +1,10 @@
1unsafe fn foo<A>() {
2 extern "C" {
3 static baz: *const A;
4 //~^ ERROR can't use generic parameters from outer function
5 }
6
7 let bar: *const u64 = core::mem::transmute(&baz);
8}
9
10fn main() { }
src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr created+12
......@@ -0,0 +1,12 @@
1error[E0401]: can't use generic parameters from outer function
2 --> $DIR/issue-65025-extern-static-parent-generics.rs:3:28
3 |
4LL | unsafe fn foo<A>() {
5 | - type parameter from outer function
6LL | extern "C" {
7LL | static baz: *const A;
8 | ^ use of generic parameter from outer function
9
10error: aborting due to previous error
11
12For more information about this error, try `rustc --explain E0401`.
src/test/ui/resolve/issue-65035-static-with-parent-generics.rs created+29
......@@ -0,0 +1,29 @@
1#![feature(const_generics)]
2//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3
4fn f<T>() {
5 extern "C" {
6 static a: *const T;
7 //~^ ERROR can't use generic parameters from outer function
8 }
9}
10
11fn g<T: Default>() {
12 static a: *const T = Default::default();
13 //~^ ERROR can't use generic parameters from outer function
14}
15
16fn h<const N: usize>() {
17 extern "C" {
18 static a: [u8; N];
19 //~^ ERROR can't use generic parameters from outer function
20 }
21}
22
23fn i<const N: usize>() {
24 static a: [u8; N] = [0; N];
25 //~^ ERROR can't use generic parameters from outer function
26 //~^^ ERROR can't use generic parameters from outer function
27}
28
29fn main() {}
src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr created+53
......@@ -0,0 +1,53 @@
1error[E0401]: can't use generic parameters from outer function
2 --> $DIR/issue-65035-static-with-parent-generics.rs:6:26
3 |
4LL | fn f<T>() {
5 | - type parameter from outer function
6LL | extern "C" {
7LL | static a: *const T;
8 | ^ use of generic parameter from outer function
9
10error[E0401]: can't use generic parameters from outer function
11 --> $DIR/issue-65035-static-with-parent-generics.rs:12:22
12 |
13LL | fn g<T: Default>() {
14 | - type parameter from outer function
15LL | static a: *const T = Default::default();
16 | ^ use of generic parameter from outer function
17
18error[E0401]: can't use generic parameters from outer function
19 --> $DIR/issue-65035-static-with-parent-generics.rs:18:24
20 |
21LL | fn h<const N: usize>() {
22 | - const parameter from outer function
23LL | extern "C" {
24LL | static a: [u8; N];
25 | ^ use of generic parameter from outer function
26
27error[E0401]: can't use generic parameters from outer function
28 --> $DIR/issue-65035-static-with-parent-generics.rs:24:20
29 |
30LL | fn i<const N: usize>() {
31 | - const parameter from outer function
32LL | static a: [u8; N] = [0; N];
33 | ^ use of generic parameter from outer function
34
35error[E0401]: can't use generic parameters from outer function
36 --> $DIR/issue-65035-static-with-parent-generics.rs:24:29
37 |
38LL | fn i<const N: usize>() {
39 | - const parameter from outer function
40LL | static a: [u8; N] = [0; N];
41 | ^ use of generic parameter from outer function
42
43warning: the feature `const_generics` is incomplete and may cause the compiler to crash
44 --> $DIR/issue-65035-static-with-parent-generics.rs:1:12
45 |
46LL | #![feature(const_generics)]
47 | ^^^^^^^^^^^^^^
48 |
49 = note: `#[warn(incomplete_features)]` on by default
50
51error: aborting due to 5 previous errors
52
53For more information about this error, try `rustc --explain E0401`.
src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr+2-2
......@@ -520,7 +520,7 @@ LL | if &let 0 = 0 {}
520520 | ^^^^^^^^^^
521521 | |
522522 | expected bool, found &bool
523 | help: consider dereferencing the borrow: `*&let 0 = 0`
523 | help: consider removing the borrow: `let 0 = 0`
524524 |
525525 = note: expected type `bool`
526526 found type `&bool`
......@@ -708,7 +708,7 @@ LL | while &let 0 = 0 {}
708708 | ^^^^^^^^^^
709709 | |
710710 | expected bool, found &bool
711 | help: consider dereferencing the borrow: `*&let 0 = 0`
711 | help: consider removing the borrow: `let 0 = 0`
712712 |
713713 = note: expected type `bool`
714714 found type `&bool`
src/test/ui/suggestions/remove-as_str.stderr+4-4
......@@ -2,25 +2,25 @@ error[E0599]: no method named `as_str` found for type `&str` in the current scop
22 --> $DIR/remove-as_str.rs:2:7
33 |
44LL | s.as_str();
5 | ^^^^^^ try removing `as_str`
5 | -^^^^^^-- help: remove this method call
66
77error[E0599]: no method named `as_str` found for type `&'a str` in the current scope
88 --> $DIR/remove-as_str.rs:7:7
99 |
1010LL | s.as_str();
11 | ^^^^^^ try removing `as_str`
11 | -^^^^^^-- help: remove this method call
1212
1313error[E0599]: no method named `as_str` found for type `&mut str` in the current scope
1414 --> $DIR/remove-as_str.rs:12:7
1515 |
1616LL | s.as_str();
17 | ^^^^^^ try removing `as_str`
17 | -^^^^^^-- help: remove this method call
1818
1919error[E0599]: no method named `as_str` found for type `&&str` in the current scope
2020 --> $DIR/remove-as_str.rs:17:7
2121 |
2222LL | s.as_str();
23 | ^^^^^^ try removing `as_str`
23 | -^^^^^^-- help: remove this method call
2424
2525error: aborting due to 4 previous errors
2626
src/tools/error_index_generator/build.rs+1-1
......@@ -15,7 +15,7 @@ fn main() {
1515 println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap());
1616 let file = fs::read_to_string(entry.path()).unwrap()
1717 .replace("syntax::register_diagnostics!", "register_diagnostics!");
18 let contents = format!("(|| {{\n{}\n}})();", file);
18 let contents = format!("(|| {{\n{}\n}})()", file);
1919
2020 fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap();
2121
src/tools/tidy/src/error_codes_check.rs created+137
......@@ -0,0 +1,137 @@
1//! Checks that all error codes have at least one test to prevent having error
2//! codes that are silently not thrown by the compiler anymore.
3
4use std::collections::HashMap;
5use std::ffi::OsStr;
6use std::path::Path;
7
8// A few of those error codes can't be tested but all the others can and *should* be tested!
9const WHITELIST: &[&str] = &[
10 "E0183",
11 "E0227",
12 "E0279",
13 "E0280",
14 "E0311",
15 "E0313",
16 "E0314",
17 "E0315",
18 "E0377",
19 "E0456",
20 "E0461",
21 "E0462",
22 "E0464",
23 "E0465",
24 "E0472",
25 "E0473",
26 "E0474",
27 "E0475",
28 "E0476",
29 "E0479",
30 "E0480",
31 "E0481",
32 "E0482",
33 "E0483",
34 "E0484",
35 "E0485",
36 "E0486",
37 "E0487",
38 "E0488",
39 "E0489",
40 "E0514",
41 "E0519",
42 "E0523",
43 "E0526",
44 "E0554",
45 "E0570",
46 "E0629",
47 "E0630",
48 "E0640",
49 "E0717",
50 "E0727",
51 "E0729",
52];
53
54fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>) {
55 let mut reached_no_explanation = false;
56 let mut last_error_code = None;
57
58 for line in f.lines() {
59 let s = line.trim();
60 if s.starts_with('E') && s.ends_with(": r##\"") {
61 if let Some(err_code) = s.splitn(2, ':').next() {
62 let err_code = err_code.to_owned();
63 last_error_code = Some(err_code.clone());
64 if !error_codes.contains_key(&err_code) {
65 error_codes.insert(err_code, false);
66 }
67 }
68 } else if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
69 if let Some(err_code) = s.splitn(2, 'E').skip(1).next() {
70 if let Some(err_code) = err_code.splitn(2, ',').next() {
71 let nb = error_codes.entry(format!("E{}", err_code)).or_insert(false);
72 *nb = true;
73 }
74 }
75 } else if s == ";" {
76 reached_no_explanation = true;
77 } else if reached_no_explanation && s.starts_with('E') {
78 if let Some(err_code) = s.splitn(2, ',').next() {
79 let err_code = err_code.to_owned();
80 if !error_codes.contains_key(&err_code) { // this check should *never* fail!
81 error_codes.insert(err_code, false);
82 }
83 }
84 } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
85 if let Some(last) = last_error_code {
86 error_codes.get_mut(&last).map(|x| *x = true);
87 }
88 last_error_code = None;
89 }
90 }
91}
92
93fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, bool>) {
94 for line in f.lines() {
95 let s = line.trim();
96 if s.starts_with("error[E") || s.starts_with("warning[E") {
97 if let Some(err_code) = s.splitn(2, ']').next() {
98 if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() {
99 let nb = error_codes.entry(err_code.to_owned()).or_insert(false);
100 *nb = true;
101 }
102 }
103 }
104 }
105}
106
107pub fn check(path: &Path, bad: &mut bool) {
108 println!("Checking which error codes lack tests...");
109 let mut error_codes: HashMap<String, bool> = HashMap::new();
110 super::walk(path,
111 &mut |path| super::filter_dirs(path),
112 &mut |entry, contents| {
113 let file_name = entry.file_name();
114 if file_name == "error_codes.rs" {
115 extract_error_codes(contents, &mut error_codes);
116 } else if entry.path().extension() == Some(OsStr::new("stderr")) {
117 extract_error_codes_from_tests(contents, &mut error_codes);
118 }
119 });
120 println!("Found {} error codes", error_codes.len());
121
122 let mut errors = Vec::new();
123 for (err_code, nb) in &error_codes {
124 if !*nb && !WHITELIST.contains(&err_code.as_str()) {
125 errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
126 }
127 }
128 errors.sort();
129 for err in &errors {
130 eprintln!("{}", err);
131 }
132 println!("Found {} error codes with no tests", errors.len());
133 if !errors.is_empty() {
134 *bad = true;
135 }
136 println!("Done!");
137}
src/tools/tidy/src/lib.rs+1
......@@ -41,6 +41,7 @@ pub mod extdeps;
4141pub mod ui_tests;
4242pub mod unit_tests;
4343pub mod unstable_book;
44pub mod error_codes_check;
4445
4546fn filter_dirs(path: &Path) -> bool {
4647 let skip = [
src/tools/tidy/src/main.rs+1
......@@ -35,6 +35,7 @@ fn main() {
3535 deps::check_whitelist(&path, &cargo, &mut bad);
3636 extdeps::check(&path, &mut bad);
3737 ui_tests::check(&path, &mut bad);
38 error_codes_check::check(&path, &mut bad);
3839
3940 if bad {
4041 eprintln!("some tidy checks failed");