Skip to content

Commit 207d955

Browse files
committed
Auto merge of #89047 - GuillaumeGomez:rollup-29gmr02, r=GuillaumeGomez
Rollup of 10 pull requests Successful merges: - #86422 (Emit clearer diagnostics for parens around `for` loop heads) - #87460 (Point to closure when emitting 'cannot move out' for captured variable) - #87566 (Recover invalid assoc type bounds using `==`) - #88666 (Improve build command for compiler docs) - #88899 (Do not issue E0071 if a type error has already been reported) - #88949 (Fix handling of `hir::GenericArg::Infer` in `wrong_number_of_generic_args.rs`) - #88953 (Add chown functions to std::os::unix::fs to change the owner and group of files) - #88954 (Allow `panic!("{}", computed_str)` in const fn.) - #88964 (Add rustdoc version into the help popup) - #89012 (Suggest removing `#![feature]` for library features that have been stabilized) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents e0c38af + 101a88f commit 207d955

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+963
-330
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,10 +702,16 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
702702
}
703703

704704
fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
705+
// checks if `#![feature]` has been used to enable any lang feature
706+
// does not check the same for lib features unless there's at least one
707+
// declared lang feature
705708
use rustc_errors::Applicability;
706709

707710
if !sess.opts.unstable_features.is_nightly_build() {
708711
let lang_features = &sess.features_untracked().declared_lang_features;
712+
if lang_features.len() == 0 {
713+
return;
714+
}
709715
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
710716
let mut err = struct_span_err!(
711717
sess.parse_sess.span_diagnostic,

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,15 +336,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
336336
if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
337337
{
338338
let closure_kind_ty = closure_substs.as_closure().kind_ty();
339-
let closure_kind = closure_kind_ty.to_opt_closure_kind();
340-
let capture_description = match closure_kind {
341-
Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure",
342-
Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure",
339+
let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
340+
Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
343341
Some(ty::ClosureKind::FnOnce) => {
344342
bug!("closure kind does not match first argument type")
345343
}
346344
None => bug!("closure kind not inferred by borrowck"),
347345
};
346+
let capture_description =
347+
format!("captured variable in an `{}` closure", closure_kind);
348348

349349
let upvar = &self.upvars[upvar_field.unwrap().index()];
350350
let upvar_hir_id = upvar.place.get_root_variable();
@@ -368,6 +368,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
368368
let mut diag = self.cannot_move_out_of(span, &place_description);
369369

370370
diag.span_label(upvar_span, "captured outer variable");
371+
diag.span_label(
372+
self.body.span,
373+
format!("captured by this `{}` closure", closure_kind),
374+
);
371375

372376
diag
373377
}

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
3636
let def_id = instance.def_id();
3737
if Some(def_id) == self.tcx.lang_items().panic_fn()
3838
|| Some(def_id) == self.tcx.lang_items().panic_str()
39+
|| Some(def_id) == self.tcx.lang_items().panic_display()
3940
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
4041
{
41-
// &str
42+
// &str or &&str
4243
assert!(args.len() == 1);
4344

44-
let msg_place = self.deref_operand(&args[0])?;
45+
let mut msg_place = self.deref_operand(&args[0])?;
46+
while msg_place.layout.ty.is_ref() {
47+
msg_place = self.deref_operand(&msg_place.into())?;
48+
}
49+
4550
let msg = Symbol::intern(self.read_str(&msg_place)?);
4651
let span = self.find_closest_untracked_caller_location();
4752
let (file, line, col) = self.location_triple_for_span(span);

compiler/rustc_const_eval/src/transform/check_consts/check.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
888888
if is_lang_panic_fn(tcx, callee) {
889889
self.check_op(ops::Panic);
890890

891+
// `begin_panic` and `panic_display` are generic functions that accept
892+
// types other than str. Check to enforce that only str can be used in
893+
// const-eval.
894+
891895
// const-eval of the `begin_panic` fn assumes the argument is `&str`
892896
if Some(callee) == tcx.lang_items().begin_panic_fn() {
893897
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
@@ -896,6 +900,15 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
896900
}
897901
}
898902

903+
// const-eval of the `panic_display` fn assumes the argument is `&&str`
904+
if Some(callee) == tcx.lang_items().panic_display() {
905+
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
906+
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
907+
{}
908+
_ => self.check_op(ops::PanicNonStr),
909+
}
910+
}
911+
899912
return;
900913
}
901914

compiler/rustc_const_eval/src/transform/check_consts/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
7979
// Keep in sync with what that function handles!
8080
Some(def_id) == tcx.lang_items().panic_fn()
8181
|| Some(def_id) == tcx.lang_items().panic_str()
82+
|| Some(def_id) == tcx.lang_items().panic_display()
8283
|| Some(def_id) == tcx.lang_items().begin_panic_fn()
8384
|| Some(def_id) == tcx.lang_items().panic_fmt()
8485
|| Some(def_id) == tcx.lang_items().begin_panic_fmt()

compiler/rustc_error_codes/src/error_codes/E0071.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ form of initializer was used.
1515
For example, the code above can be fixed to:
1616

1717
```
18-
enum Foo {
19-
FirstValue(i32)
20-
}
18+
type U32 = u32;
19+
let t: U32 = 4;
20+
```
2121

22-
fn main() {
23-
let u = Foo::FirstValue(0i32);
22+
or:
2423

25-
let t = 4;
26-
}
24+
```
25+
struct U32 { value: u32 }
26+
let t = U32 { value: 4 };
2727
```

compiler/rustc_hir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ language_item_table! {
283283
// a weak lang item, but do not have it defined.
284284
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
285285
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
286+
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
286287
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
287288
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
288289
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,30 +1334,25 @@ impl<'a> Parser<'a> {
13341334
pub(super) fn recover_parens_around_for_head(
13351335
&mut self,
13361336
pat: P<Pat>,
1337-
expr: &Expr,
13381337
begin_paren: Option<Span>,
13391338
) -> P<Pat> {
13401339
match (&self.token.kind, begin_paren) {
13411340
(token::CloseDelim(token::Paren), Some(begin_par_sp)) => {
13421341
self.bump();
13431342

1344-
let pat_str = self
1345-
// Remove the `(` from the span of the pattern:
1346-
.span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap())
1347-
.unwrap_or_else(|_| pprust::pat_to_string(&pat));
1348-
1349-
self.struct_span_err(self.prev_token.span, "unexpected closing `)`")
1350-
.span_label(begin_par_sp, "opening `(`")
1351-
.span_suggestion(
1352-
begin_par_sp.to(self.prev_token.span),
1353-
"remove parenthesis in `for` loop",
1354-
format!("{} in {}", pat_str, pprust::expr_to_string(&expr)),
1355-
// With e.g. `for (x) in y)` this would replace `(x) in y)`
1356-
// with `x) in y)` which is syntactically invalid.
1357-
// However, this is prevented before we get here.
1358-
Applicability::MachineApplicable,
1359-
)
1360-
.emit();
1343+
self.struct_span_err(
1344+
MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]),
1345+
"unexpected parenthesis surrounding `for` loop head",
1346+
)
1347+
.multipart_suggestion(
1348+
"remove parenthesis in `for` loop",
1349+
vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())],
1350+
// With e.g. `for (x) in y)` this would replace `(x) in y)`
1351+
// with `x) in y)` which is syntactically invalid.
1352+
// However, this is prevented before we get here.
1353+
Applicability::MachineApplicable,
1354+
)
1355+
.emit();
13611356

13621357
// Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
13631358
pat.and_then(|pat| match pat.kind {
@@ -1955,7 +1950,19 @@ impl<'a> Parser<'a> {
19551950
}
19561951
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
19571952
Ok(expr) => {
1958-
if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() {
1953+
// Find a mistake like `MyTrait<Assoc == S::Assoc>`.
1954+
if token::EqEq == snapshot.token.kind {
1955+
err.span_suggestion(
1956+
snapshot.token.span,
1957+
"if you meant to use an associated type binding, replace `==` with `=`",
1958+
"=".to_string(),
1959+
Applicability::MaybeIncorrect,
1960+
);
1961+
let value = self.mk_expr_err(start.to(expr.span));
1962+
err.emit();
1963+
return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
1964+
} else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
1965+
{
19591966
// Avoid the following output by checking that we consumed a full const arg:
19601967
// help: expressions must be enclosed in braces to be used as const generic
19611968
// arguments

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> {
20422042
self.check_for_for_in_in_typo(self.prev_token.span);
20432043
let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
20442044

2045-
let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren);
2045+
let pat = self.recover_parens_around_for_head(pat, begin_paren);
20462046

20472047
let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
20482048
attrs.extend(iattrs);

compiler/rustc_passes/src/stability.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,16 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
929929
let declared_lib_features = &tcx.features().declared_lib_features;
930930
let mut remaining_lib_features = FxHashMap::default();
931931
for (feature, span) in declared_lib_features {
932+
if !tcx.sess.opts.unstable_features.is_nightly_build() {
933+
struct_span_err!(
934+
tcx.sess,
935+
*span,
936+
E0554,
937+
"`#![feature]` may not be used on the {} release channel",
938+
env!("CFG_RELEASE_CHANNEL")
939+
)
940+
.emit();
941+
}
932942
if remaining_lib_features.contains_key(&feature) {
933943
// Warn if the user enables a lib feature multiple times.
934944
duplicate_feature_err(tcx.sess, *span, *feature);

0 commit comments

Comments
 (0)