Auto merge of #127728 - matthiaskrgr:rollup-ercdbjd, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #127273 (Fix `DebugParser`.) - #127587 (Report usage of lib features in ast validation) - #127592 (doc: Suggest `str::repeat` over `iter::repeat().take().collect()`) - #127630 (Remove lang feature for type ascription (since it's a lib feature now)) - #127711 (Add regression test for a gce + effects ICE) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f8e4ac0760
@ -607,8 +607,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
|||||||
// does not check the same for lib features unless there's at least one
|
// does not check the same for lib features unless there's at least one
|
||||||
// declared lang feature
|
// declared lang feature
|
||||||
if !sess.opts.unstable_features.is_nightly_build() {
|
if !sess.opts.unstable_features.is_nightly_build() {
|
||||||
let lang_features = &features.declared_lang_features;
|
if features.declared_features.is_empty() {
|
||||||
if lang_features.len() == 0 {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
|
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
|
||||||
@ -624,7 +623,8 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
|
|||||||
attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident())
|
attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident())
|
||||||
{
|
{
|
||||||
let name = ident.name;
|
let name = ident.name;
|
||||||
let stable_since = lang_features
|
let stable_since = features
|
||||||
|
.declared_lang_features
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
|
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
|
||||||
.next();
|
.next();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#![feature(
|
#![feature(
|
||||||
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
|
no_core, lang_items, intrinsics, unboxed_closures, extern_types,
|
||||||
decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
|
decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
|
||||||
thread_local
|
thread_local
|
||||||
)]
|
)]
|
||||||
|
@ -621,8 +621,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
|||||||
(unstable, try_blocks, "1.29.0", Some(31436)),
|
(unstable, try_blocks, "1.29.0", Some(31436)),
|
||||||
/// Allows `impl Trait` to be used inside type aliases (RFC 2515).
|
/// Allows `impl Trait` to be used inside type aliases (RFC 2515).
|
||||||
(unstable, type_alias_impl_trait, "1.38.0", Some(63063)),
|
(unstable, type_alias_impl_trait, "1.38.0", Some(63063)),
|
||||||
/// Allows the use of type ascription in expressions.
|
|
||||||
(unstable, type_ascription, "1.6.0", Some(23416)),
|
|
||||||
/// Allows creation of instances of a struct by moving fields that have
|
/// Allows creation of instances of a struct by moving fields that have
|
||||||
/// not changed from prior instances of the same struct (RFC #2528)
|
/// not changed from prior instances of the same struct (RFC #2528)
|
||||||
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
||||||
|
@ -1537,14 +1537,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
|
|
||||||
// we don't need N spans, but we want at least one, so print all of prev_token
|
// we don't need N spans, but we want at least one, so print all of prev_token
|
||||||
dbg_fmt.field("prev_token", &parser.prev_token);
|
dbg_fmt.field("prev_token", &parser.prev_token);
|
||||||
// make it easier to peek farther ahead by taking TokenKinds only until EOF
|
let mut tokens = vec![];
|
||||||
let tokens = (0..*lookahead)
|
for i in 0..*lookahead {
|
||||||
.map(|i| parser.look_ahead(i, |tok| tok.kind.clone()))
|
let tok = parser.look_ahead(i, |tok| tok.kind.clone());
|
||||||
.scan(parser.prev_token == TokenKind::Eof, |eof, tok| {
|
let is_eof = tok == TokenKind::Eof;
|
||||||
let current = eof.then_some(tok.clone()); // include a trailing EOF token
|
tokens.push(tok);
|
||||||
*eof |= &tok == &TokenKind::Eof;
|
if is_eof {
|
||||||
current
|
// Don't look ahead past EOF.
|
||||||
});
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
|
dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
|
||||||
dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls);
|
dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls);
|
||||||
|
|
||||||
|
@ -1376,12 +1376,13 @@ fn parse_expr_from_source_str(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses a macro rather than a function so that failure messages mention the
|
#[track_caller]
|
||||||
// correct line in the test function.
|
fn look(p: &Parser<'_>, dist: usize, kind: rustc_ast::token::TokenKind) {
|
||||||
macro_rules! look {
|
// Do the `assert_eq` outside the closure so that `track_caller` works.
|
||||||
($p:ident, $dist:literal, $kind:expr) => {
|
// (`#![feature(closure_track_caller)]` + `#[track_caller]` on the closure
|
||||||
$p.look_ahead($dist, |tok| assert_eq!($kind, tok.kind));
|
// doesn't give the line number in the test below if the assertion fails.)
|
||||||
};
|
let tok = p.look_ahead(dist, |tok| tok.clone());
|
||||||
|
assert_eq!(kind, tok.kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1397,63 +1398,63 @@ fn look_ahead() {
|
|||||||
let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string());
|
let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string());
|
||||||
|
|
||||||
// Current position is the `fn`.
|
// Current position is the `fn`.
|
||||||
look!(p, 0, token::Ident(kw::Fn, raw_no));
|
look(&p, 0, token::Ident(kw::Fn, raw_no));
|
||||||
look!(p, 1, token::Ident(sym_f, raw_no));
|
look(&p, 1, token::Ident(sym_f, raw_no));
|
||||||
look!(p, 2, token::OpenDelim(Delimiter::Parenthesis));
|
look(&p, 2, token::OpenDelim(Delimiter::Parenthesis));
|
||||||
look!(p, 3, token::Ident(sym_x, raw_no));
|
look(&p, 3, token::Ident(sym_x, raw_no));
|
||||||
look!(p, 4, token::Colon);
|
look(&p, 4, token::Colon);
|
||||||
look!(p, 5, token::Ident(sym::u32, raw_no));
|
look(&p, 5, token::Ident(sym::u32, raw_no));
|
||||||
look!(p, 6, token::CloseDelim(Delimiter::Parenthesis));
|
look(&p, 6, token::CloseDelim(Delimiter::Parenthesis));
|
||||||
look!(p, 7, token::OpenDelim(Delimiter::Brace));
|
look(&p, 7, token::OpenDelim(Delimiter::Brace));
|
||||||
look!(p, 8, token::Ident(sym_x, raw_no));
|
look(&p, 8, token::Ident(sym_x, raw_no));
|
||||||
look!(p, 9, token::CloseDelim(Delimiter::Brace));
|
look(&p, 9, token::CloseDelim(Delimiter::Brace));
|
||||||
look!(p, 10, token::Ident(kw::Struct, raw_no));
|
look(&p, 10, token::Ident(kw::Struct, raw_no));
|
||||||
look!(p, 11, token::Ident(sym_S, raw_no));
|
look(&p, 11, token::Ident(sym_S, raw_no));
|
||||||
look!(p, 12, token::Semi);
|
look(&p, 12, token::Semi);
|
||||||
// Any lookahead past the end of the token stream returns `Eof`.
|
// Any lookahead past the end of the token stream returns `Eof`.
|
||||||
look!(p, 13, token::Eof);
|
look(&p, 13, token::Eof);
|
||||||
look!(p, 14, token::Eof);
|
look(&p, 14, token::Eof);
|
||||||
look!(p, 15, token::Eof);
|
look(&p, 15, token::Eof);
|
||||||
look!(p, 100, token::Eof);
|
look(&p, 100, token::Eof);
|
||||||
|
|
||||||
// Move forward to the first `x`.
|
// Move forward to the first `x`.
|
||||||
for _ in 0..3 {
|
for _ in 0..3 {
|
||||||
p.bump();
|
p.bump();
|
||||||
}
|
}
|
||||||
look!(p, 0, token::Ident(sym_x, raw_no));
|
look(&p, 0, token::Ident(sym_x, raw_no));
|
||||||
look!(p, 1, token::Colon);
|
look(&p, 1, token::Colon);
|
||||||
look!(p, 2, token::Ident(sym::u32, raw_no));
|
look(&p, 2, token::Ident(sym::u32, raw_no));
|
||||||
look!(p, 3, token::CloseDelim(Delimiter::Parenthesis));
|
look(&p, 3, token::CloseDelim(Delimiter::Parenthesis));
|
||||||
look!(p, 4, token::OpenDelim(Delimiter::Brace));
|
look(&p, 4, token::OpenDelim(Delimiter::Brace));
|
||||||
look!(p, 5, token::Ident(sym_x, raw_no));
|
look(&p, 5, token::Ident(sym_x, raw_no));
|
||||||
look!(p, 6, token::CloseDelim(Delimiter::Brace));
|
look(&p, 6, token::CloseDelim(Delimiter::Brace));
|
||||||
look!(p, 7, token::Ident(kw::Struct, raw_no));
|
look(&p, 7, token::Ident(kw::Struct, raw_no));
|
||||||
look!(p, 8, token::Ident(sym_S, raw_no));
|
look(&p, 8, token::Ident(sym_S, raw_no));
|
||||||
look!(p, 9, token::Semi);
|
look(&p, 9, token::Semi);
|
||||||
look!(p, 10, token::Eof);
|
look(&p, 10, token::Eof);
|
||||||
look!(p, 11, token::Eof);
|
look(&p, 11, token::Eof);
|
||||||
look!(p, 100, token::Eof);
|
look(&p, 100, token::Eof);
|
||||||
|
|
||||||
// Move forward to the `;`.
|
// Move forward to the `;`.
|
||||||
for _ in 0..9 {
|
for _ in 0..9 {
|
||||||
p.bump();
|
p.bump();
|
||||||
}
|
}
|
||||||
look!(p, 0, token::Semi);
|
look(&p, 0, token::Semi);
|
||||||
// Any lookahead past the end of the token stream returns `Eof`.
|
// Any lookahead past the end of the token stream returns `Eof`.
|
||||||
look!(p, 1, token::Eof);
|
look(&p, 1, token::Eof);
|
||||||
look!(p, 100, token::Eof);
|
look(&p, 100, token::Eof);
|
||||||
|
|
||||||
// Move one past the `;`, i.e. past the end of the token stream.
|
// Move one past the `;`, i.e. past the end of the token stream.
|
||||||
p.bump();
|
p.bump();
|
||||||
look!(p, 0, token::Eof);
|
look(&p, 0, token::Eof);
|
||||||
look!(p, 1, token::Eof);
|
look(&p, 1, token::Eof);
|
||||||
look!(p, 100, token::Eof);
|
look(&p, 100, token::Eof);
|
||||||
|
|
||||||
// Bumping after Eof is idempotent.
|
// Bumping after Eof is idempotent.
|
||||||
p.bump();
|
p.bump();
|
||||||
look!(p, 0, token::Eof);
|
look(&p, 0, token::Eof);
|
||||||
look!(p, 1, token::Eof);
|
look(&p, 1, token::Eof);
|
||||||
look!(p, 100, token::Eof);
|
look(&p, 100, token::Eof);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1476,24 +1477,261 @@ fn look_ahead_non_outermost_stream() {
|
|||||||
for _ in 0..3 {
|
for _ in 0..3 {
|
||||||
p.bump();
|
p.bump();
|
||||||
}
|
}
|
||||||
look!(p, 0, token::Ident(kw::Fn, raw_no));
|
look(&p, 0, token::Ident(kw::Fn, raw_no));
|
||||||
look!(p, 1, token::Ident(sym_f, raw_no));
|
look(&p, 1, token::Ident(sym_f, raw_no));
|
||||||
look!(p, 2, token::OpenDelim(Delimiter::Parenthesis));
|
look(&p, 2, token::OpenDelim(Delimiter::Parenthesis));
|
||||||
look!(p, 3, token::Ident(sym_x, raw_no));
|
look(&p, 3, token::Ident(sym_x, raw_no));
|
||||||
look!(p, 4, token::Colon);
|
look(&p, 4, token::Colon);
|
||||||
look!(p, 5, token::Ident(sym::u32, raw_no));
|
look(&p, 5, token::Ident(sym::u32, raw_no));
|
||||||
look!(p, 6, token::CloseDelim(Delimiter::Parenthesis));
|
look(&p, 6, token::CloseDelim(Delimiter::Parenthesis));
|
||||||
look!(p, 7, token::OpenDelim(Delimiter::Brace));
|
look(&p, 7, token::OpenDelim(Delimiter::Brace));
|
||||||
look!(p, 8, token::Ident(sym_x, raw_no));
|
look(&p, 8, token::Ident(sym_x, raw_no));
|
||||||
look!(p, 9, token::CloseDelim(Delimiter::Brace));
|
look(&p, 9, token::CloseDelim(Delimiter::Brace));
|
||||||
look!(p, 10, token::Ident(kw::Struct, raw_no));
|
look(&p, 10, token::Ident(kw::Struct, raw_no));
|
||||||
look!(p, 11, token::Ident(sym_S, raw_no));
|
look(&p, 11, token::Ident(sym_S, raw_no));
|
||||||
look!(p, 12, token::Semi);
|
look(&p, 12, token::Semi);
|
||||||
look!(p, 13, token::CloseDelim(Delimiter::Brace));
|
look(&p, 13, token::CloseDelim(Delimiter::Brace));
|
||||||
// Any lookahead past the end of the token stream returns `Eof`.
|
// Any lookahead past the end of the token stream returns `Eof`.
|
||||||
look!(p, 14, token::Eof);
|
look(&p, 14, token::Eof);
|
||||||
look!(p, 15, token::Eof);
|
look(&p, 15, token::Eof);
|
||||||
look!(p, 100, token::Eof);
|
look(&p, 100, token::Eof);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(nnethercote) All the output is currently wrong.
|
||||||
|
#[test]
|
||||||
|
fn debug_lookahead() {
|
||||||
|
create_default_session_globals_then(|| {
|
||||||
|
let psess = psess();
|
||||||
|
let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string());
|
||||||
|
|
||||||
|
// Current position is the `fn`.
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:#?}", p.debug_lookahead(0)),
|
||||||
|
"Parser {
|
||||||
|
prev_token: Token {
|
||||||
|
kind: Question,
|
||||||
|
span: Span {
|
||||||
|
lo: BytePos(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
hi: BytePos(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
ctxt: #0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: [],
|
||||||
|
approx_token_stream_pos: 1,
|
||||||
|
..
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:#?}", p.debug_lookahead(7)),
|
||||||
|
"Parser {
|
||||||
|
prev_token: Token {
|
||||||
|
kind: Question,
|
||||||
|
span: Span {
|
||||||
|
lo: BytePos(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
hi: BytePos(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
ctxt: #0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: [
|
||||||
|
Ident(
|
||||||
|
\"fn\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"f\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
OpenDelim(
|
||||||
|
Parenthesis,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"x\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
Colon,
|
||||||
|
Ident(
|
||||||
|
\"u32\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
CloseDelim(
|
||||||
|
Parenthesis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
approx_token_stream_pos: 1,
|
||||||
|
..
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
// There are 13 tokens. We request 15, get 14; the last one is `Eof`.
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:#?}", p.debug_lookahead(15)),
|
||||||
|
"Parser {
|
||||||
|
prev_token: Token {
|
||||||
|
kind: Question,
|
||||||
|
span: Span {
|
||||||
|
lo: BytePos(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
hi: BytePos(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
ctxt: #0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: [
|
||||||
|
Ident(
|
||||||
|
\"fn\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"f\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
OpenDelim(
|
||||||
|
Parenthesis,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"x\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
Colon,
|
||||||
|
Ident(
|
||||||
|
\"u32\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
CloseDelim(
|
||||||
|
Parenthesis,
|
||||||
|
),
|
||||||
|
OpenDelim(
|
||||||
|
Brace,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"x\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
CloseDelim(
|
||||||
|
Brace,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"struct\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"S\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
Semi,
|
||||||
|
Eof,
|
||||||
|
],
|
||||||
|
approx_token_stream_pos: 1,
|
||||||
|
..
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Move forward to the second `x`.
|
||||||
|
for _ in 0..8 {
|
||||||
|
p.bump();
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:#?}", p.debug_lookahead(1)),
|
||||||
|
"Parser {
|
||||||
|
prev_token: Token {
|
||||||
|
kind: OpenDelim(
|
||||||
|
Brace,
|
||||||
|
),
|
||||||
|
span: Span {
|
||||||
|
lo: BytePos(
|
||||||
|
13,
|
||||||
|
),
|
||||||
|
hi: BytePos(
|
||||||
|
14,
|
||||||
|
),
|
||||||
|
ctxt: #0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: [
|
||||||
|
Ident(
|
||||||
|
\"x\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
approx_token_stream_pos: 9,
|
||||||
|
..
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:#?}", p.debug_lookahead(4)),
|
||||||
|
"Parser {
|
||||||
|
prev_token: Token {
|
||||||
|
kind: OpenDelim(
|
||||||
|
Brace,
|
||||||
|
),
|
||||||
|
span: Span {
|
||||||
|
lo: BytePos(
|
||||||
|
13,
|
||||||
|
),
|
||||||
|
hi: BytePos(
|
||||||
|
14,
|
||||||
|
),
|
||||||
|
ctxt: #0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: [
|
||||||
|
Ident(
|
||||||
|
\"x\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
CloseDelim(
|
||||||
|
Brace,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"struct\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
Ident(
|
||||||
|
\"S\",
|
||||||
|
No,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
approx_token_stream_pos: 9,
|
||||||
|
..
|
||||||
|
}"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Move two past the final token (the `;`).
|
||||||
|
for _ in 0..6 {
|
||||||
|
p.bump();
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:#?}", p.debug_lookahead(3)),
|
||||||
|
"Parser {
|
||||||
|
prev_token: Token {
|
||||||
|
kind: Eof,
|
||||||
|
span: Span {
|
||||||
|
lo: BytePos(
|
||||||
|
27,
|
||||||
|
),
|
||||||
|
hi: BytePos(
|
||||||
|
28,
|
||||||
|
),
|
||||||
|
ctxt: #0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tokens: [
|
||||||
|
Eof,
|
||||||
|
],
|
||||||
|
approx_token_stream_pos: 15,
|
||||||
|
..
|
||||||
|
}"
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,9 +290,6 @@ passes_export_name =
|
|||||||
passes_extern_main =
|
passes_extern_main =
|
||||||
the `main` function cannot be declared in an `extern` block
|
the `main` function cannot be declared in an `extern` block
|
||||||
|
|
||||||
passes_feature_only_on_nightly =
|
|
||||||
`#![feature]` may not be used on the {$release_channel} release channel
|
|
||||||
|
|
||||||
passes_feature_previously_declared =
|
passes_feature_previously_declared =
|
||||||
feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
|
feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
|
||||||
|
|
||||||
|
@ -1492,14 +1492,6 @@ pub struct TraitImplConstStable {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(passes_feature_only_on_nightly, code = E0554)]
|
|
||||||
pub struct FeatureOnlyOnNightly {
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Span,
|
|
||||||
pub release_channel: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_unknown_feature, code = E0635)]
|
#[diag(passes_unknown_feature, code = E0635)]
|
||||||
pub struct UnknownFeature {
|
pub struct UnknownFeature {
|
||||||
|
@ -936,12 +936,6 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||||||
let declared_lib_features = &tcx.features().declared_lib_features;
|
let declared_lib_features = &tcx.features().declared_lib_features;
|
||||||
let mut remaining_lib_features = FxIndexMap::default();
|
let mut remaining_lib_features = FxIndexMap::default();
|
||||||
for (feature, span) in declared_lib_features {
|
for (feature, span) in declared_lib_features {
|
||||||
if !tcx.sess.opts.unstable_features.is_nightly_build() {
|
|
||||||
tcx.dcx().emit_err(errors::FeatureOnlyOnNightly {
|
|
||||||
span: *span,
|
|
||||||
release_channel: env!("CFG_RELEASE_CHANNEL"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if remaining_lib_features.contains_key(&feature) {
|
if remaining_lib_features.contains_key(&feature) {
|
||||||
// Warn if the user enables a lib feature multiple times.
|
// Warn if the user enables a lib feature multiple times.
|
||||||
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
|
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
|
||||||
|
@ -8,11 +8,15 @@
|
|||||||
/// Infinite iterators like `repeat()` are often used with adapters like
|
/// Infinite iterators like `repeat()` are often used with adapters like
|
||||||
/// [`Iterator::take()`], in order to make them finite.
|
/// [`Iterator::take()`], in order to make them finite.
|
||||||
///
|
///
|
||||||
|
/// Use [`str::repeat()`] instead of this function if you just want to repeat
|
||||||
|
/// a char/string `n`th times.
|
||||||
|
///
|
||||||
/// If the element type of the iterator you need does not implement `Clone`,
|
/// If the element type of the iterator you need does not implement `Clone`,
|
||||||
/// or if you do not want to keep the repeated element in memory, you can
|
/// or if you do not want to keep the repeated element in memory, you can
|
||||||
/// instead use the [`repeat_with()`] function.
|
/// instead use the [`repeat_with()`] function.
|
||||||
///
|
///
|
||||||
/// [`repeat_with()`]: crate::iter::repeat_with
|
/// [`repeat_with()`]: crate::iter::repeat_with
|
||||||
|
/// [`str::repeat()`]: ../../std/primitive.str.html#method.repeat
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
//~^ WARN: the feature `generic_const_exprs` is incomplete
|
||||||
|
|
||||||
|
// Regression test for #125770 which would ICE under the old effects desugaring that
|
||||||
|
// created a const generic parameter for constness on `Add`.
|
||||||
|
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
pub struct Dimension;
|
||||||
|
|
||||||
|
pub struct Quantity<S, const D: Dimension>(S);
|
||||||
|
//~^ ERROR: `Dimension` is forbidden as the type of a const generic parameter
|
||||||
|
|
||||||
|
impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {}
|
||||||
|
//~^ ERROR: trait takes at most 1 generic argument
|
||||||
|
//~| ERROR: `Dimension` is forbidden as the type of a const generic parameter
|
||||||
|
|
||||||
|
pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> {
|
||||||
|
//~^ ERROR: `Dimension` is forbidden as the type of a const generic parameter
|
||||||
|
x + y
|
||||||
|
//~^ ERROR: cannot find value `y` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,64 @@
|
|||||||
|
error[E0425]: cannot find value `y` in this scope
|
||||||
|
--> $DIR/mismatched_generic_args.rs:20:9
|
||||||
|
|
|
||||||
|
LL | pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> {
|
||||||
|
| - similarly named const parameter `U` defined here
|
||||||
|
LL |
|
||||||
|
LL | x + y
|
||||||
|
| ^ help: a const parameter with a similar name exists: `U`
|
||||||
|
|
||||||
|
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/mismatched_generic_args.rs:1:12
|
||||||
|
|
|
||||||
|
LL | #![feature(generic_const_exprs)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error: `Dimension` is forbidden as the type of a const generic parameter
|
||||||
|
--> $DIR/mismatched_generic_args.rs:11:33
|
||||||
|
|
|
||||||
|
LL | pub struct Quantity<S, const D: Dimension>(S);
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: the only supported types are integers, `bool` and `char`
|
||||||
|
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
||||||
|
|
|
||||||
|
LL + #![feature(adt_const_params)]
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0107]: trait takes at most 1 generic argument but 2 generic arguments were supplied
|
||||||
|
--> $DIR/mismatched_generic_args.rs:14:36
|
||||||
|
|
|
||||||
|
LL | impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {}
|
||||||
|
| ^^^ expected at most 1 generic argument
|
||||||
|
|
||||||
|
error: `Dimension` is forbidden as the type of a const generic parameter
|
||||||
|
--> $DIR/mismatched_generic_args.rs:14:15
|
||||||
|
|
|
||||||
|
LL | impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {}
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: the only supported types are integers, `bool` and `char`
|
||||||
|
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
||||||
|
|
|
||||||
|
LL + #![feature(adt_const_params)]
|
||||||
|
|
|
||||||
|
|
||||||
|
error: `Dimension` is forbidden as the type of a const generic parameter
|
||||||
|
--> $DIR/mismatched_generic_args.rs:18:21
|
||||||
|
|
|
||||||
|
LL | pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> {
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: the only supported types are integers, `bool` and `char`
|
||||||
|
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
||||||
|
|
|
||||||
|
LL + #![feature(adt_const_params)]
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0107, E0425.
|
||||||
|
For more information about an error, try `rustc --explain E0107`.
|
Loading…
Reference in New Issue
Block a user