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:
bors 2024-07-14 18:50:26 +00:00
commit f8e4ac0760
11 changed files with 406 additions and 93 deletions

View File

@ -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
// declared lang feature
if !sess.opts.unstable_features.is_nightly_build() {
let lang_features = &features.declared_lang_features;
if lang_features.len() == 0 {
if features.declared_features.is_empty() {
return;
}
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())
{
let name = ident.name;
let stable_since = lang_features
let stable_since = features
.declared_lang_features
.iter()
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
.next();

View File

@ -1,5 +1,5 @@
#![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,
thread_local
)]

View File

@ -621,8 +621,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, try_blocks, "1.29.0", Some(31436)),
/// Allows `impl Trait` to be used inside type aliases (RFC 2515).
(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
/// not changed from prior instances of the same struct (RFC #2528)
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),

View File

@ -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
dbg_fmt.field("prev_token", &parser.prev_token);
// make it easier to peek farther ahead by taking TokenKinds only until EOF
let tokens = (0..*lookahead)
.map(|i| parser.look_ahead(i, |tok| tok.kind.clone()))
.scan(parser.prev_token == TokenKind::Eof, |eof, tok| {
let current = eof.then_some(tok.clone()); // include a trailing EOF token
*eof |= &tok == &TokenKind::Eof;
current
});
let mut tokens = vec![];
for i in 0..*lookahead {
let tok = parser.look_ahead(i, |tok| tok.kind.clone());
let is_eof = tok == TokenKind::Eof;
tokens.push(tok);
if is_eof {
// Don't look ahead past EOF.
break;
}
}
dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls);

View File

@ -1376,12 +1376,13 @@ fn parse_expr_from_source_str(
});
}
// Uses a macro rather than a function so that failure messages mention the
// correct line in the test function.
macro_rules! look {
($p:ident, $dist:literal, $kind:expr) => {
$p.look_ahead($dist, |tok| assert_eq!($kind, tok.kind));
};
#[track_caller]
fn look(p: &Parser<'_>, dist: usize, kind: rustc_ast::token::TokenKind) {
// Do the `assert_eq` outside the closure so that `track_caller` works.
// (`#![feature(closure_track_caller)]` + `#[track_caller]` on the closure
// 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]
@ -1397,63 +1398,63 @@ fn look_ahead() {
let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string());
// Current position is the `fn`.
look!(p, 0, token::Ident(kw::Fn, raw_no));
look!(p, 1, token::Ident(sym_f, raw_no));
look!(p, 2, token::OpenDelim(Delimiter::Parenthesis));
look!(p, 3, token::Ident(sym_x, raw_no));
look!(p, 4, token::Colon);
look!(p, 5, token::Ident(sym::u32, raw_no));
look!(p, 6, token::CloseDelim(Delimiter::Parenthesis));
look!(p, 7, token::OpenDelim(Delimiter::Brace));
look!(p, 8, token::Ident(sym_x, raw_no));
look!(p, 9, token::CloseDelim(Delimiter::Brace));
look!(p, 10, token::Ident(kw::Struct, raw_no));
look!(p, 11, token::Ident(sym_S, raw_no));
look!(p, 12, token::Semi);
look(&p, 0, token::Ident(kw::Fn, raw_no));
look(&p, 1, token::Ident(sym_f, raw_no));
look(&p, 2, token::OpenDelim(Delimiter::Parenthesis));
look(&p, 3, token::Ident(sym_x, raw_no));
look(&p, 4, token::Colon);
look(&p, 5, token::Ident(sym::u32, raw_no));
look(&p, 6, token::CloseDelim(Delimiter::Parenthesis));
look(&p, 7, token::OpenDelim(Delimiter::Brace));
look(&p, 8, token::Ident(sym_x, raw_no));
look(&p, 9, token::CloseDelim(Delimiter::Brace));
look(&p, 10, token::Ident(kw::Struct, raw_no));
look(&p, 11, token::Ident(sym_S, raw_no));
look(&p, 12, token::Semi);
// Any lookahead past the end of the token stream returns `Eof`.
look!(p, 13, token::Eof);
look!(p, 14, token::Eof);
look!(p, 15, token::Eof);
look!(p, 100, token::Eof);
look(&p, 13, token::Eof);
look(&p, 14, token::Eof);
look(&p, 15, token::Eof);
look(&p, 100, token::Eof);
// Move forward to the first `x`.
for _ in 0..3 {
p.bump();
}
look!(p, 0, token::Ident(sym_x, raw_no));
look!(p, 1, token::Colon);
look!(p, 2, token::Ident(sym::u32, raw_no));
look!(p, 3, token::CloseDelim(Delimiter::Parenthesis));
look!(p, 4, token::OpenDelim(Delimiter::Brace));
look!(p, 5, token::Ident(sym_x, raw_no));
look!(p, 6, token::CloseDelim(Delimiter::Brace));
look!(p, 7, token::Ident(kw::Struct, raw_no));
look!(p, 8, token::Ident(sym_S, raw_no));
look!(p, 9, token::Semi);
look!(p, 10, token::Eof);
look!(p, 11, token::Eof);
look!(p, 100, token::Eof);
look(&p, 0, token::Ident(sym_x, raw_no));
look(&p, 1, token::Colon);
look(&p, 2, token::Ident(sym::u32, raw_no));
look(&p, 3, token::CloseDelim(Delimiter::Parenthesis));
look(&p, 4, token::OpenDelim(Delimiter::Brace));
look(&p, 5, token::Ident(sym_x, raw_no));
look(&p, 6, token::CloseDelim(Delimiter::Brace));
look(&p, 7, token::Ident(kw::Struct, raw_no));
look(&p, 8, token::Ident(sym_S, raw_no));
look(&p, 9, token::Semi);
look(&p, 10, token::Eof);
look(&p, 11, token::Eof);
look(&p, 100, token::Eof);
// Move forward to the `;`.
for _ in 0..9 {
p.bump();
}
look!(p, 0, token::Semi);
look(&p, 0, token::Semi);
// Any lookahead past the end of the token stream returns `Eof`.
look!(p, 1, token::Eof);
look!(p, 100, token::Eof);
look(&p, 1, token::Eof);
look(&p, 100, token::Eof);
// Move one past the `;`, i.e. past the end of the token stream.
p.bump();
look!(p, 0, token::Eof);
look!(p, 1, token::Eof);
look!(p, 100, token::Eof);
look(&p, 0, token::Eof);
look(&p, 1, token::Eof);
look(&p, 100, token::Eof);
// Bumping after Eof is idempotent.
p.bump();
look!(p, 0, token::Eof);
look!(p, 1, token::Eof);
look!(p, 100, token::Eof);
look(&p, 0, token::Eof);
look(&p, 1, token::Eof);
look(&p, 100, token::Eof);
});
}
@ -1476,24 +1477,261 @@ fn look_ahead_non_outermost_stream() {
for _ in 0..3 {
p.bump();
}
look!(p, 0, token::Ident(kw::Fn, raw_no));
look!(p, 1, token::Ident(sym_f, raw_no));
look!(p, 2, token::OpenDelim(Delimiter::Parenthesis));
look!(p, 3, token::Ident(sym_x, raw_no));
look!(p, 4, token::Colon);
look!(p, 5, token::Ident(sym::u32, raw_no));
look!(p, 6, token::CloseDelim(Delimiter::Parenthesis));
look!(p, 7, token::OpenDelim(Delimiter::Brace));
look!(p, 8, token::Ident(sym_x, raw_no));
look!(p, 9, token::CloseDelim(Delimiter::Brace));
look!(p, 10, token::Ident(kw::Struct, raw_no));
look!(p, 11, token::Ident(sym_S, raw_no));
look!(p, 12, token::Semi);
look!(p, 13, token::CloseDelim(Delimiter::Brace));
look(&p, 0, token::Ident(kw::Fn, raw_no));
look(&p, 1, token::Ident(sym_f, raw_no));
look(&p, 2, token::OpenDelim(Delimiter::Parenthesis));
look(&p, 3, token::Ident(sym_x, raw_no));
look(&p, 4, token::Colon);
look(&p, 5, token::Ident(sym::u32, raw_no));
look(&p, 6, token::CloseDelim(Delimiter::Parenthesis));
look(&p, 7, token::OpenDelim(Delimiter::Brace));
look(&p, 8, token::Ident(sym_x, raw_no));
look(&p, 9, token::CloseDelim(Delimiter::Brace));
look(&p, 10, token::Ident(kw::Struct, raw_no));
look(&p, 11, token::Ident(sym_S, raw_no));
look(&p, 12, token::Semi);
look(&p, 13, token::CloseDelim(Delimiter::Brace));
// Any lookahead past the end of the token stream returns `Eof`.
look!(p, 14, token::Eof);
look!(p, 15, token::Eof);
look!(p, 100, token::Eof);
look(&p, 14, token::Eof);
look(&p, 15, 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,
..
}"
);
});
}

View File

@ -290,9 +290,6 @@ passes_export_name =
passes_extern_main =
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 =
feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}

View File

@ -1492,14 +1492,6 @@ pub struct TraitImplConstStable {
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)]
#[diag(passes_unknown_feature, code = E0635)]
pub struct UnknownFeature {

View File

@ -936,12 +936,6 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let declared_lib_features = &tcx.features().declared_lib_features;
let mut remaining_lib_features = FxIndexMap::default();
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) {
// Warn if the user enables a lib feature multiple times.
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });

View File

@ -8,11 +8,15 @@
/// Infinite iterators like `repeat()` are often used with adapters like
/// [`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`,
/// or if you do not want to keep the repeated element in memory, you can
/// instead use the [`repeat_with()`] function.
///
/// [`repeat_with()`]: crate::iter::repeat_with
/// [`str::repeat()`]: ../../std/primitive.str.html#method.repeat
///
/// # Examples
///

View File

@ -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() {}

View File

@ -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`.