Skip to content

Commit

Permalink
Auto merge of rust-lang#89047 - GuillaumeGomez:rollup-29gmr02, r=Guil…
Browse files Browse the repository at this point in the history
…laumeGomez

Rollup of 10 pull requests

Successful merges:

 - rust-lang#86422 (Emit clearer diagnostics for parens around `for` loop heads)
 - rust-lang#87460 (Point to closure when emitting 'cannot move out' for captured variable)
 - rust-lang#87566 (Recover invalid assoc type bounds using `==`)
 - rust-lang#88666 (Improve build command for compiler docs)
 - rust-lang#88899 (Do not issue E0071 if a type error has already been reported)
 - rust-lang#88949 (Fix handling of `hir::GenericArg::Infer` in `wrong_number_of_generic_args.rs`)
 - rust-lang#88953 (Add chown functions to std::os::unix::fs to change the owner and group of files)
 - rust-lang#88954 (Allow `panic!("{}", computed_str)` in const fn.)
 - rust-lang#88964 (Add rustdoc version into the help popup)
 - rust-lang#89012 (Suggest removing `#![feature]` for library features that have been stabilized)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Sep 17, 2021
2 parents e0c38af + 101a88f commit 207d955
Show file tree
Hide file tree
Showing 49 changed files with 963 additions and 330 deletions.
6 changes: 6 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,10 +702,16 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
}

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

if !sess.opts.unstable_features.is_nightly_build() {
let lang_features = &sess.features_untracked().declared_lang_features;
if lang_features.len() == 0 {
return;
}
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
let mut err = struct_span_err!(
sess.parse_sess.span_diagnostic,
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_borrowck/src/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,15 +336,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
{
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind();
let capture_description = match closure_kind {
Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure",
Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure",
let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
Some(ty::ClosureKind::FnOnce) => {
bug!("closure kind does not match first argument type")
}
None => bug!("closure kind not inferred by borrowck"),
};
let capture_description =
format!("captured variable in an `{}` closure", closure_kind);

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

diag.span_label(upvar_span, "captured outer variable");
diag.span_label(
self.body.span,
format!("captured by this `{}` closure", closure_kind),
);

diag
}
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,17 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
let def_id = instance.def_id();
if Some(def_id) == self.tcx.lang_items().panic_fn()
|| Some(def_id) == self.tcx.lang_items().panic_str()
|| Some(def_id) == self.tcx.lang_items().panic_display()
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
{
// &str
// &str or &&str
assert!(args.len() == 1);

let msg_place = self.deref_operand(&args[0])?;
let mut msg_place = self.deref_operand(&args[0])?;
while msg_place.layout.ty.is_ref() {
msg_place = self.deref_operand(&msg_place.into())?;
}

let msg = Symbol::intern(self.read_str(&msg_place)?);
let span = self.find_closest_untracked_caller_location();
let (file, line, col) = self.location_triple_for_span(span);
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
if is_lang_panic_fn(tcx, callee) {
self.check_op(ops::Panic);

// `begin_panic` and `panic_display` are generic functions that accept
// types other than str. Check to enforce that only str can be used in
// const-eval.

// const-eval of the `begin_panic` fn assumes the argument is `&str`
if Some(callee) == tcx.lang_items().begin_panic_fn() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
Expand All @@ -896,6 +900,15 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
}
}

// const-eval of the `panic_display` fn assumes the argument is `&&str`
if Some(callee) == tcx.lang_items().panic_display() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
{}
_ => self.check_op(ops::PanicNonStr),
}
}

return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
// Keep in sync with what that function handles!
Some(def_id) == tcx.lang_items().panic_fn()
|| Some(def_id) == tcx.lang_items().panic_str()
|| Some(def_id) == tcx.lang_items().panic_display()
|| Some(def_id) == tcx.lang_items().begin_panic_fn()
|| Some(def_id) == tcx.lang_items().panic_fmt()
|| Some(def_id) == tcx.lang_items().begin_panic_fmt()
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_error_codes/src/error_codes/E0071.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ form of initializer was used.
For example, the code above can be fixed to:

```
enum Foo {
FirstValue(i32)
}
type U32 = u32;
let t: U32 = 4;
```

fn main() {
let u = Foo::FirstValue(0i32);
or:

let t = 4;
}
```
struct U32 { value: u32 }
let t = U32 { value: 4 };
```
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ language_item_table! {
// a weak lang item, but do not have it defined.
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;
Expand Down
45 changes: 26 additions & 19 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1334,30 +1334,25 @@ impl<'a> Parser<'a> {
pub(super) fn recover_parens_around_for_head(
&mut self,
pat: P<Pat>,
expr: &Expr,
begin_paren: Option<Span>,
) -> P<Pat> {
match (&self.token.kind, begin_paren) {
(token::CloseDelim(token::Paren), Some(begin_par_sp)) => {
self.bump();

let pat_str = self
// Remove the `(` from the span of the pattern:
.span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap())
.unwrap_or_else(|_| pprust::pat_to_string(&pat));

self.struct_span_err(self.prev_token.span, "unexpected closing `)`")
.span_label(begin_par_sp, "opening `(`")
.span_suggestion(
begin_par_sp.to(self.prev_token.span),
"remove parenthesis in `for` loop",
format!("{} in {}", pat_str, pprust::expr_to_string(&expr)),
// With e.g. `for (x) in y)` this would replace `(x) in y)`
// with `x) in y)` which is syntactically invalid.
// However, this is prevented before we get here.
Applicability::MachineApplicable,
)
.emit();
self.struct_span_err(
MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]),
"unexpected parenthesis surrounding `for` loop head",
)
.multipart_suggestion(
"remove parenthesis in `for` loop",
vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())],
// With e.g. `for (x) in y)` this would replace `(x) in y)`
// with `x) in y)` which is syntactically invalid.
// However, this is prevented before we get here.
Applicability::MachineApplicable,
)
.emit();

// Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
pat.and_then(|pat| match pat.kind {
Expand Down Expand Up @@ -1955,7 +1950,19 @@ impl<'a> Parser<'a> {
}
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
Ok(expr) => {
if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() {
// Find a mistake like `MyTrait<Assoc == S::Assoc>`.
if token::EqEq == snapshot.token.kind {
err.span_suggestion(
snapshot.token.span,
"if you meant to use an associated type binding, replace `==` with `=`",
"=".to_string(),
Applicability::MaybeIncorrect,
);
let value = self.mk_expr_err(start.to(expr.span));
err.emit();
return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
} else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
{
// Avoid the following output by checking that we consumed a full const arg:
// help: expressions must be enclosed in braces to be used as const generic
// arguments
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> {
self.check_for_for_in_in_typo(self.prev_token.span);
let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;

let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren);
let pat = self.recover_parens_around_for_head(pat, begin_paren);

let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,16 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let declared_lib_features = &tcx.features().declared_lib_features;
let mut remaining_lib_features = FxHashMap::default();
for (feature, span) in declared_lib_features {
if !tcx.sess.opts.unstable_features.is_nightly_build() {
struct_span_err!(
tcx.sess,
*span,
E0554,
"`#![feature]` may not be used on the {} release channel",
env!("CFG_RELEASE_CHANNEL")
)
.emit();
}
if remaining_lib_features.contains_key(&feature) {
// Warn if the user enables a lib feature multiple times.
duplicate_feature_err(tcx.sess, *span, *feature);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ symbols! {
panic_2021,
panic_abort,
panic_bounds_check,
panic_display,
panic_fmt,
panic_handler,
panic_impl,
Expand Down
28 changes: 19 additions & 9 deletions compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,15 +532,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

Some((variant, ty))
} else {
struct_span_err!(
self.tcx.sess,
path_span,
E0071,
"expected struct, variant or union type, found {}",
ty.sort_string(self.tcx)
)
.span_label(path_span, "not a struct")
.emit();
match ty.kind() {
ty::Error(_) => {
// E0071 might be caused by a spelling error, which will have
// already caused an error message and probably a suggestion
// elsewhere. Refrain from emitting more unhelpful errors here
// (issue #88844).
}
_ => {
struct_span_err!(
self.tcx.sess,
path_span,
E0071,
"expected struct, variant or union type, found {}",
ty.sort_string(self.tcx)
)
.span_label(path_span, "not a struct")
.emit();
}
}
None
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
AngleBrackets::Missing => 0,
// Only lifetime arguments can be implied
AngleBrackets::Implied => self.gen_args.args.len(),
AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg {
hir::GenericArg::Lifetime(_) => acc + 1,
_ => acc,
}),
AngleBrackets::Available => self.gen_args.num_lifetime_params(),
}
}

Expand All @@ -148,10 +145,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
AngleBrackets::Missing => 0,
// Only lifetime arguments can be implied
AngleBrackets::Implied => 0,
AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg {
hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => acc + 1,
_ => acc,
}),
AngleBrackets::Available => self.gen_args.num_generic_params(),
}
}

Expand Down Expand Up @@ -651,7 +645,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let mut found_redundant = false;
for arg in self.gen_args.args {
match arg {
hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => {
hir::GenericArg::Type(_)
| hir::GenericArg::Const(_)
| hir::GenericArg::Infer(_) => {
gen_arg_spans.push(arg.span());
if gen_arg_spans.len() > self.num_expected_type_or_const_args() {
found_redundant = true;
Expand Down
9 changes: 9 additions & 0 deletions library/core/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ pub macro panic_2015 {
($msg:literal $(,)?) => (
$crate::panicking::panic($msg)
),
// Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
($msg:expr $(,)?) => (
$crate::panicking::panic_str($msg)
),
// Special-case the single-argument case for const_panic.
("{}", $arg:expr $(,)?) => (
$crate::panicking::panic_display(&$arg)
),
($fmt:expr, $($arg:tt)+) => (
$crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
),
Expand All @@ -44,6 +49,10 @@ pub macro panic_2021 {
() => (
$crate::panicking::panic("explicit panic")
),
// Special-case the single-argument case for const_panic.
("{}", $arg:expr $(,)?) => (
$crate::panicking::panic_display(&$arg)
),
($($t:tt)+) => (
$crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
),
Expand Down
7 changes: 7 additions & 0 deletions library/core/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ pub fn panic_str(expr: &str) -> ! {
panic_fmt(format_args!("{}", expr));
}

#[inline]
#[track_caller]
#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics
pub fn panic_display<T: fmt::Display>(x: &T) -> ! {
panic_fmt(format_args!("{}", *x));
}

#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
Expand Down
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
#![feature(const_trait_impl)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]
#![feature(core_panic)]
#![feature(custom_test_frameworks)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
Expand Down
Loading

0 comments on commit 207d955

Please sign in to comment.