diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 94f21042c8f..a616409d9a4 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -187,7 +187,7 @@ This flag lets you control debug information: This flag lets you control the optimization level. -* `0`: no optimizations +* `0`: no optimizations, also turn on `cfg(debug_assertions)`. * `1`: basic optimizations * `2`: some optimizations * `3`: all optimizations diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md index 3a1cafe8a61..25a5c97b0a1 100644 --- a/src/doc/rustc/src/contributing.md +++ b/src/doc/rustc/src/contributing.md @@ -1,6 +1,12 @@ # Contributing to rustc We'd love to have your help improving `rustc`! To that end, we've written [a -whole book](https://rust-lang.github.io/rustc-guide/) on its +whole book][rustc_guide] on its internals, how it works, and how to get started working on it. To learn more, you'll want to check that out. + +If you would like to contribute to _this_ book, you can find its source in the +rustc source at [src/doc/rustc][rustc_book]. + +[rustc_guide]: https://rust-lang.github.io/rustc-guide/ +[rustc_book]: https://github.com/rust-lang/rust/tree/master/src/doc/rustc diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs index 4f55c68ecd4..6cfa36741d0 100644 --- a/src/libcore/ops/index.rs +++ b/src/libcore/ops/index.rs @@ -51,6 +51,21 @@ /// ``` #[lang = "index"] #[rustc_on_unimplemented( + on( + _Self="&str", + note="you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self="str", + note="you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self="std::string::String", + note="you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), message="the type `{Self}` cannot be indexed by `{Idx}`", label="`{Self}` cannot be indexed by `{Idx}`", )] @@ -141,6 +156,21 @@ pub trait Index { /// ``` #[lang = "index_mut"] #[rustc_on_unimplemented( + on( + _Self="&str", + note="you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self="str", + note="you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), + on( + _Self="std::string::String", + note="you can use `.chars().nth()` or `.bytes().nth()` +see chapter in The Book " + ), message="the type `{Self}` cannot be mutably indexed by `{Idx}`", label="`{Self}` cannot be mutably indexed by `{Idx}`", )] diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8badcbfc1b3..8cdc493e6fd 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3775,7 +3775,7 @@ impl<'a> LoweringContext<'a> { let ohs = P(self.lower_expr(ohs)); hir::ExprKind::Unary(op, ohs) } - ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((*l).clone())), + ExprKind::Lit(ref l) => hir::ExprKind::Lit((*l).clone()), ExprKind::Cast(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index fc4bd05476f..aaef1c722be 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -19,7 +19,7 @@ use syntax_pos::{Span, DUMMY_SP, symbol::InternedString}; use syntax::source_map::{self, Spanned}; use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect}; -use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy}; +use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::InlineAttr; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; @@ -142,17 +142,6 @@ pub const DUMMY_HIR_ID: HirId = HirId { pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; -#[derive(Clone, RustcEncodable, RustcDecodable, Copy)] -pub struct Label { - pub ident: Ident, -} - -impl fmt::Debug for Label { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "label({:?})", self.ident) - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Copy)] pub struct Lifetime { pub id: NodeId, @@ -1466,7 +1455,7 @@ pub enum ExprKind { /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, P), /// A literal (For example: `1`, `"foo"`) - Lit(P), + Lit(Lit), /// A cast (`foo as f64`) Cast(P, P), Type(P, P), diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 8ff60e5f562..f48059b328f 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -153,7 +153,7 @@ impl_stable_hash_for!(enum hir::LifetimeName { Error, }); -impl_stable_hash_for!(struct hir::Label { +impl_stable_hash_for!(struct ast::Label { ident }); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a78cf1a471b..2ca823929fd 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -911,17 +911,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn compute(&mut self, body: &hir::Expr) -> LiveNode { - // if there is a `break` or `again` at the top level, then it's - // effectively a return---this only occurs in `for` loops, - // where the body is really a closure. - debug!("compute: using id for body, {}", self.ir.tcx.hir().node_to_pretty_string(body.id)); - let exit_ln = self.s.exit_ln; - - self.break_ln.insert(body.id, exit_ln); - self.cont_ln.insert(body.id, exit_ln); - // the fallthrough exit is only for those cases where we do not // explicitly return: let s = self.s; @@ -1024,19 +1015,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&e, succ) } - hir::ExprKind::Closure(.., blk_id, _, _) => { + hir::ExprKind::Closure(..) => { debug!("{} is an ExprKind::Closure", self.ir.tcx.hir().node_to_pretty_string(expr.id)); - // The next-node for a break is the successor of the entire - // loop. The next-node for a continue is the top of this loop. - let node = self.live_node(expr.hir_id, expr.span); - - let break_ln = succ; - let cont_ln = node; - self.break_ln.insert(blk_id.node_id, break_ln); - self.cont_ln.insert(blk_id.node_id, cont_ln); - // the construction of a closure itself is not important, // but we have to consider the closed over variables. let caps = self.ir.capture_info_map.get(&expr.id).cloned().unwrap_or_else(|| @@ -1407,15 +1389,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { debug!("propagate_through_loop: using id for loop body {} {}", expr.id, self.ir.tcx.hir().node_to_pretty_string(body.id)); - let break_ln = succ; - let cont_ln = ln; - self.break_ln.insert(expr.id, break_ln); - self.cont_ln.insert(expr.id, cont_ln); + + self.break_ln.insert(expr.id, succ); let cond_ln = match kind { LoopLoop => ln, WhileLoop(ref cond) => self.propagate_through_expr(&cond, ln), }; + + self.cont_ln.insert(expr.id, cond_ln); + let body_ln = self.propagate_through_block(body, cond_ln); // repeat until fixed point is reached: diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a074441f8a1..3e25f98ccd2 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -135,10 +135,11 @@ impl CodeSuggestion { if let Some(line) = line_opt { if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) { let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi)); - buf.push_str(match hi_opt { - Some(hi) => &line[lo..hi], - None => &line[lo..], - }); + match hi_opt { + Some(hi) if hi > lo => buf.push_str(&line[lo..hi]), + Some(_) => (), + None => buf.push_str(&line[lo..]), + } } if let None = hi_opt { buf.push('\n'); diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index d35d64957b7..1f00086e32f 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -163,7 +163,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { !self.tcx.features().static_nobundle { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "static_nobundle", - span.unwrap(), + span.unwrap_or_else(|| syntax_pos::DUMMY_SP), GateIssue::Language, "kind=\"static-nobundle\" is feature gated"); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b4119372306..a58d63e1ca2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3318,7 +3318,12 @@ impl<'a> Resolver<'a> { if let Some(def) = def { match (def, source) { (Def::Macro(..), _) => { - err.span_label(span, format!("did you mean `{}!(...)`?", path_str)); + err.span_suggestion_with_applicability( + span, + "use `!` to invoke the macro", + format!("{}!", path_str), + Applicability::MaybeIncorrect, + ); return (err, candidates); } (Def::TyAlias(..), PathSource::Trait(_)) => { @@ -3330,13 +3335,22 @@ impl<'a> Resolver<'a> { } (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { ExprKind::Field(_, ident) => { - err.span_label(parent.span, format!("did you mean `{}::{}`?", - path_str, ident)); + err.span_suggestion_with_applicability( + parent.span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, ident), + Applicability::MaybeIncorrect, + ); return (err, candidates); } ExprKind::MethodCall(ref segment, ..) => { - err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", - path_str, segment.ident)); + let span = parent.span.with_hi(segment.ident.span.hi()); + err.span_suggestion_with_applicability( + span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, segment.ident), + Applicability::MaybeIncorrect, + ); return (err, candidates); } _ => {} @@ -3387,6 +3401,29 @@ impl<'a> Resolver<'a> { Ok(ref snippet) if snippet == "{" => true, _ => false, }; + // In case this could be a struct literal that needs to be surrounded + // by parenthesis, find the appropriate span. + let mut i = 0; + let mut closing_brace = None; + loop { + sp = sm.next_point(sp); + match sm.span_to_snippet(sp) { + Ok(ref snippet) => { + if snippet == "}" { + let sp = span.to(sp); + if let Ok(snippet) = sm.span_to_snippet(sp) { + closing_brace = Some((sp, snippet)); + } + break; + } + } + _ => break, + } + i += 1; + if i > 100 { // The bigger the span the more likely we're + break; // incorrect. Bound it to 100 chars long. + } + } match source { PathSource::Expr(Some(parent)) => { match parent.node { @@ -3413,11 +3450,20 @@ impl<'a> Resolver<'a> { } }, PathSource::Expr(None) if followed_by_brace == true => { - err.span_label( - span, - format!("did you mean `({} {{ /* fields */ }})`?", - path_str), - ); + if let Some((sp, snippet)) = closing_brace { + err.span_suggestion_with_applicability( + sp, + "surround the struct literal with parenthesis", + format!("({})", snippet), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label( + span, + format!("did you mean `({} {{ /* fields */ }})`?", + path_str), + ); + } return (err, candidates); }, _ => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 823c786bded..5b430d13516 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5234,22 +5234,13 @@ impl<'a> Parser<'a> { kind: ast::GenericParamKind::Lifetime, }); if let Some(sp) = seen_ty_param { - let param_span = self.prev_span; - let ate_comma = self.eat(&token::Comma); - let remove_sp = if ate_comma { - param_span.until(self.span) - } else { - last_comma_span.unwrap_or(param_span).to(param_span) - }; - bad_lifetime_pos.push(param_span); - - if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) { + let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span); + bad_lifetime_pos.push(self.prev_span); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) { suggestions.push((remove_sp, String::new())); - suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet))); - } - if ate_comma { - last_comma_span = Some(self.prev_span); - continue + suggestions.push(( + sp.shrink_to_lo(), + format!("{}, ", snippet))); } } } else if self.check_ident() { diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index c422a1e7957..d0deb8ce7ea 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -29,19 +29,25 @@ error[E0423]: expected value, found struct `S` --> $DIR/E0423.rs:12:32 | LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); } - | ^ did you mean `(S { /* fields */ })`? + | ^--------------- + | | + | help: surround the struct literal with parenthesis: `(S { x: 1, y: 2 })` error[E0423]: expected value, found struct `T` --> $DIR/E0423.rs:15:8 | LL | if T {} == T {} { println!("Ok"); } - | ^ did you mean `(T { /* fields */ })`? + | ^--- + | | + | help: surround the struct literal with parenthesis: `(T {})` error[E0423]: expected value, found struct `std::ops::Range` --> $DIR/E0423.rs:21:14 | LL | for _ in std::ops::Range { start: 0, end: 10 } {} - | ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`? + | ^^^^^^^^^^^^^^^---------------------- + | | + | help: surround the struct literal with parenthesis: `(std::ops::Range { start: 0, end: 10 })` error: aborting due to 7 previous errors diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs new file mode 100644 index 00000000000..92844f9306d --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs @@ -0,0 +1,6 @@ +//~ ERROR kind="static-nobundle" is feature gated +// Test the behavior of rustc when non-existent library is statically linked + +// compile-flags: -l static-nobundle=nonexistent + +fn main() {} diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr new file mode 100644 index 00000000000..419c21901a0 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr @@ -0,0 +1,7 @@ +error[E0658]: kind="static-nobundle" is feature gated (see issue #37403) + | + = help: add #![feature(static_nobundle)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issue-53787-inline-assembler-macro.rs b/src/test/ui/issue-53787-inline-assembler-macro.rs new file mode 100644 index 00000000000..937bce1b655 --- /dev/null +++ b/src/test/ui/issue-53787-inline-assembler-macro.rs @@ -0,0 +1,23 @@ +// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros. + +#![feature(asm)] + +macro_rules! fake_jump { + ($id:expr) => { + unsafe { + asm!( + " + jmp $0 + lea eax, [ebx] + xor eax, 0xDEADBEEF + retn + $0: + "::"0"($id)::"volatile", "intel"); + } + }; +} + +fn main() { + fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly + println!("Hello, world!"); +} diff --git a/src/test/ui/issue-53787-inline-assembler-macro.stderr b/src/test/ui/issue-53787-inline-assembler-macro.stderr new file mode 100644 index 00000000000..69f380bdc9c --- /dev/null +++ b/src/test/ui/issue-53787-inline-assembler-macro.stderr @@ -0,0 +1,9 @@ +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/issue-53787-inline-assembler-macro.rs:21:16 + | +LL | fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0669`. diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs new file mode 100644 index 00000000000..9b905d4883a --- /dev/null +++ b/src/test/ui/lifetime-before-type-params.rs @@ -0,0 +1,9 @@ +#![allow(unused)] +fn first() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn second<'a, T, 'b>() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn third() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn fourth<'a, T, 'b, U, 'c, V>() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr new file mode 100644 index 00000000000..7ac8dffdfbe --- /dev/null +++ b/src/test/ui/lifetime-before-type-params.stderr @@ -0,0 +1,47 @@ +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:2:13 + | +LL | fn first() {} + | ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn first<'a, 'b, T>() {} + | ^^^ ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:4:18 + | +LL | fn second<'a, T, 'b>() {} + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn second<'a, 'b, T>() {} + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:6:16 + | +LL | fn third() {} + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn third<'a, T, U>() {} + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:8:18 + | +LL | fn fourth<'a, T, 'b, U, 'c, V>() {} + | ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn fourth<'a, 'b, 'c, T, U, V>() {} + | ^^^ ^^^ -- -- + +error[E0601]: `main` function not found in crate `lifetime_before_type_params` + | + = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/liveness/liveness-dead.rs b/src/test/ui/liveness/liveness-dead.rs index 7d420afde4b..004663c85ee 100644 --- a/src/test/ui/liveness/liveness-dead.rs +++ b/src/test/ui/liveness/liveness-dead.rs @@ -27,4 +27,13 @@ fn f5(mut x: i32) { x = 4; //~ ERROR: value assigned to `x` is never read } +// #22630 +fn f6() { + let mut done = false; + while !done { + done = true; // no error + continue; + } +} + fn main() {} diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 4f6d0f695df..ebe3c36f21e 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -2,7 +2,7 @@ error[E0423]: expected function, found macro `assert` --> $DIR/resolve-hint-macro.rs:2:5 | LL | assert(true); - | ^^^^^^ did you mean `assert!(...)`? + | ^^^^^^ help: use `!` to invoke the macro: `assert!` error: aborting due to previous error diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index 8a9426bfee8..b7b158ce7ef 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -4,15 +4,15 @@ error[E0423]: expected value, found module `a` LL | a.I | ^-- | | - | did you mean `a::I`? + | help: use the path separator to refer to an item: `a::I` error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5 | LL | a.g() - | ^---- + | ^-- | | - | did you mean `a::g(...)`? + | help: use the path separator to refer to an item: `a::g` error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5 @@ -20,16 +20,21 @@ error[E0423]: expected value, found module `a` LL | a.b.J | ^-- | | - | did you mean `a::b`? + | help: use the path separator to refer to an item: `a::b` error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5 | LL | a::b.J - | ^^^--- - | | | - | | help: a constant with a similar name exists: `I` - | did you mean `a::b::J`? + | ^^^^ +help: a constant with a similar name exists + | +LL | a::I.J + | ^ +help: use the path separator to refer to an item + | +LL | a::b::J + | error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5 @@ -37,7 +42,7 @@ error[E0423]: expected value, found module `a` LL | a.b.f(); | ^-- | | - | did you mean `a::b`? + | help: use the path separator to refer to an item: `a::b` error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12 @@ -51,10 +56,15 @@ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5 | LL | a::b.f() - | ^^^----- - | | | - | | help: a constant with a similar name exists: `I` - | did you mean `a::b::f(...)`? + | ^^^^ +help: a constant with a similar name exists + | +LL | a::I.f() + | ^ +help: use the path separator to refer to an item + | +LL | a::b::f() + | ^^^^^^^ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5 diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index 108096df9c4..71b17474923 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -5,6 +5,8 @@ LL | let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integ | ^^^^ `str` cannot be indexed by `{integer}` | = help: the trait `std::ops::Index<{integer}>` is not implemented for `str` + = note: you can use `.chars().nth()` or `.bytes().nth()` + see chapter in The Book error: aborting due to previous error diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index a0c7c2c574e..a1212c5a4fe 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -29,6 +29,8 @@ LL | s[1usize] = bot(); | ^^^^^^^^^ `str` cannot be mutably indexed by `usize` | = help: the trait `std::ops::IndexMut` is not implemented for `str` + = note: you can use `.chars().nth()` or `.bytes().nth()` + see chapter in The Book error: aborting due to 3 previous errors diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr index 72a2cbe6bf6..b36e927b5c0 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -16,7 +16,7 @@ LL | struct B { //~ ERROR lifetime parameters must be declared help: move the lifetime parameter prior to the first type parameter | LL | struct B<'a, T, U> { //~ ERROR lifetime parameters must be declared - | ^^^ -- + | ^^^ -- error: lifetime parameters must be declared prior to type parameters --> $DIR/suggest-move-lifetimes.rs:10:16 @@ -36,7 +36,7 @@ LL | struct D { //~ ERROR lifetime parameters must be decla help: move the lifetime parameter prior to the first type parameter | LL | struct D<'a, 'b, 'c, T, U, V> { //~ ERROR lifetime parameters must be declared - | ^^^ ^^^ ^^^ --- + | ^^^ ^^^ ^^^ -- -- error: aborting due to 4 previous errors diff --git a/src/test/ui/thread-local-mutation.nll.stderr b/src/test/ui/thread-local-mutation.nll.stderr new file mode 100644 index 00000000000..0a3664b0d9d --- /dev/null +++ b/src/test/ui/thread-local-mutation.nll.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable static item `S` + --> $DIR/thread-local-mutation.rs:11:5 + | +LL | S = "after"; //~ ERROR cannot assign to immutable + | ^^^^^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/thread-local-mutation.rs b/src/test/ui/thread-local-mutation.rs new file mode 100644 index 00000000000..e738225ce2a --- /dev/null +++ b/src/test/ui/thread-local-mutation.rs @@ -0,0 +1,18 @@ +// Regression test for #54901: immutable thread locals could be mutated. See: +// https://github.com/rust-lang/rust/issues/29594#issuecomment-328177697 +// https://github.com/rust-lang/rust/issues/54901 + +#![feature(thread_local)] + +#[thread_local] +static S: &str = "before"; + +fn set_s() { + S = "after"; //~ ERROR cannot assign to immutable +} + +fn main() { + println!("{}", S); + set_s(); + println!("{}", S); +} diff --git a/src/test/ui/thread-local-mutation.stderr b/src/test/ui/thread-local-mutation.stderr new file mode 100644 index 00000000000..bf298523e1b --- /dev/null +++ b/src/test/ui/thread-local-mutation.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable thread-local static item + --> $DIR/thread-local-mutation.rs:11:5 + | +LL | S = "after"; //~ ERROR cannot assign to immutable + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index 63650086bca..a7b81060d3d 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -15,7 +15,7 @@ error[E0574]: expected struct, variant or union type, found macro `try` --> $DIR/try-block-in-edition2015.rs:4:33 | LL | let try_result: Option<_> = try { - | ^^^ did you mean `try!(...)`? + | ^^^ help: use `!` to invoke the macro: `try!` error: aborting due to 2 previous errors