Auto merge of #57747 - Centril:rollup, r=Centril
Rollup of 11 pull requests Successful merges: - #57107 (Add a regression test for mutating a non-mut #[thread_local]) - #57132 (Document that `-C opt-level=0` implies `-C debug-assertions`.) - #57212 (docs(rustc): Link to the book's source in rustc) - #57302 (Fix unused_assignments false positive) - #57350 (Better error note on unimplemented Index trait for string) - #57635 (use structured macro and path resolve suggestions) - #57650 (librustc_metadata: Pass a default value when unwrapping a span) - #57657 (Add regression test to close #53787) - #57658 (Two HIR tweaks) - #57720 (Fix suggestions given mulitple bad lifetimes) - #57725 (Use structured suggestion to surround struct literal with parenthesis) Failed merges: r? @ghost
This commit is contained in:
commit
f001287c90
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
|
||||
),
|
||||
on(
|
||||
_Self="str",
|
||||
note="you can use `.chars().nth()` or `.bytes().nth()`
|
||||
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
|
||||
),
|
||||
on(
|
||||
_Self="std::string::String",
|
||||
note="you can use `.chars().nth()` or `.bytes().nth()`
|
||||
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
|
||||
),
|
||||
message="the type `{Self}` cannot be indexed by `{Idx}`",
|
||||
label="`{Self}` cannot be indexed by `{Idx}`",
|
||||
)]
|
||||
@ -141,6 +156,21 @@ pub trait Index<Idx: ?Sized> {
|
||||
/// ```
|
||||
#[lang = "index_mut"]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
_Self="&str",
|
||||
note="you can use `.chars().nth()` or `.bytes().nth()`
|
||||
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
|
||||
),
|
||||
on(
|
||||
_Self="str",
|
||||
note="you can use `.chars().nth()` or `.bytes().nth()`
|
||||
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
|
||||
),
|
||||
on(
|
||||
_Self="std::string::String",
|
||||
note="you can use `.chars().nth()` or `.bytes().nth()`
|
||||
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
|
||||
),
|
||||
message="the type `{Self}` cannot be mutably indexed by `{Idx}`",
|
||||
label="`{Self}` cannot be mutably indexed by `{Idx}`",
|
||||
)]
|
||||
|
@ -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()))
|
||||
|
@ -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<Expr>),
|
||||
/// A literal (For example: `1`, `"foo"`)
|
||||
Lit(P<Lit>),
|
||||
Lit(Lit),
|
||||
/// A cast (`foo as f64`)
|
||||
Cast(P<Expr>, P<Ty>),
|
||||
Type(P<Expr>, P<Ty>),
|
||||
|
@ -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
|
||||
});
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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');
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
},
|
||||
_ => {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
@ -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`.
|
23
src/test/ui/issue-53787-inline-assembler-macro.rs
Normal file
23
src/test/ui/issue-53787-inline-assembler-macro.rs
Normal file
@ -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!");
|
||||
}
|
9
src/test/ui/issue-53787-inline-assembler-macro.stderr
Normal file
9
src/test/ui/issue-53787-inline-assembler-macro.stderr
Normal file
@ -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`.
|
9
src/test/ui/lifetime-before-type-params.rs
Normal file
9
src/test/ui/lifetime-before-type-params.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![allow(unused)]
|
||||
fn first<T, 'a, 'b>() {}
|
||||
//~^ 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<T, U, 'a>() {}
|
||||
//~^ 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
|
47
src/test/ui/lifetime-before-type-params.stderr
Normal file
47
src/test/ui/lifetime-before-type-params.stderr
Normal file
@ -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<T, 'a, 'b>() {}
|
||||
| ^^ ^^
|
||||
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<T, U, 'a>() {}
|
||||
| ^^
|
||||
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`.
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -29,6 +29,8 @@ LL | s[1usize] = bot();
|
||||
| ^^^^^^^^^ `str` cannot be mutably indexed by `usize`
|
||||
|
|
||||
= help: the trait `std::ops::IndexMut<usize>` is not implemented for `str`
|
||||
= note: you can use `.chars().nth()` or `.bytes().nth()`
|
||||
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -16,7 +16,7 @@ LL | struct B<T, 'a, U> { //~ 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<T, U, 'a, 'b, V, 'c> { //~ 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
|
||||
|
||||
|
9
src/test/ui/thread-local-mutation.nll.stderr
Normal file
9
src/test/ui/thread-local-mutation.nll.stderr
Normal file
@ -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`.
|
18
src/test/ui/thread-local-mutation.rs
Normal file
18
src/test/ui/thread-local-mutation.rs
Normal file
@ -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);
|
||||
}
|
9
src/test/ui/thread-local-mutation.stderr
Normal file
9
src/test/ui/thread-local-mutation.stderr
Normal file
@ -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`.
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user