Skip to content

Commit

Permalink
Auto merge of #69360 - Mark-Simulacrum:beta-next, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
[beta] beta backports

This backports the following PRs:

* Revert "Remove `checked_add` in `Layout::repeat`" #69241
* Do not ICE when encountering `yield` inside `async` block #69175
* Fix MIR typeck soundness holes #69145
* Fix extra subslice lowering #69128
* Correct ICE caused by macros generating invalid spans. #68611
* Make conflicting_repr_hints a deny-by-default c-future-compat lint #68586
  • Loading branch information
bors committed Feb 24, 2020
2 parents 86f329b + e553243 commit 13e0fbc
Show file tree
Hide file tree
Showing 27 changed files with 344 additions and 64 deletions.
3 changes: 3 additions & 0 deletions src/ci/azure-pipelines/steps/run.yml
Expand Up @@ -31,6 +31,9 @@ steps:
- bash: src/ci/scripts/setup-environment.sh
displayName: Setup environment

- bash: src/ci/scripts/clean-disk.sh
displayName: Clean disk

- bash: src/ci/scripts/should-skip-this.sh
displayName: Decide whether to run this job

Expand Down
16 changes: 16 additions & 0 deletions src/ci/scripts/clean-disk.sh
@@ -0,0 +1,16 @@
#!/bin/bash
# This script deletes some of the Azure-provided artifacts. We don't use these,
# and disk space is at a premium on our builders.

set -euo pipefail
IFS=$'\n\t'

source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"

# All the Linux builds happen inside Docker.
if isLinux; then
# 6.7GB
sudo rm -rf /opt/ghc
# 16GB
sudo rm -rf /usr/share/dotnet
fi
12 changes: 7 additions & 5 deletions src/libcore/alloc.rs
Expand Up @@ -241,11 +241,13 @@ impl Layout {
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
// This cannot overflow. Quoting from the invariant of Layout:
// > `size`, when rounded up to the nearest multiple of `align`,
// > must not overflow (i.e., the rounded value must be less than
// > `usize::MAX`)
let padded_size = self.size() + self.padding_needed_for(self.align());
// Warning, removing the checked_add here led to segfaults in #67174. Further
// analysis in #69225 seems to indicate that this is an LTO-related
// miscompilation, so #67174 might be able to be reapplied in the future.
let padded_size = self
.size()
.checked_add(self.padding_needed_for(self.align()))
.ok_or(LayoutErr { private: () })?;
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;

unsafe {
Expand Down
21 changes: 12 additions & 9 deletions src/librustc/hir/check_attr.rs
Expand Up @@ -14,7 +14,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::DUMMY_HIR_ID;
use rustc_hir::{self, HirId, Item, ItemKind, TraitItem, TraitItemKind};
use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;
use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES};
use rustc_span::symbol::sym;
use rustc_span::Span;
use syntax::ast::Attribute;
Expand Down Expand Up @@ -196,7 +196,7 @@ impl CheckAttrVisitor<'tcx> {
self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(hir_id));
}

self.check_repr(attrs, span, target, item);
self.check_repr(attrs, span, target, item, hir_id);
self.check_used(attrs, target);
}

Expand Down Expand Up @@ -357,6 +357,7 @@ impl CheckAttrVisitor<'tcx> {
span: &Span,
target: Target,
item: Option<&Item<'_>>,
hir_id: HirId,
) {
// Extract the names of all repr hints, e.g., [foo, bar, align] for:
// ```
Expand Down Expand Up @@ -446,13 +447,15 @@ impl CheckAttrVisitor<'tcx> {
|| (is_simd && is_c)
|| (int_reprs == 1 && is_c && item.map_or(false, |item| is_c_like_enum(item)))
{
struct_span_err!(
self.tcx.sess,
hint_spans.collect::<Vec<Span>>(),
E0566,
"conflicting representation hints",
)
.emit();
self.tcx
.struct_span_lint_hir(
CONFLICTING_REPR_HINTS,
hir_id,
hint_spans.collect::<Vec<Span>>(),
"conflicting representation hints",
)
.code(rustc_errors::error_code!(E0566))
.emit();
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/hir/map/hir_id_validator.rs
Expand Up @@ -7,7 +7,7 @@ use rustc_hir::intravisit;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{HirId, ItemLocalId};

pub fn check_crate(hir_map: &Map<'_>) {
pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
hir_map.dep_graph.assert_ignored();

let errors = Lock::new(Vec::new());
Expand All @@ -24,7 +24,7 @@ pub fn check_crate(hir_map: &Map<'_>) {

if !errors.is_empty() {
let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
bug!("{}", message);
sess.delay_span_bug(rustc_span::DUMMY_SP, &message);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/map/mod.rs
Expand Up @@ -1271,7 +1271,7 @@ pub fn map_crate<'hir>(
};

sess.time("validate_HIR_map", || {
hir_id_validator::check_crate(&map);
hir_id_validator::check_crate(&map, sess);
});

map
Expand Down
17 changes: 11 additions & 6 deletions src/librustc_ast_lowering/pat.rs
Expand Up @@ -128,6 +128,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let mut slice = None;
let mut prev_rest_span = None;

// Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| {
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
let node = this.lower_pat_ident(pat, bm, ident, lower_sub);
this.pat_with_node_id_of(pat, node)
};

let mut iter = pats.iter();
// Lower all the patterns until the first occurrence of a sub-slice pattern.
for pat in iter.by_ref() {
Expand All @@ -142,9 +149,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Record, lower it to `$binding_mode $ident @ _`, and stop here.
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
prev_rest_span = Some(sub.span);
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
slice = Some(self.pat_with_node_id_of(pat, node));
slice = Some(lower_rest_sub(self, pat, bm, ident, sub));
break;
}
// It was not a subslice pattern so lower it normally.
Expand All @@ -157,9 +162,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// There was a previous subslice pattern; make sure we don't allow more.
let rest_span = match pat.kind {
PatKind::Rest => Some(pat.span),
PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
// The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
after.push(self.pat_wild_with_node_id_of(pat));
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
// #69103: Lower into `binding @ _` as above to avoid ICEs.
after.push(lower_rest_sub(self, pat, bm, ident, sub));
Some(sub.span)
}
_ => None,
Expand Down
9 changes: 8 additions & 1 deletion src/librustc_errors/emitter.rs
Expand Up @@ -19,6 +19,7 @@ use crate::{
pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle,
};

use log::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_span::hygiene::{ExpnKind, MacroKind};
Expand Down Expand Up @@ -2108,7 +2109,13 @@ impl<'a> Drop for WritableDst<'a> {
/// Whether the original and suggested code are visually similar enough to warrant extra wording.
pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
// FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode.
let found = sm.span_to_snippet(sp).unwrap();
let found = match sm.span_to_snippet(sp) {
Ok(snippet) => snippet,
Err(e) => {
warn!("Invalid span {:?}. Err={:?}", sp, e);
return false;
}
};
let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z'];
// All the chars that differ in capitalization are confusable (above):
let confusable = found
Expand Down
70 changes: 41 additions & 29 deletions src/librustc_mir/borrow_check/type_check/mod.rs
Expand Up @@ -310,6 +310,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
);
}
} else {
let tcx = self.tcx();
if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val {
if let Some(promoted) = promoted {
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
Expand Down Expand Up @@ -359,10 +360,23 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
);
}
}
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
let unnormalized_ty = tcx.type_of(static_def_id);
let locations = location.to_locations();
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
let literal_ty = constant.literal.ty.builtin_deref(true).unwrap().ty;

if let Err(terr) = self.cx.eq_types(
normalized_ty,
literal_ty,
locations,
ConstraintCategory::Boring,
) {
span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
}
}
if let ty::FnDef(def_id, substs) = constant.literal.ty.kind {
let tcx = self.tcx();

if let ty::FnDef(def_id, substs) = constant.literal.ty.kind {
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
self.cx.normalize_and_prove_instantiated_predicates(
instantiated_predicates,
Expand Down Expand Up @@ -467,33 +481,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {

let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);

if place.projection.is_empty() {
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
let tcx = self.tcx();
let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().copy_trait().unwrap(),
substs: tcx.mk_substs_trait(place_ty.ty, &[]),
};

// To have a `Copy` operand, the type `T` of the
// value must be `Copy`. Note that we prove that `T: Copy`,
// rather than using the `is_copy_modulo_regions`
// test. This is important because
// `is_copy_modulo_regions` ignores the resulting region
// obligations and assumes they pass. This can result in
// bounds from `Copy` impls being unsoundly ignored (e.g.,
// #29149). Note that we decide to use `Copy` before knowing
// whether the bounds fully apply: in effect, the rule is
// that if a value of some type could implement `Copy`, then
// it must.
self.cx.prove_trait_ref(
trait_ref,
location.to_locations(),
ConstraintCategory::CopyBound,
);
}
}

for elem in place.projection.iter() {
if place_ty.variant_index.is_none() {
if place_ty.ty.references_error() {
Expand All @@ -504,6 +491,31 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
place_ty = self.sanitize_projection(place_ty, elem, place, location)
}

if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
let tcx = self.tcx();
let trait_ref = ty::TraitRef {
def_id: tcx.lang_items().copy_trait().unwrap(),
substs: tcx.mk_substs_trait(place_ty.ty, &[]),
};

// To have a `Copy` operand, the type `T` of the
// value must be `Copy`. Note that we prove that `T: Copy`,
// rather than using the `is_copy_modulo_regions`
// test. This is important because
// `is_copy_modulo_regions` ignores the resulting region
// obligations and assumes they pass. This can result in
// bounds from `Copy` impls being unsoundly ignored (e.g.,
// #29149). Note that we decide to use `Copy` before knowing
// whether the bounds fully apply: in effect, the rule is
// that if a value of some type could implement `Copy`, then
// it must.
self.cx.prove_trait_ref(
trait_ref,
location.to_locations(),
ConstraintCategory::CopyBound,
);
}

place_ty
}

Expand Down
11 changes: 11 additions & 0 deletions src/librustc_session/lint/builtin.rs
Expand Up @@ -18,6 +18,16 @@ declare_lint! {
};
}

declare_lint! {
pub CONFLICTING_REPR_HINTS,
Deny,
"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #68585 <https://github.com/rust-lang/rust/issues/68585>",
edition: None,
};
}

declare_lint! {
pub META_VARIABLE_MISUSE,
Allow,
Expand Down Expand Up @@ -520,6 +530,7 @@ declare_lint_pass! {
MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
ILL_FORMED_ATTRIBUTE_INPUT,
CONFLICTING_REPR_HINTS,
META_VARIABLE_MISUSE,
DEPRECATED_IN_FUTURE,
AMBIGUOUS_ASSOCIATED_ITEMS,
Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs
@@ -0,0 +1,18 @@
// We used to not lower the extra `b @ ..` into `b @ _` which meant that no type
// was registered for the binding `b` although it passed through resolve.
// This resulted in an ICE (#69103).

fn main() {
let [a @ .., b @ ..] = &mut [1, 2];
//~^ ERROR `..` can only be used once per slice pattern
b;

let [.., c @ ..] = [1, 2];
//~^ ERROR `..` can only be used once per slice pattern
c;

// This never ICEd, but let's make sure it won't regress either.
let (.., d @ ..) = (1, 2);
//~^ ERROR `..` patterns are not allowed here
d;
}
@@ -0,0 +1,26 @@
error: `..` can only be used once per slice pattern
--> $DIR/issue-69103-extra-binding-subslice.rs:6:22
|
LL | let [a @ .., b @ ..] = &mut [1, 2];
| -- ^^ can only be used once per slice pattern
| |
| previously used here

error: `..` can only be used once per slice pattern
--> $DIR/issue-69103-extra-binding-subslice.rs:10:18
|
LL | let [.., c @ ..] = [1, 2];
| -- ^^ can only be used once per slice pattern
| |
| previously used here

error: `..` patterns are not allowed here
--> $DIR/issue-69103-extra-binding-subslice.rs:15:18
|
LL | let (.., d @ ..) = (1, 2);
| ^^
|
= note: only allowed in tuple, tuple struct, and slice patterns

error: aborting due to 3 previous errors

2 changes: 2 additions & 0 deletions src/test/ui/conflicting-repr-hints.rs
Expand Up @@ -11,11 +11,13 @@ enum B {
}

#[repr(C, u64)] //~ ERROR conflicting representation hints
//~^ WARN this was previously accepted
enum C {
C,
}

#[repr(u32, u64)] //~ ERROR conflicting representation hints
//~^ WARN this was previously accepted
enum D {
D,
}
Expand Down

0 comments on commit 13e0fbc

Please sign in to comment.