diff --git a/src/doc/book/crates-and-modules.md b/src/doc/book/crates-and-modules.md index 67fe8ba2c11..fcb7e0bc7ea 100644 --- a/src/doc/book/crates-and-modules.md +++ b/src/doc/book/crates-and-modules.md @@ -22,6 +22,7 @@ As an example, let’s make a *phrases* crate, which will give us various phrase in different languages. To keep things simple, we’ll stick to ‘greetings’ and ‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as two languages for those phrases to be in. We’ll use this module layout: + ```text +-----------+ +---| greetings | diff --git a/src/doc/book/patterns.md b/src/doc/book/patterns.md index a0245d4c7b1..910b1375476 100644 --- a/src/doc/book/patterns.md +++ b/src/doc/book/patterns.md @@ -109,14 +109,14 @@ struct Point { y: i32, } -let origin = Point { x: 0, y: 0 }; +let point = Point { x: 2, y: 3 }; -match origin { +match point { Point { x, .. } => println!("x is {}", x), } ``` -This prints `x is 0`. +This prints `x is 2`. You can do this kind of match on any member, not only the first: @@ -126,14 +126,14 @@ struct Point { y: i32, } -let origin = Point { x: 0, y: 0 }; +let point = Point { x: 2, y: 3 }; -match origin { +match point { Point { y, .. } => println!("y is {}", y), } ``` -This prints `y is 0`. +This prints `y is 3`. This ‘destructuring’ behavior works on any compound data type, like [tuples][tuples] or [enums][enums]. diff --git a/src/doc/reference.md b/src/doc/reference.md index f4ffe5774d2..f0ab1488d40 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3039,7 +3039,7 @@ The precedence of Rust binary operators is ordered as follows, going from strong to weak: ```{.text .precedence} -as +as : * / % + - << >> @@ -3050,6 +3050,7 @@ as && || .. ... +<- = ``` diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 599e3ec871a..366b58e06c4 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -316,7 +316,10 @@ fn check_arms(cx: &MatchCheckCtxt, let &(ref first_arm_pats, _) = &arms[0]; let first_pat = &first_arm_pats[0]; let span = first_pat.span; - span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern"); + struct_span_err!(cx.tcx.sess, span, E0162, + "irrefutable if-let pattern") + .span_label(span, &format!("irrefutable pattern")) + .emit(); printed_if_let_err = true; } }, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index b4e9fb5c65b..07595c5dbe1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -360,8 +360,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data) } hir::ParenthesizedParameters(..) => { - span_err!(tcx.sess, span, E0214, - "parenthesized parameters may only be used with a trait"); + struct_span_err!(tcx.sess, span, E0214, + "parenthesized parameters may only be used with a trait") + .span_label(span, &format!("only traits may use parentheses")) + .emit(); + let ty_param_defs = decl_generics.types.get_slice(TypeSpace); (Substs::empty(), ty_param_defs.iter().map(|_| tcx.types.err).collect(), @@ -1201,10 +1204,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } for (trait_def_id, name) in associated_types { - span_err!(tcx.sess, span, E0191, + struct_span_err!(tcx.sess, span, E0191, "the value of the associated type `{}` (from the trait `{}`) must be specified", name, - tcx.item_path_str(trait_def_id)); + tcx.item_path_str(trait_def_id)) + .span_label(span, &format!( + "missing associated type `{}` value", name)) + .emit(); } tcx.mk_trait(object.principal, object.bounds) @@ -1281,10 +1287,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } if bounds.len() > 1 { - let mut err = struct_span_err!(self.tcx().sess, span, E0221, - "ambiguous associated type `{}` in bounds of `{}`", - assoc_name, - ty_param_name); + let mut err = struct_span_err!( + self.tcx().sess, span, E0221, + "ambiguous associated type `{}` in bounds of `{}`", + assoc_name, + ty_param_name); + err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name)); for bound in &bounds { span_note!(&mut err, span, @@ -1584,9 +1592,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { return self.tcx().types.err; } _ => { - span_err!(tcx.sess, span, E0248, - "found value `{}` used as a type", - tcx.item_path_str(def.def_id())); + struct_span_err!(tcx.sess, span, E0248, + "found value `{}` used as a type", + tcx.item_path_str(def.def_id())) + .span_label(span, &format!("value used as a type")) + .emit(); return self.tcx().types.err; } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index fe68690d4e9..5f255cc1fb7 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -633,10 +633,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_pat(&subpat, field_ty); } } else { - span_err!(tcx.sess, pat.span, E0023, - "this pattern has {} field{s}, but the corresponding {} has {} field{s}", - subpats.len(), def.kind_name(), variant.fields.len(), - s = if variant.fields.len() == 1 {""} else {"s"}); + let subpats_ending = if subpats.len() == 1 { + "" + } else { + "s" + }; + let fields_ending = if variant.fields.len() == 1 { + "" + } else { + "s" + }; + struct_span_err!(tcx.sess, pat.span, E0023, + "this pattern has {} field{}, but the corresponding {} has {} field{}", + subpats.len(), subpats_ending, def.kind_name(), + variant.fields.len(), fields_ending) + .span_label(pat.span, &format!("expected {} field{}, found {}", + variant.fields.len(), fields_ending, subpats.len())) + .emit(); on_error(); } } @@ -682,10 +695,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { field_map.get(&field.name) .map(|f| self.field_ty(span, f, substs)) .unwrap_or_else(|| { - span_err!(tcx.sess, span, E0026, - "struct `{}` does not have a field named `{}`", - tcx.item_path_str(variant.did), - field.name); + struct_span_err!(tcx.sess, span, E0026, + "struct `{}` does not have a field named `{}`", + tcx.item_path_str(variant.did), + field.name) + .span_label(span, + &format!("struct `{}` does not have field `{}`", + tcx.item_path_str(variant.did), + field.name)) + .emit(); + tcx.types.err }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4bb36aa639c..f11bb3175da 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4372,14 +4372,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if i < type_count { substs.types.push(space, t); } else if i == type_count { - span_err!(self.tcx.sess, typ.span, E0087, - "too many type parameters provided: \ - expected at most {} parameter{}, \ - found {} parameter{}", - type_count, - if type_count == 1 {""} else {"s"}, - data.types.len(), - if data.types.len() == 1 {""} else {"s"}); + struct_span_err!(self.tcx.sess, typ.span, E0087, + "too many type parameters provided: \ + expected at most {} parameter{}, \ + found {} parameter{}", + type_count, + if type_count == 1 {""} else {"s"}, + data.types.len(), + if data.types.len() == 1 {""} else {"s"}) + .span_label(typ.span , &format!("expected {} parameter{}", + type_count, + if type_count == 1 {""} else {"s"})).emit(); substs.types.truncate(space, 0); break; } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index cdf2ca14d4c..7a923cd29d0 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -321,13 +321,18 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } Err(CopyImplementationError::InfrigingVariant(name)) => { - struct_span_err!(tcx.sess, span, E0205, - "the trait `Copy` may not be \ - implemented for this type") - .span_label(span, &format!("variant \ - `{}` does not implement `Copy`", - name)) - .emit() + let item = tcx.map.expect_item(impl_node_id); + let span = if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node { + tr.path.span + } else { + span + }; + + struct_span_err!(tcx.sess, span, E0205, + "the trait `Copy` may not be implemented for this type") + .span_label(span, &format!("variant `{}` does not implement `Copy`", + name)) + .emit() } Err(CopyImplementationError::NotAnAdt) => { let item = tcx.map.expect_item(impl_node_id); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index eac26487ea3..5e733389e24 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -262,9 +262,10 @@ fn check_start_fn_ty(ccx: &CrateCtxt, match it.node { hir::ItemFn(_,_,_,_,ref ps,_) if ps.is_parameterized() => { - struct_span_err!(tcx.sess, start_span, E0132, + let sp = if let Some(sp) = ps.span() { sp } else { start_span }; + struct_span_err!(tcx.sess, sp, E0132, "start function is not allowed to have type parameters") - .span_label(ps.span().unwrap(), + .span_label(sp, &format!("start function cannot have type parameters")) .emit(); return; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index fd7b0a2e6bb..8039421ae77 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -199,13 +199,12 @@ fn test_resize_policy() { /// A hash map implementation which uses linear probing with Robin /// Hood bucket stealing. /// -/// The hashes are all keyed by the thread-local random number generator -/// on creation by default. This means that the ordering of the keys is -/// randomized, but makes the tables more resistant to -/// denial-of-service attacks (Hash DoS). No guarantees are made to the -/// quality of the random data. The implementation uses the best available -/// random data from your platform at the time of creation. This behavior -/// can be overridden with one of the constructors. +/// By default, HashMap uses a somewhat slow hashing algorithm which can provide resistance +/// to DoS attacks. Rust makes a best attempt at acquiring random numbers without IO +/// blocking from your system. Because of this HashMap is not guaranteed to provide +/// DoS resistance since the numbers generated might not be truly random. If you do +/// require this behavior you can create your own hashing function using +/// [BuildHasherDefault](../hash/struct.BuildHasherDefault.html). /// /// It is required that the keys implement the `Eq` and `Hash` traits, although /// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`. diff --git a/src/test/compile-fail/E0023.rs b/src/test/compile-fail/E0023.rs index 05f126baf9a..c3623e3177b 100644 --- a/src/test/compile-fail/E0023.rs +++ b/src/test/compile-fail/E0023.rs @@ -13,10 +13,15 @@ enum Fruit { Pear(u32), } + fn main() { let x = Fruit::Apple(String::new(), String::new()); match x { Fruit::Apple(a) => {}, //~ ERROR E0023 + //~| NOTE expected 2 fields, found 1 Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 + //~| NOTE expected 2 fields, found 3 + Fruit::Pear(1, 2) => {}, //~ ERROR E0023 + //~| NOTE expected 1 field, found 2 } } diff --git a/src/test/compile-fail/E0026.rs b/src/test/compile-fail/E0026.rs index 359c2a822a2..ac609da4cbd 100644 --- a/src/test/compile-fail/E0026.rs +++ b/src/test/compile-fail/E0026.rs @@ -16,6 +16,8 @@ struct Thing { fn main() { let thing = Thing { x: 0, y: 0 }; match thing { - Thing { x, y, z } => {} //~ ERROR E0026 + Thing { x, y, z } => {} + //~^ ERROR struct `Thing` does not have a field named `z` [E0026] + //~| NOTE struct `Thing` does not have field `z` } } diff --git a/src/test/compile-fail/E0087.rs b/src/test/compile-fail/E0087.rs index ec559fc8389..437ad3698a2 100644 --- a/src/test/compile-fail/E0087.rs +++ b/src/test/compile-fail/E0087.rs @@ -12,4 +12,5 @@ fn foo() {} fn main() { foo::(); //~ ERROR E0087 + //~^ NOTE expected } diff --git a/src/test/compile-fail/E0162.rs b/src/test/compile-fail/E0162.rs index e13b0af6f79..0b63d7c3f85 100644 --- a/src/test/compile-fail/E0162.rs +++ b/src/test/compile-fail/E0162.rs @@ -13,6 +13,7 @@ struct Irrefutable(i32); fn main() { let irr = Irrefutable(0); if let Irrefutable(x) = irr { //~ ERROR E0162 + //~| NOTE irrefutable pattern println!("{}", x); } } diff --git a/src/test/compile-fail/E0191.rs b/src/test/compile-fail/E0191.rs index 489ebb033f8..dcfe441ab0d 100644 --- a/src/test/compile-fail/E0191.rs +++ b/src/test/compile-fail/E0191.rs @@ -13,6 +13,7 @@ trait Trait { } type Foo = Trait; //~ ERROR E0191 + //~| NOTE missing associated type `Bar` value fn main() { } diff --git a/src/test/compile-fail/E0205.rs b/src/test/compile-fail/E0205.rs index 37ac57af524..c73e7534301 100644 --- a/src/test/compile-fail/E0205.rs +++ b/src/test/compile-fail/E0205.rs @@ -14,11 +14,11 @@ enum Foo { } impl Copy for Foo { } -//~^ ERROR E0205 +//~^ ERROR the trait `Copy` may not be implemented for this type //~| NOTE variant `Bar` does not implement `Copy` #[derive(Copy)] -//~^ ERROR E0205 +//~^ ERROR the trait `Copy` may not be implemented for this type //~| NOTE variant `Bar` does not implement `Copy` //~| NOTE in this expansion of #[derive(Copy)] enum Foo2<'a> { diff --git a/src/test/compile-fail/E0214.rs b/src/test/compile-fail/E0214.rs index 59609345ee5..e9c3cb72c11 100644 --- a/src/test/compile-fail/E0214.rs +++ b/src/test/compile-fail/E0214.rs @@ -9,5 +9,7 @@ // except according to those terms. fn main() { - let v: Vec(&str) = vec!["foo"]; //~ ERROR E0214 + let v: Vec(&str) = vec!["foo"]; + //~^ ERROR E0214 + //~| NOTE only traits may use parentheses } diff --git a/src/test/compile-fail/E0248.rs b/src/test/compile-fail/E0248.rs index fdfd41a456b..25568a323e1 100644 --- a/src/test/compile-fail/E0248.rs +++ b/src/test/compile-fail/E0248.rs @@ -13,6 +13,6 @@ enum Foo { } fn do_something(x: Foo::Bar) { } //~ ERROR E0248 - + //~| NOTE value used as a type fn main() { } diff --git a/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs b/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs index 2b34fcab24c..a2a11c62bb8 100644 --- a/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs +++ b/src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs @@ -28,6 +28,7 @@ pub trait BoxCar : Box + Vehicle { fn dent(c: C, color: C::Color) { //~^ ERROR ambiguous associated type `Color` in bounds of `C` + //~| NOTE ambiguous associated type `Color` //~| NOTE could derive from `Vehicle` //~| NOTE could derive from `Box` } @@ -35,12 +36,15 @@ fn dent(c: C, color: C::Color) { fn dent_object(c: BoxCar) { //~^ ERROR ambiguous associated type //~| ERROR the value of the associated type `Color` (from the trait `Vehicle`) must be specified + //~| NOTE ambiguous associated type `Color` //~| NOTE could derive from `Vehicle` //~| NOTE could derive from `Box` + //~| NOTE missing associated type `Color` value } fn paint(c: C, d: C::Color) { //~^ ERROR ambiguous associated type `Color` in bounds of `C` + //~| NOTE ambiguous associated type `Color` //~| NOTE could derive from `Vehicle` //~| NOTE could derive from `Box` } diff --git a/src/test/run-pass/issue-33498.rs b/src/test/run-pass/issue-33498.rs new file mode 100644 index 00000000000..9b4e1918bae --- /dev/null +++ b/src/test/run-pass/issue-33498.rs @@ -0,0 +1,19 @@ +// 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. + +pub fn main() { + let x = (0, 2); + + match x { + (0, ref y) => {} + (y, 0) => {} + _ => (), + } +}