Skip to content

Commit

Permalink
Auto merge of #63341 - Centril:rollup-hkhxahb, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 9 pull requests

Successful merges:

 - #63034 (Fix generator size regressions due to optimization)
 - #63035 (Use MaybeUninit to produce more correct layouts)
 - #63163 (add a pair of whitespace after remove parentheses)
 - #63294 (tests for async/await drop order)
 - #63307 (don't ignore mir_dump folder)
 - #63308 (PlaceRef's base is already a reference)
 - #63310 (Tests around moving parts of structs and tuples across await points)
 - #63314 (doc: the content has since been moved to the guide)
 - #63333 (Remove unnecessary features from compiler error code list)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Aug 7, 2019
2 parents c326c2e + c8ea26e commit 615c460
Show file tree
Hide file tree
Showing 26 changed files with 1,599 additions and 73 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ config.mk
config.stamp
keywords.md
lexer.ml
mir_dump
Session.vim
src/etc/dl
tmp.*.rs
Expand Down
7 changes: 2 additions & 5 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ This directory contains the source code of the rust project, including:

For more information on how various parts of the compiler work, see the [rustc guide].

There is also useful content in the following READMEs, which are gradually being moved over to the guide:
- https://github.com/rust-lang/rust/tree/master/src/librustc/ty/query
- https://github.com/rust-lang/rust/tree/master/src/librustc/dep_graph
- https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked
- https://github.com/rust-lang/rust/tree/master/src/librustc/infer/lexical_region_resolve
There is also useful content in this README:
https://github.com/rust-lang/rust/tree/master/src/librustc/infer/lexical_region_resolve.

[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
2 changes: 2 additions & 0 deletions src/libcore/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ use crate::mem::ManuallyDrop;
/// guarantee may evolve.
#[allow(missing_debug_implementations)]
#[stable(feature = "maybe_uninit", since = "1.36.0")]
// Lang item so we can wrap other types in it. This is useful for generators.
#[cfg_attr(not(bootstrap), lang = "maybe_uninit")]
#[derive(Copy)]
#[repr(transparent)]
pub union MaybeUninit<T> {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ language_item_table! {

ManuallyDropItem, "manually_drop", manually_drop, Target::Struct;

MaybeUninitLangItem, "maybe_uninit", maybe_uninit, Target::Union;

DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait;

// Align offset for stride != 1, must not panic.
Expand Down
21 changes: 16 additions & 5 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2347,18 +2347,17 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_ty(Foreign(def_id))
}

pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
let adt_def = self.adt_def(def_id);
let substs = InternalSubsts::for_item(self, def_id, |param, substs| {
fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
let adt_def = self.adt_def(wrapper_def_id);
let substs = InternalSubsts::for_item(self, wrapper_def_id, |param, substs| {
match param.kind {
GenericParamDefKind::Lifetime |
GenericParamDefKind::Const => {
bug!()
}
GenericParamDefKind::Type { has_default, .. } => {
if param.index == 0 {
ty.into()
ty_param.into()
} else {
assert!(has_default);
self.type_of(param.def_id).subst(self, substs).into()
Expand All @@ -2369,6 +2368,18 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_ty(Adt(adt_def, substs))
}

#[inline]
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
self.mk_generic_adt(def_id, ty)
}

#[inline]
pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem);
self.mk_generic_adt(def_id, ty)
}

#[inline]
pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
self.mk_ty(RawPtr(tm))
Expand Down
28 changes: 23 additions & 5 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,27 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
}

// Count the number of variants in use. If only one of them, then it is
// impossible to overlap any locals in our layout. In this case it's
// always better to make the remaining locals ineligible, so we can
// lay them out with the other locals in the prefix and eliminate
// unnecessary padding bytes.
{
let mut used_variants = BitSet::new_empty(info.variant_fields.len());
for assignment in &assignments {
match assignment {
Assigned(idx) => { used_variants.insert(*idx); }
_ => {}
}
}
if used_variants.count() < 2 {
for assignment in assignments.iter_mut() {
*assignment = Ineligible(None);
}
ineligible_locals.insert_all();
}
}

// Write down the order of our locals that will be promoted to the prefix.
{
let mut idx = 0u32;
Expand Down Expand Up @@ -1406,24 +1427,21 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
Abi::Scalar(s) => s.clone(),
_ => bug!(),
};
// FIXME(eddyb) wrap each promoted type in `MaybeUninit` so that they
// don't poison the `largest_niche` or `abi` fields of `prefix`.
let promoted_layouts = ineligible_locals.iter()
.map(|local| subst_field(info.field_tys[local]))
.map(|ty| tcx.mk_maybe_uninit(ty))
.map(|ty| self.layout_of(ty));
let prefix_layouts = substs.prefix_tys(def_id, tcx)
.map(|ty| self.layout_of(ty))
.chain(iter::once(Ok(discr_layout)))
.chain(promoted_layouts)
.collect::<Result<Vec<_>, _>>()?;
let mut prefix = self.univariant_uninterned(
let prefix = self.univariant_uninterned(
ty,
&prefix_layouts,
&ReprOptions::default(),
StructKind::AlwaysSized,
)?;
// FIXME(eddyb) need `MaybeUninit` around promoted types (see above).
prefix.largest_niche = None;

let (prefix_size, prefix_align) = (prefix.size, prefix.align);

Expand Down
110 changes: 83 additions & 27 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use syntax::print::pprust;
use syntax::symbol::{kw, sym};
use syntax::symbol::Symbol;
use syntax::util::parser;
use syntax_pos::Span;
use syntax_pos::{Span, BytePos};

use rustc::hir;

Expand Down Expand Up @@ -353,31 +353,46 @@ declare_lint! {
declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);

impl UnusedParens {

fn is_expr_parens_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
followed_by_block && match inner.node {
ast::ExprKind::Ret(_) | ast::ExprKind::Break(..) => true,
_ => parser::contains_exterior_struct_lit(&inner),
}
}

fn check_unused_parens_expr(&self,
cx: &EarlyContext<'_>,
value: &ast::Expr,
msg: &str,
followed_by_block: bool) {
cx: &EarlyContext<'_>,
value: &ast::Expr,
msg: &str,
followed_by_block: bool,
left_pos: Option<BytePos>,
right_pos: Option<BytePos>) {
match value.node {
ast::ExprKind::Paren(ref inner) => {
let necessary = followed_by_block && match inner.node {
ast::ExprKind::Ret(_) | ast::ExprKind::Break(..) => true,
_ => parser::contains_exterior_struct_lit(&inner),
};
if !necessary {
if !Self::is_expr_parens_necessary(inner, followed_by_block) {
let expr_text = if let Ok(snippet) = cx.sess().source_map()
.span_to_snippet(value.span) {
snippet
} else {
pprust::expr_to_string(value)
};
Self::remove_outer_parens(cx, value.span, &expr_text, msg);
let keep_space = (
left_pos.map(|s| s >= value.span.lo()).unwrap_or(false),
right_pos.map(|s| s <= value.span.hi()).unwrap_or(false),
);
Self::remove_outer_parens(cx, value.span, &expr_text, msg, keep_space);
}
}
ast::ExprKind::Let(_, ref expr) => {
// FIXME(#60336): Properly handle `let true = (false && true)`
// actually needing the parenthesis.
self.check_unused_parens_expr(cx, expr, "`let` head expression", followed_by_block);
self.check_unused_parens_expr(
cx, expr,
"`let` head expression",
followed_by_block,
None, None
);
}
_ => {}
}
Expand All @@ -394,11 +409,15 @@ impl UnusedParens {
} else {
pprust::pat_to_string(value)
};
Self::remove_outer_parens(cx, value.span, &pattern_text, msg);
Self::remove_outer_parens(cx, value.span, &pattern_text, msg, (false, false));
}
}

fn remove_outer_parens(cx: &EarlyContext<'_>, span: Span, pattern: &str, msg: &str) {
fn remove_outer_parens(cx: &EarlyContext<'_>,
span: Span,
pattern: &str,
msg: &str,
keep_space: (bool, bool)) {
let span_msg = format!("unnecessary parentheses around {}", msg);
let mut err = cx.struct_span_lint(UNUSED_PARENS, span, &span_msg);
let mut ate_left_paren = false;
Expand All @@ -424,11 +443,27 @@ impl UnusedParens {
},
_ => false,
}
}).to_owned();
});

let replace = {
let mut replace = if keep_space.0 {
let mut s = String::from(" ");
s.push_str(parens_removed);
s
} else {
String::from(parens_removed)
};

if keep_space.1 {
replace.push(' ');
}
replace
};

err.span_suggestion_short(
span,
"remove these parentheses",
parens_removed,
replace,
Applicability::MachineApplicable,
);
err.emit();
Expand All @@ -438,14 +473,35 @@ impl UnusedParens {
impl EarlyLintPass for UnusedParens {
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
use syntax::ast::ExprKind::*;
let (value, msg, followed_by_block) = match e.node {
If(ref cond, ..) => (cond, "`if` condition", true),
While(ref cond, ..) => (cond, "`while` condition", true),
ForLoop(_, ref cond, ..) => (cond, "`for` head expression", true),
Match(ref head, _) => (head, "`match` head expression", true),
Ret(Some(ref value)) => (value, "`return` value", false),
Assign(_, ref value) => (value, "assigned value", false),
AssignOp(.., ref value) => (value, "assigned value", false),
let (value, msg, followed_by_block, left_pos, right_pos) = match e.node {
If(ref cond, ref block, ..) => {
let left = e.span.lo() + syntax_pos::BytePos(2);
let right = block.span.lo();
(cond, "`if` condition", true, Some(left), Some(right))
}

While(ref cond, ref block, ..) => {
let left = e.span.lo() + syntax_pos::BytePos(5);
let right = block.span.lo();
(cond, "`while` condition", true, Some(left), Some(right))
},

ForLoop(_, ref cond, ref block, ..) => {
(cond, "`for` head expression", true, None, Some(block.span.lo()))
}

Match(ref head, _) => {
let left = e.span.lo() + syntax_pos::BytePos(5);
(head, "`match` head expression", true, Some(left), None)
}

Ret(Some(ref value)) => {
let left = e.span.lo() + syntax_pos::BytePos(3);
(value, "`return` value", false, Some(left), None)
}

Assign(_, ref value) => (value, "assigned value", false, None, None),
AssignOp(.., ref value) => (value, "assigned value", false, None, None),
// either function/method call, or something this lint doesn't care about
ref call_or_other => {
let (args_to_check, call_kind) = match *call_or_other {
Expand All @@ -467,12 +523,12 @@ impl EarlyLintPass for UnusedParens {
}
let msg = format!("{} argument", call_kind);
for arg in args_to_check {
self.check_unused_parens_expr(cx, arg, &msg, false);
self.check_unused_parens_expr(cx, arg, &msg, false, None, None);
}
return;
}
};
self.check_unused_parens_expr(cx, &value, msg, followed_by_block);
self.check_unused_parens_expr(cx, &value, msg, followed_by_block, left_pos, right_pos);
}

fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
Expand All @@ -492,7 +548,7 @@ impl EarlyLintPass for UnusedParens {
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
if let ast::StmtKind::Local(ref local) = s.node {
if let Some(ref value) = local.init {
self.check_unused_parens_expr(cx, &value, "assigned value", false);
self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None);
}
}
}
Expand Down
Loading

0 comments on commit 615c460

Please sign in to comment.