Skip to content

Commit

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

This pull request backports the following pull requests, which have all been beta-accepted by the
compiler team.

 * Handle non_exhaustive in borrow checking #66722
 * Do not ICE on trait aliases with missing obligations #66392
 * Do not ICE in `if` without `else` in `async fn` #66391
 * Fix ICE when trying to suggest `Type<>` instead of `Type()` #66390
 * Do not ICE on recovery from unmet associated type bound obligation #66388
 * find_deprecation: deprecation attr may be ill-formed meta. #66381
 * parser: don't use `unreachable!()` in `fn unexpected`. #66361
 * Undo an assert causing an ICE until we fix the underlying problem #66250
 * Do not ICE with a precision flag in formatting str and no format arguments #66093
 * Fix two OOM issues related to `ConstProp` #66394
  • Loading branch information
bors committed Dec 7, 2019
2 parents 1463fed + d8612f3 commit 3f7f341
Show file tree
Hide file tree
Showing 29 changed files with 335 additions and 38 deletions.
19 changes: 10 additions & 9 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1874,15 +1874,16 @@ impl<'a> LoweringContext<'a> {
if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
// Do not suggest going from `Trait()` to `Trait<>`
if data.inputs.len() > 0 {
let split = snippet.find('(').unwrap();
let trait_name = &snippet[0..split];
let args = &snippet[split + 1 .. snippet.len() - 1];
err.span_suggestion(
data.span,
"use angle brackets instead",
format!("{}<{}>", trait_name, args),
Applicability::MaybeIncorrect,
);
if let Some(split) = snippet.find('(') {
let trait_name = &snippet[0..split];
let args = &snippet[split + 1 .. snippet.len() - 1];
err.span_suggestion(
data.span,
"use angle brackets instead",
format!("{}<{}>", trait_name, args),
Applicability::MaybeIncorrect,
);
}
}
};
err.emit();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.hir.tcx().features().exhaustive_patterns &&
!v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
}
});
}) && (adt_def.did.is_local() || !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index);
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
Expand Down
10 changes: 9 additions & 1 deletion src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use rustc::ty::subst::InternalSubsts;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::IndexVec;
use rustc::ty::layout::{
LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout,
LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size,
};

use crate::interpret::{
Expand All @@ -34,6 +34,9 @@ use crate::interpret::{
use crate::const_eval::error_to_const_error;
use crate::transform::{MirPass, MirSource};

/// The maximum number of bytes that we'll allocate space for a return value.
const MAX_ALLOC_LIMIT: u64 = 1024;

pub struct ConstProp;

impl<'tcx> MirPass<'tcx> for ConstProp {
Expand Down Expand Up @@ -434,6 +437,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
) -> Option<()> {
let span = source_info.span;

// #66397: Don't try to eval into large places as that can cause an OOM
if place_layout.size >= Size::from_bytes(MAX_ALLOC_LIMIT) {
return None;
}

let overflow_check = self.tcx.sess.overflow_checks();

// Perform any special handling for specific Rvalue types.
Expand Down
6 changes: 1 addition & 5 deletions src/librustc_target/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,11 +738,7 @@ impl FieldPlacement {

pub fn offset(&self, i: usize) -> Size {
match *self {
FieldPlacement::Union(count) => {
assert!(i < count,
"Tried to access field {} of union with {} fields", i, count);
Size::ZERO
},
FieldPlacement::Union(_) => Size::ZERO,
FieldPlacement::Array { stride, count } => {
let i = i as u64;
assert!(i < count);
Expand Down
31 changes: 19 additions & 12 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1221,16 +1221,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
}

/// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
/// removing the dummy `Self` type (`trait_object_dummy_self`).
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
-> ty::ExistentialTraitRef<'tcx> {
if trait_ref.self_ty() != self.tcx().types.trait_object_dummy_self {
bug!("trait_ref_to_existential called on {:?} with non-dummy Self", trait_ref);
}
ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
}

fn conv_object_ty_poly_trait_ref(&self,
span: Span,
trait_bounds: &[hir::PolyTraitRef],
Expand Down Expand Up @@ -1412,13 +1402,30 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("regular_traits: {:?}", regular_traits);
debug!("auto_traits: {:?}", auto_traits);

// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
// removing the dummy `Self` type (`trait_object_dummy_self`).
let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| {
if trait_ref.self_ty() != dummy_self {
// FIXME: There appears to be a missing filter on top of `expand_trait_aliases`,
// which picks up non-supertraits where clauses - but also, the object safety
// completely ignores trait aliases, which could be object safety hazards. We
// `delay_span_bug` here to avoid an ICE in stable even when the feature is
// disabled. (#66420)
tcx.sess.delay_span_bug(DUMMY_SP, &format!(
"trait_ref_to_existential called on {:?} with non-dummy Self",
trait_ref,
));
}
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
};

// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
let existential_trait_refs = regular_traits.iter().map(|i| {
i.trait_ref().map_bound(|trait_ref| self.trait_ref_to_existential(trait_ref))
i.trait_ref().map_bound(|trait_ref| trait_ref_to_existential(trait_ref))
});
let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
bound.map_bound(|b| {
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
ty::ExistentialProjection {
ty: b.ty,
item_def_id: b.projection_ty.item_def_id,
Expand Down
10 changes: 8 additions & 2 deletions src/librustc_typeck/check/generator_interior.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
// can be reborrowed without needing to spill to a temporary.
// If this were not the case, then we could conceivably have
// to create intermediate temporaries.)
let ty = self.fcx.tables.borrow().expr_ty(expr);
self.record(ty, scope, Some(expr), expr.span);
//
// The type table might not have information for this expression
// if it is in a malformed scope. (#66387)
if let Some(ty) = self.fcx.tables.borrow().expr_ty_opt(expr) {
self.record(ty, scope, Some(expr), expr.span);
} else {
self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node");
}
}
}
3 changes: 2 additions & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3010,7 +3010,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fallback_has_occurred: bool,
mutate_fullfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
) {
if let Err(mut errors) = self.fulfillment_cx.borrow_mut().select_where_possible(self) {
let result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
if let Err(mut errors) = result {
mutate_fullfillment_errors(&mut errors);
self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
}
Expand Down
5 changes: 4 additions & 1 deletion src/libsyntax/attr/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,10 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess,
break
}

let meta = attr.meta().unwrap();
let meta = match attr.meta() {
Some(meta) => meta,
None => continue,
};
depr = match &meta.kind {
MetaItemKind::Word => Some(Deprecation { since: None, note: None }),
MetaItemKind::NameValue(..) => {
Expand Down
4 changes: 3 additions & 1 deletion src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,9 @@ impl<'a> Parser<'a> {
crate fn unexpected<T>(&mut self) -> PResult<'a, T> {
match self.expect_one_of(&[], &[]) {
Err(e) => Err(e),
Ok(_) => unreachable!(),
// We can get `Ok(true)` from `recover_closing_delimiter`
// which is called in `expected_one_of_not_found`.
Ok(_) => FatalError.raise(),
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/libsyntax_ext/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,12 @@ impl<'a, 'b> Context<'a, 'b> {
format!("are {} arguments", count)
},
));
e.span_label(
self.args[pos].span,
"this parameter corresponds to the precision flag",
);
if let Some(arg) = self.args.get(pos) {
e.span_label(
arg.span,
"this parameter corresponds to the precision flag",
);
}
zero_based_note = true;
}
_ => {}
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/async-await/issue-66387-if-without-else.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// edition:2018
async fn f() -> i32 {
if true { //~ ERROR if may be missing an else clause
return 0;
}
// An `if` block without `else` causes the type table not to have a type for this expr.
// Check that we do not unconditionally access the type table and we don't ICE.
}

fn main() {}
16 changes: 16 additions & 0 deletions src/test/ui/async-await/issue-66387-if-without-else.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0317]: if may be missing an else clause
--> $DIR/issue-66387-if-without-else.rs:3:5
|
LL | / if true {
LL | | return 0;
LL | | }
| |_____^ expected (), found i32
|
= note: expected type `()`
found type `i32`
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type

error: aborting due to previous error

For more information about this error, try `rustc --explain E0317`.
12 changes: 12 additions & 0 deletions src/test/ui/consts/issue-66342.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// check-pass
// only-x86_64

// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash.

fn foo() -> [u8; 4 * 1024 * 1024 * 1024 * 1024] {
unimplemented!()
}

fn main() {
foo();
}
8 changes: 8 additions & 0 deletions src/test/ui/consts/issue-66397.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// check-pass
// only-x86_64

// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash.

fn main() {
[0; 4 * 1024 * 1024 * 1024 * 1024];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// The original problem in #66340 was that `find_deprecation_generic`
// called `attr.meta().unwrap()` under the assumption that the attribute
// was a well-formed `MetaItem`.

fn main() {
foo()
}

#[deprecated(note = test)]
//~^ ERROR expected unsuffixed literal or identifier, found `test`
fn foo() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: expected unsuffixed literal or identifier, found `test`
--> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21
|
LL | #[deprecated(note = test)]
| ^^^^

error: aborting due to previous error

5 changes: 5 additions & 0 deletions src/test/ui/if/ifmt-bad-arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,9 @@ tenth number: {}",
println!("{:foo}", 1); //~ ERROR unknown format trait `foo`
println!("{5} {:4$} {6:7$}", 1);
//~^ ERROR invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument)

// We used to ICE here because we tried to unconditionally access the first argument, which
// doesn't exist.
println!("{:.*}");
//~^ ERROR 2 positional arguments in format string, but no arguments were given
}
13 changes: 12 additions & 1 deletion src/test/ui/if/ifmt-bad-arg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,17 @@ LL | println!("{5} {:4$} {6:7$}", 1);
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html

error: 2 positional arguments in format string, but no arguments were given
--> $DIR/ifmt-bad-arg.rs:92:15
|
LL | println!("{:.*}");
| ^^--^
| |
| this precision flag adds an extra required argument at position 0, which is why there are 2 arguments expected
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html

error[E0308]: mismatched types
--> $DIR/ifmt-bad-arg.rs:78:32
|
Expand All @@ -303,6 +314,6 @@ LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
= note: expected type `&usize`
found type `&{float}`

error: aborting due to 35 previous errors
error: aborting due to 36 previous errors

For more information about this error, try `rustc --explain E0308`.
15 changes: 15 additions & 0 deletions src/test/ui/issues/issue-65462.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// build-pass

enum Empty {}
enum Enum {
Empty( Empty )
}

fn foobar() -> Option< Enum > {
let value: Option< Empty > = None;
Some( Enum::Empty( value? ) )
}

fn main() {
foobar();
}
12 changes: 12 additions & 0 deletions src/test/ui/issues/issue-65673.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(trait_alias)] // Enabled to reduce stderr output, but can be triggered even if disabled.
trait Trait {}
trait WithType {
type Ctx;
}
trait Alias<T> = where T: Trait;

impl<T> WithType for T {
type Ctx = dyn Alias<T>;
//~^ ERROR the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
}
fn main() {}
17 changes: 17 additions & 0 deletions src/test/ui/issues/issue-65673.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/issue-65673.rs:9:5
|
LL | type Ctx;
| --- associated type defined here
...
LL | impl<T> WithType for T {
| ---------------------- in this `impl` item
LL | type Ctx = dyn Alias<T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
15 changes: 15 additions & 0 deletions src/test/ui/issues/issue-66353.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// #66353: ICE when trying to recover from incorrect associated type

trait _Func<T> {
fn func(_: Self);
}

trait _A {
type AssocT;
}

fn main() {
_Func::< <() as _A>::AssocT >::func(());
//~^ ERROR the trait bound `(): _A` is not satisfied
//~| ERROR the trait bound `(): _Func<_>` is not satisfied
}
18 changes: 18 additions & 0 deletions src/test/ui/issues/issue-66353.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0277]: the trait bound `(): _A` is not satisfied
--> $DIR/issue-66353.rs:12:14
|
LL | _Func::< <() as _A>::AssocT >::func(());
| ^^^^^^^^^^^^^^^^^^ the trait `_A` is not implemented for `()`

error[E0277]: the trait bound `(): _Func<_>` is not satisfied
--> $DIR/issue-66353.rs:12:41
|
LL | fn func(_: Self);
| ----------------- required by `_Func::func`
...
LL | _Func::< <() as _A>::AssocT >::func(());
| ^^ the trait `_Func<_>` is not implemented for `()`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
14 changes: 14 additions & 0 deletions src/test/ui/parser/issue-66357-unexpected-unreachable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// The problem in #66357 was that the call trace:
//
// - parse_fn_block_decl
// - expect_or
// - unexpected
// - expect_one_of
// - expected_one_of_not_found
// - recover_closing_delimiter
//
// ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`.

fn f() { |[](* }
//~^ ERROR expected one of `,` or `:`, found `(`
//~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
Loading

0 comments on commit 3f7f341

Please sign in to comment.