Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 11 pull requests #81392

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b43aa96
Print failure message on all tests that should panic, but don't
johanngan Jan 10, 2021
679f6f3
Add `unwrap_unchecked()` methods for `Option` and `Result`
ojeda Jan 10, 2021
76299b3
Add `SAFETY` annotations
ojeda Jan 10, 2021
63a1eee
Reset LateContext enclosing body in nested items
camsteffen Jan 18, 2021
21fb586
Query for TypeckResults in LateContext::qpath_res
camsteffen Jan 18, 2021
def0e9b
Fix ICE with `ReadPointerAsBytes` validation error
camelid Jan 11, 2021
a7b7a43
Move test to `src/test/ui/consts/`
camelid Jan 11, 2021
eaba3da
Remove qpath_res util function
camsteffen Jan 18, 2021
e25959b
Make more traits of the From/Into family diagnostic items
flip1995 Jan 22, 2021
3a4786d
Use UFCS instead of method calls in `derive(Debug)`. See issue 81211 …
pnkfelix Jan 23, 2021
78e57d3
Regression tests for issue 81211.
pnkfelix Jan 23, 2021
d78f0a1
Test exploring the interactions between all of the different kinds of…
pnkfelix Jan 23, 2021
aa8fdad
placate tidy.
pnkfelix Jan 23, 2021
6d4e03a
codegen: assume constants cannot fail to evaluate
RalfJung Jan 24, 2021
2be1993
Ignore test on 32-bit architectures
camelid Jan 25, 2021
26b4baf
Point to span of upvar making closure FnMut
sledgehammervampire Jan 18, 2021
088c89d
Account for generics when suggesting bound
estebank Jan 19, 2021
042facb
Fix some bugs reported by eslint
GuillaumeGomez Jan 23, 2021
0140dac
Link the reference about undefined behavior
ojeda Jan 25, 2021
01250fc
Add tracking issue
ojeda Jan 25, 2021
24149d7
Blessed change to output of flaky test.
pnkfelix Jan 25, 2021
1c0a52d
rustdoc: Document CommonMark extensions.
ehuss Jan 25, 2021
17ba456
Rollup merge of #80868 - johanngan:should-panic-msg-with-expected, r=…
jonas-schievink Jan 25, 2021
0e416cc
Rollup merge of #80876 - ojeda:option-result-unwrap_unchecked, r=m-ou-se
jonas-schievink Jan 25, 2021
8ee1696
Rollup merge of #80900 - camelid:readpointerasbytes-ice, r=oli-obk
jonas-schievink Jan 25, 2021
e4e79fa
Rollup merge of #81158 - 1000teslas:issue-80313-fix, r=Aaron1011
jonas-schievink Jan 25, 2021
0652507
Rollup merge of #81176 - camsteffen:qpath-res, r=oli-obk
jonas-schievink Jan 25, 2021
00188e0
Rollup merge of #81195 - estebank:suggest-bound-on-trait-with-params,…
jonas-schievink Jan 25, 2021
e94b0b7
Rollup merge of #81277 - flip1995:from_diag_items, r=matthewjasper
jonas-schievink Jan 25, 2021
21998ab
Rollup merge of #81294 - pnkfelix:issue-81211-use-ufcs-in-derive-debu…
jonas-schievink Jan 25, 2021
b1d6d12
Rollup merge of #81299 - GuillaumeGomez:fix-eslint-detected-bugs, r=N…
jonas-schievink Jan 25, 2021
cc7b2ce
Rollup merge of #81327 - RalfJung:codegen-no-const-fail, r=oli-obk
jonas-schievink Jan 25, 2021
c8a112d
Rollup merge of #81389 - ehuss:rustdoc-cmark-extensions, r=GuillaumeG…
jonas-schievink Jan 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions compiler/rustc_builtin_macros/src/deriving/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};

fn make_mut_borrow(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<Expr>) -> P<Expr> {
cx.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Mut, expr))
}

pub fn expand_deriving_debug(
cx: &mut ExtCtxt<'_>,
span: Span,
Expand Down Expand Up @@ -67,34 +71,34 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
let fmt = substr.nonself_args[0].clone();

let mut stmts = Vec::with_capacity(fields.len() + 2);
let fn_path_finish;
match vdata {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
// tuple struct/"normal" variant
let expr =
cx.expr_method_call(span, fmt, Ident::new(sym::debug_tuple, span), vec![name]);
let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);
stmts.push(cx.stmt_let(span, true, builder, expr));

for field in fields {
// Use double indirection to make sure this works for unsized types
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);

let expr = cx.expr_method_call(
span,
builder_expr.clone(),
Ident::new(sym::field, span),
vec![field],
);
let fn_path_field = cx.std_path(&[sym::fmt, sym::DebugTuple, sym::field]);
let builder_recv = make_mut_borrow(cx, span, builder_expr.clone());
let expr = cx.expr_call_global(span, fn_path_field, vec![builder_recv, field]);

// Use `let _ = expr;` to avoid triggering the
// unused_results lint.
stmts.push(stmt_let_underscore(cx, span, expr));
}

fn_path_finish = cx.std_path(&[sym::fmt, sym::DebugTuple, sym::finish]);
}
ast::VariantData::Struct(..) => {
// normal struct/struct variant
let expr =
cx.expr_method_call(span, fmt, Ident::new(sym::debug_struct, span), vec![name]);
let fn_path_debug_struct = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_struct]);
let expr = cx.expr_call_global(span, fn_path_debug_struct, vec![fmt, name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));

for field in fields {
Expand All @@ -104,20 +108,20 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
);

// Use double indirection to make sure this works for unsized types
let fn_path_field = cx.std_path(&[sym::fmt, sym::DebugStruct, sym::field]);
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);
let expr = cx.expr_method_call(
span,
builder_expr.clone(),
Ident::new(sym::field, span),
vec![name, field],
);
let builder_recv = make_mut_borrow(cx, span, builder_expr.clone());
let expr =
cx.expr_call_global(span, fn_path_field, vec![builder_recv, name, field]);
stmts.push(stmt_let_underscore(cx, span, expr));
}
fn_path_finish = cx.std_path(&[sym::fmt, sym::DebugStruct, sym::finish]);
}
}

let expr = cx.expr_method_call(span, builder_expr, Ident::new(sym::finish, span), vec![]);
let builder_recv = make_mut_borrow(cx, span, builder_expr);
let expr = cx.expr_call_global(span, fn_path_finish, vec![builder_recv]);

stmts.push(cx.stmt_expr(expr));
let block = cx.block(span, stmts);
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_codegen_ssa/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx);

let mut all_consts_ok = true;
for const_ in &mir.required_consts {
if let Err(err) = fx.eval_mir_constant(const_) {
all_consts_ok = false;
match err {
// errored or at least linted
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {}
Expand All @@ -199,6 +201,25 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
}
}
}
if !all_consts_ok {
// There is no delay_span_bug here, we just have to rely on a hard error actually having
// been raised.
bx.abort();
// `abort` does not terminate the block, so we still need to generate
// an `unreachable` terminator after it.
bx.unreachable();
// We also have to delete all the other basic blocks again...
for bb in mir.basic_blocks().indices() {
if bb != mir::START_BLOCK {
unsafe {
bx.delete_basic_block(fx.blocks[bb]);
}
}
}
// FIXME: Can we somehow avoid all this by evaluating the consts before creating the basic
// blocks? The tricky part is doing that without duplicating `fx.eval_mir_constant`.
return;
}

let memory_locals = analyze::non_ssa_locals(&fx);

Expand Down
25 changes: 4 additions & 21 deletions compiler/rustc_codegen_ssa/src/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ use crate::glue;
use crate::traits::*;
use crate::MemFlags;

use rustc_errors::ErrorReported;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar};
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::Ty;
use rustc_target::abi::{Abi, Align, LayoutOf, Size};
Expand Down Expand Up @@ -439,25 +438,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}

mir::Operand::Constant(ref constant) => {
self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|err| {
match err {
// errored or at least linted
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {}
ErrorHandled::TooGeneric => {
bug!("codegen encountered polymorphic constant")
}
}
// Allow RalfJ to sleep soundly knowing that even refactorings that remove
// the above error (or silence it under some conditions) will not cause UB.
bx.abort();
// We still have to return an operand but it doesn't matter,
// this code is unreachable.
let ty = self.monomorphize(constant.literal.ty);
let layout = bx.cx().layout_of(ty);
bx.load_operand(PlaceRef::new_sized(
bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))),
layout,
))
// This cannot fail because we checked all required_consts in advance.
self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|_err| {
span_bug!(constant.span, "erroneous constant not captured by required_consts")
})
}
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,14 @@ impl<'tcx> LateContext<'tcx> {
hir::QPath::Resolved(_, ref path) => path.res,
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
.maybe_typeck_results()
.filter(|typeck_results| typeck_results.hir_owner == id.owner)
.or_else(|| {
if self.tcx.has_typeck_results(id.owner.to_def_id()) {
Some(self.tcx.typeck(id.owner))
} else {
None
}
})
.and_then(|typeck_results| typeck_results.type_dependent_def(id))
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,17 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
let generics = self.context.generics.take();
self.context.generics = it.kind.generics();
let old_cached_typeck_results = self.context.cached_typeck_results.take();
let old_enclosing_body = self.context.enclosing_body.take();
self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
cx.with_param_env(it.hir_id, |cx| {
lint_callback!(cx, check_item, it);
hir_visit::walk_item(cx, it);
lint_callback!(cx, check_item_post, it);
});
});
self.context.enclosing_body = old_enclosing_body;
self.context.cached_typeck_results.set(old_cached_typeck_results);
self.context.generics = generics;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use rustc_hir as hir;
use rustc_hir::Node;
use rustc_index::vec::Idx;
use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location};
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{
hir::place::PlaceBase,
mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location},
};
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
Expand Down Expand Up @@ -241,6 +244,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
format!("mut {}", self.local_names[local].unwrap()),
Applicability::MachineApplicable,
);
let tcx = self.infcx.tcx;
if let ty::Closure(id, _) = the_place_err.ty(self.body, tcx).ty.kind() {
self.show_mutating_upvar(tcx, id, the_place_err, &mut err);
}
}

// Also suggest adding mut for upvars
Expand Down Expand Up @@ -271,6 +278,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
);
}
}

let tcx = self.infcx.tcx;
if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind()
{
if let ty::Closure(id, _) = ty.kind() {
self.show_mutating_upvar(tcx, id, the_place_err, &mut err);
}
}
}

// complete hack to approximate old AST-borrowck
Expand Down Expand Up @@ -463,6 +478,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.buffer(&mut self.errors_buffer);
}

// point to span of upvar making closure call require mutable borrow
fn show_mutating_upvar(
&self,
tcx: TyCtxt<'_>,
id: &hir::def_id::DefId,
the_place_err: PlaceRef<'tcx>,
err: &mut DiagnosticBuilder<'_>,
) {
let id = id.expect_local();
let tables = tcx.typeck(id);
let hir_id = tcx.hir().local_def_id_to_hir_id(id);
let (span, place) = &tables.closure_kind_origins()[hir_id];
let reason = if let PlaceBase::Upvar(upvar_id) = place.base {
let upvar = ty::place_to_string_for_capture(tcx, place);
match tables.upvar_capture(upvar_id) {
ty::UpvarCapture::ByRef(ty::UpvarBorrow {
kind: ty::BorrowKind::MutBorrow,
..
}) => {
format!("mutable borrow of `{}`", upvar)
}
ty::UpvarCapture::ByValue(_) => {
format!("possible mutation of `{}`", upvar)
}
_ => bug!("upvar `{}` borrowed, but not mutably", upvar),
}
} else {
bug!("not an upvar")
};
err.span_label(
*span,
format!(
"calling `{}` requires mutable binding due to {}",
self.describe_place(the_place_err).unwrap(),
reason
),
);
}

/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) {
err.span_label(sp, format!("cannot {}", act));
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_mir/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Constant(ref constant) => {
let val =
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal);
// This can still fail:
// * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
// checked yet.
// * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
self.const_to_op(val, layout)?
}
};
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_mir/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
Ok(true)
}
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
let value = self.ecx.read_scalar(value)?;
let value = try_validation!(
self.ecx.read_scalar(value),
self.path,
err_unsup!(ReadPointerAsBytes) => { "read of part of a pointer" },
);
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
if self.ctfe_mode.is_some() {
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ symbols! {
Copy,
Count,
Debug,
DebugStruct,
DebugTuple,
Decodable,
Decoder,
Default,
Expand Down Expand Up @@ -622,6 +624,7 @@ symbols! {
intel,
into_iter,
into_result,
into_trait,
intra_doc_pointers,
intrinsics,
irrefutable_let_patterns,
Expand Down Expand Up @@ -1159,6 +1162,8 @@ symbols! {
truncf32,
truncf64,
try_blocks,
try_from_trait,
try_into_trait,
try_trait,
tt,
tuple,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,21 +286,32 @@ fn suggest_restriction(
);
} else {
// Trivial case: `T` needs an extra bound: `T: Bound`.
let (sp, suggestion) = match super_traits {
None => predicate_constraint(
let (sp, suggestion) = match (
generics
.params
.iter()
.filter(
|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: Some(_), ..}),
)
.next(),
super_traits,
) {
(_, None) => predicate_constraint(
generics,
trait_ref.without_const().to_predicate(tcx).to_string(),
),
Some((ident, bounds)) => match bounds {
[.., bound] => (
bound.span().shrink_to_hi(),
format!(" + {}", trait_ref.print_only_trait_path().to_string()),
),
[] => (
ident.span.shrink_to_hi(),
format!(": {}", trait_ref.print_only_trait_path().to_string()),
),
},
(None, Some((ident, []))) => (
ident.span.shrink_to_hi(),
format!(": {}", trait_ref.print_only_trait_path().to_string()),
),
(_, Some((_, [.., bounds]))) => (
bounds.span().shrink_to_hi(),
format!(" + {}", trait_ref.print_only_trait_path().to_string()),
),
(Some(_), Some((_, []))) => (
generics.span.shrink_to_hi(),
format!(": {}", trait_ref.print_only_trait_path().to_string()),
),
};

err.span_suggestion_verbose(
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/convert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ pub trait AsMut<T: ?Sized> {
///
/// [`String`]: ../../std/string/struct.String.html
/// [`Vec`]: ../../std/vec/struct.Vec.html
#[rustc_diagnostic_item = "into_trait"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Into<T>: Sized {
/// Performs the conversion.
Expand Down Expand Up @@ -382,6 +383,7 @@ pub trait From<T>: Sized {
///
/// This suffers the same restrictions and reasoning as implementing
/// [`Into`], see there for details.
#[rustc_diagnostic_item = "try_into_trait"]
#[stable(feature = "try_from", since = "1.34.0")]
pub trait TryInto<T>: Sized {
/// The type returned in the event of a conversion error.
Expand Down Expand Up @@ -462,6 +464,7 @@ pub trait TryInto<T>: Sized {
///
/// [`try_from`]: TryFrom::try_from
/// [`!`]: ../../std/primitive.never.html
#[rustc_diagnostic_item = "try_from_trait"]
#[stable(feature = "try_from", since = "1.34.0")]
pub trait TryFrom<T>: Sized {
/// The type returned in the event of a conversion error.
Expand Down
Loading