From 96b549a2ee6d309d22f909d285c63b3346be3c4e Mon Sep 17 00:00:00 2001 From: Yossi Konstantinovsky Date: Fri, 2 Sep 2016 02:31:40 +0200 Subject: [PATCH 01/10] Update E0088 to new format, remove E0090 --- src/librustc_typeck/check/mod.rs | 31 +++++++++++++++++++------------ src/test/compile-fail/E0088.rs | 5 +++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a95b3f4a973bb..f76d356e045d5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4412,20 +4412,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Check provided lifetime parameters. let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); if lifetimes.len() > lifetime_defs.len() { - let span = lifetimes[lifetime_defs.len()].span; - span_err!(self.tcx.sess, span, E0088, - "too many lifetime parameters provided: \ - expected {}, found {}", - count(lifetime_defs.len()), - count(lifetimes.len())); - } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() { - span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: \ - expected {}, found {}", - count(lifetime_defs.len()), - count(lifetimes.len())); + let span = lifetimes[..].into_iter().skip(1).map(|lft| lft.span) + .fold(lifetimes[0].span, |acc, n| Span { + expn_id: acc.expn_id, + lo: acc.lo, + hi: n.hi, + }); + + struct_span_err!(self.tcx.sess, span, E0088, + "too many lifetime parameters provided: \ + expected {}, found {}", + count(lifetime_defs.len()), + count(lifetimes.len())) + .span_label(span, &format!("unexpected lifetime parameter{}", + match lifetimes.len() { 1 => "", _ => "s" })) + .emit(); } + // The case where there is not enough lifetime parameters is not checked, + // because this is not possible - a function never takes lifetime parameters. + // See discussion for Pull Request 36208. + // Check provided type parameters. let type_defs = segment.map_or(&[][..], |(_, generics)| { if generics.parent.is_none() { diff --git a/src/test/compile-fail/E0088.rs b/src/test/compile-fail/E0088.rs index 0b235aa240c3c..724398ada5216 100644 --- a/src/test/compile-fail/E0088.rs +++ b/src/test/compile-fail/E0088.rs @@ -9,7 +9,12 @@ // except according to those terms. fn f() {} +fn g<'a>() {} fn main() { f::<'static>(); //~ ERROR E0088 + //~^ unexpected lifetime parameter + + g::<'static, 'static>(); //~ ERROR E0088 + //~^ unexpected lifetime parameters } From 92abce2addffb8394406fda764e83e81ebd29d08 Mon Sep 17 00:00:00 2001 From: Omer Sheikh Date: Wed, 16 Nov 2016 20:56:57 -0500 Subject: [PATCH 02/10] Use span of first unexpected lifetime in E0088. --- src/librustc_typeck/check/mod.rs | 10 ++-------- src/test/compile-fail/E0088.rs | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f76d356e045d5..fe6dbe96a96ea 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4412,13 +4412,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Check provided lifetime parameters. let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); if lifetimes.len() > lifetime_defs.len() { - let span = lifetimes[..].into_iter().skip(1).map(|lft| lft.span) - .fold(lifetimes[0].span, |acc, n| Span { - expn_id: acc.expn_id, - lo: acc.lo, - hi: n.hi, - }); - + let span = lifetimes[lifetime_defs.len()].span; struct_span_err!(self.tcx.sess, span, E0088, "too many lifetime parameters provided: \ expected {}, found {}", @@ -4430,7 +4424,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // The case where there is not enough lifetime parameters is not checked, - // because this is not possible - a function never takes lifetime parameters. + // because this is not possible - a function never takes lifetime parameters. // See discussion for Pull Request 36208. // Check provided type parameters. diff --git a/src/test/compile-fail/E0088.rs b/src/test/compile-fail/E0088.rs index 724398ada5216..9ec0960322410 100644 --- a/src/test/compile-fail/E0088.rs +++ b/src/test/compile-fail/E0088.rs @@ -14,7 +14,7 @@ fn g<'a>() {} fn main() { f::<'static>(); //~ ERROR E0088 //~^ unexpected lifetime parameter - + g::<'static, 'static>(); //~ ERROR E0088 //~^ unexpected lifetime parameters } From ce57c66f5ca6120345bfc0828ebddd1b2f1d615e Mon Sep 17 00:00:00 2001 From: Brett Cooley Date: Thu, 17 Nov 2016 12:23:57 -0700 Subject: [PATCH 03/10] Fix grammar error in lifetimes.md --- src/doc/book/lifetimes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 397263c697330..140e27d19248c 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -352,7 +352,7 @@ to it. Rust supports powerful local type inference in the bodies of functions but not in their item signatures. It's forbidden to allow reasoning about types based on the item signature alone. However, for ergonomic reasons, a very restricted secondary inference algorithm called -“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely to infer +“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision acts as a shorthand for writing an item signature, while not hiding away the actual types involved as full local inference would if applied to it. From 83ee4e93e0b142ea199b8407c23015a6865f9a04 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 17 Nov 2016 14:28:38 -0500 Subject: [PATCH 04/10] ICH: Add regression tests for various kinds of loops. --- src/test/incremental/hashes/for_loops.rs | 306 ++++++++++++++++++ .../incremental/hashes/loop_expressions.rs | 231 +++++++++++++ .../incremental/hashes/while_let_loops.rs | 256 +++++++++++++++ src/test/incremental/hashes/while_loops.rs | 256 +++++++++++++++ 4 files changed, 1049 insertions(+) create mode 100644 src/test/incremental/hashes/for_loops.rs create mode 100644 src/test/incremental/hashes/loop_expressions.rs create mode 100644 src/test/incremental/hashes/while_let_loops.rs create mode 100644 src/test/incremental/hashes/while_loops.rs diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs new file mode 100644 index 0000000000000..7a8502f7caab1 --- /dev/null +++ b/src/test/incremental/hashes/for_loops.rs @@ -0,0 +1,306 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `for` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + for _ in 0..1 { + _x = 2; + break; + } +} + + + +// Change iteration variable name ---------------------------------------------- +#[cfg(cfail1)] +fn change_iteration_variable_name() { + let mut _x = 0; + for _i in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_iteration_variable_name() { + let mut _x = 0; + for _a in 0..1 { + _x = 1; + break; + } +} + + + +// Change iteration variable pattern ------------------------------------------- +#[cfg(cfail1)] +fn change_iteration_variable_pattern() { + let mut _x = 0; + for _i in &[0, 1, 2] { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_iteration_variable_pattern() { + let mut _x = 0; + for &_i in &[0, 1, 2] { + _x = 1; + break; + } +} + + + +// Change iterable ------------------------------------------------------------- +#[cfg(cfail1)] +fn change_iterable() { + let mut _x = 0; + for _ in &[0, 1, 2] { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_iterable() { + let mut _x = 0; + for _ in &[0, 1, 3] { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs new file mode 100644 index 0000000000000..eaa5f68b98c4b --- /dev/null +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -0,0 +1,231 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `loop` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + loop { + _x = 2; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + loop { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: loop { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: loop { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: loop { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: loop { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: loop { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + loop { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs new file mode 100644 index 0000000000000..405645bd1b842 --- /dev/null +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -0,0 +1,256 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `while let` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 2; + break; + } +} + + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_condition() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_condition() { + let mut _x = 0; + while let Some(1u32) = None { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs new file mode 100644 index 0000000000000..f16611ee463e0 --- /dev/null +++ b/src/test/incremental/hashes/while_loops.rs @@ -0,0 +1,256 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `while` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_body() { + let mut _x = 0; + while true { + _x = 2; + break; + } +} + + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_condition() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_loop_condition() { + let mut _x = 0; + while false { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + while true { + _x = 1; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_break() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label() { + let mut _x = 0; + 'label: while true { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while true { + _x = 1; + break; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while true { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + break 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_break_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while true { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while true { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + continue 'inner; + } + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + while true { + _x = 1; + continue; + } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +fn change_continue_to_break() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} From f0c9a9f4749c8db719d2913c3c7619665db1c0c2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Nov 2016 10:10:09 +1100 Subject: [PATCH 05/10] Don't clone in UnificationTable::probe(). This speeds up compilation of rustc-benchmarks/inflate-0.1.0 by 1%. --- src/librustc_data_structures/unify/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs index 1f4d09a92247e..e2d3a4f453749 100644 --- a/src/librustc_data_structures/unify/mod.rs +++ b/src/librustc_data_structures/unify/mod.rs @@ -344,7 +344,7 @@ impl<'tcx, K, V> UnificationTable } pub fn probe(&mut self, a_id: K) -> Option { - self.get(a_id).value.clone() + self.get(a_id).value } pub fn unsolved_variables(&mut self) -> Vec { From 4ccc0628afaebee3793a846682d2f6275d586f2c Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 19 Nov 2016 13:57:48 +0100 Subject: [PATCH 06/10] reference: fix duplicate bullet points in feature list --- src/doc/reference.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 0596e476d5f6c..4fbe518396760 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2474,18 +2474,19 @@ The currently implemented features of the reference compiler are: internally without imposing on callers (i.e. making them behave like function calls in terms of encapsulation). -* - `default_type_parameter_fallback` - Allows type parameter defaults to - influence type inference. -* - `stmt_expr_attributes` - Allows attributes on expressions. +* `default_type_parameter_fallback` - Allows type parameter defaults to + influence type inference. -* - `type_ascription` - Allows type ascription expressions `expr: Type`. +* `stmt_expr_attributes` - Allows attributes on expressions. -* - `abi_vectorcall` - Allows the usage of the vectorcall calling convention - (e.g. `extern "vectorcall" func fn_();`) +* `type_ascription` - Allows type ascription expressions `expr: Type`. -* - `abi_sysv64` - Allows the usage of the system V AMD64 calling convention - (e.g. `extern "sysv64" func fn_();`) +* `abi_vectorcall` - Allows the usage of the vectorcall calling convention + (e.g. `extern "vectorcall" func fn_();`) + +* `abi_sysv64` - Allows the usage of the system V AMD64 calling convention + (e.g. `extern "sysv64" func fn_();`) If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about `#![feature]` directives which enabled From 4dbc44fea1a5d5fc77ef716db4e086623542072c Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 19 Nov 2016 17:22:33 +0000 Subject: [PATCH 07/10] rustdoc: Remove unnecessary stability versions For some reason only on enum and macro pages, the stability version is rendered after the summary unlike all other pages. As it is already displayed at the top of the page for all items, this removes it for consistency and to prevent it from overlapping the summary text. --- src/librustdoc/html/render.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2761ab7660705..fd0fb9d05e737 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2439,7 +2439,6 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, "}}")?; } write!(w, "")?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it)?; if !e.variants.is_empty() { @@ -3055,7 +3054,6 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, Some("macro"), None, None))?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it) } From de2f61740d4622f3938cb6ddb01854c80c1e9082 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 19 Nov 2016 18:43:41 +0000 Subject: [PATCH 08/10] Optimise Chars::last() The default implementation of last() goes through the entire iterator but that's not needed here. --- src/libcollectionstest/str.rs | 8 ++++++++ src/libcore/str/mod.rs | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index cc56bbf4890aa..a13e1fb33d159 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -814,6 +814,14 @@ fn test_iterator_clone() { assert!(it.clone().zip(it).all(|(x,y)| x == y)); } +#[test] +fn test_iterator_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.chars(); + it.next(); + assert_eq!(it.last(), Some('m')); +} + #[test] fn test_bytesator() { let s = "ศไทย中华Việt Nam"; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 196750254af30..1dfd00e11aa96 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -432,6 +432,12 @@ impl<'a> Iterator for Chars<'a> { // `isize::MAX` (that's well below `usize::MAX`). ((len + 3) / 4, Some(len)) } + + #[inline] + fn last(mut self) -> Option { + // No need to go through the entire string. + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] From bf78ef3851b10001a5ec95f9c4aace6184348d6d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 19 Nov 2016 18:33:32 +0100 Subject: [PATCH 09/10] Add missing examples in SocketAddr --- src/libstd/net/addr.rs | 79 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 20dc5b3801ba4..1c016015b7928 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -31,7 +31,7 @@ pub enum SocketAddr { /// An IPv4 socket address which is a (ip, port) combination. #[stable(feature = "rust1", since = "1.0.0")] V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), - /// An IPv6 socket address + /// An IPv6 socket address. #[stable(feature = "rust1", since = "1.0.0")] V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6), } @@ -48,6 +48,16 @@ pub struct SocketAddrV6 { inner: c::sockaddr_in6 } impl SocketAddr { /// Creates a new socket address from the (ip, port) pair. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// assert_eq!(socket.port(), 8080); + /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] pub fn new(ip: IpAddr, port: u16) -> SocketAddr { match ip { @@ -57,6 +67,15 @@ impl SocketAddr { } /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] pub fn ip(&self) -> IpAddr { match *self { @@ -66,6 +85,16 @@ impl SocketAddr { } /// Change the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_ip(&mut self, new_ip: IpAddr) { // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. @@ -77,6 +106,15 @@ impl SocketAddr { } /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.port(), 8080); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { match *self { @@ -86,6 +124,16 @@ impl SocketAddr { } /// Change the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_port(1025); + /// assert_eq!(socket.port(), 1025); + /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { match *self { @@ -96,6 +144,20 @@ impl SocketAddr { /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address, /// false if it's a valid IPv6 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(sockaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// fn main() { + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), true); + /// assert_eq!(socket.is_ipv6(), false); + /// } + /// ``` #[unstable(feature = "sockaddr_checker", issue = "36949")] pub fn is_ipv4(&self) -> bool { match *self { @@ -106,6 +168,21 @@ impl SocketAddr { /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address, /// false if it's a valid IPv4 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(sockaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; + /// + /// fn main() { + /// let socket = SocketAddr::new( + /// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), false); + /// assert_eq!(socket.is_ipv6(), true); + /// } + /// ``` #[unstable(feature = "sockaddr_checker", issue = "36949")] pub fn is_ipv6(&self) -> bool { match *self { From 9e86e18092174b43514816c4bdeeafe8b518553f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sun, 20 Nov 2016 00:37:48 +0000 Subject: [PATCH 10/10] Optimise CharIndices::last() The default implementation of last() goes through the entire iterator but that's not needed here. --- src/libcollectionstest/str.rs | 8 ++++++++ src/libcore/str/mod.rs | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index a13e1fb33d159..ebbfbefc21b66 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -919,6 +919,14 @@ fn test_char_indices_revator() { assert_eq!(pos, p.len()); } +#[test] +fn test_char_indices_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.char_indices(); + it.next(); + assert_eq!(it.last(), Some((27, 'm'))); +} + #[test] fn test_splitn_char_iterator() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 1dfd00e11aa96..1bd6188f4875a 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -511,6 +511,12 @@ impl<'a> Iterator for CharIndices<'a> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<(usize, char)> { + // No need to go through the entire string. + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")]