Skip to content

Commit de4ce57

Browse files
authored
Merge pull request #34635 from alexcrichton/beta-next
Last minute backports to beta
2 parents e353933 + 609ae53 commit de4ce57

File tree

8 files changed

+161
-55
lines changed

8 files changed

+161
-55
lines changed

mk/main.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ CFG_RELEASE_NUM=1.10.0
1818
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
1919
# NB Make sure it starts with a dot to conform to semver pre-release
2020
# versions (section 9)
21-
CFG_PRERELEASE_VERSION=.3
21+
CFG_PRERELEASE_VERSION=.4
2222

2323
# Append a version-dependent hash to each library, so we can install different
2424
# versions in the same place

src/librustc/traits/object_safety.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
228228
/// otherwise ensure that they cannot be used when `Self=Trait`.
229229
pub fn is_vtable_safe_method(self,
230230
trait_def_id: DefId,
231-
method: &ty::Method<'tcx>)
231+
method: &ty::Method<'gcx>)
232232
-> bool
233233
{
234+
// Any method that has a `Self : Sized` requisite can't be called.
235+
if self.generics_require_sized_self(&method.generics, &method.predicates) {
236+
return false;
237+
}
238+
234239
self.virtual_call_violation_for_method(trait_def_id, method).is_none()
235240
}
236241

src/librustc_const_eval/eval.rs

+38-45
Original file line numberDiff line numberDiff line change
@@ -556,51 +556,44 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
556556
let result = match e.node {
557557
hir::ExprUnary(hir::UnNeg, ref inner) => {
558558
// unary neg literals already got their sign during creation
559-
match inner.node {
560-
hir::ExprLit(ref lit) => {
561-
use syntax::ast::*;
562-
use syntax::ast::LitIntType::*;
563-
const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1;
564-
const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1;
565-
const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1;
566-
const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1;
567-
match (&lit.node, ety.map(|t| &t.sty)) {
568-
(&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) |
569-
(&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
570-
return Ok(Integral(I8(::std::i8::MIN)))
571-
},
572-
(&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) |
573-
(&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
574-
return Ok(Integral(I16(::std::i16::MIN)))
575-
},
576-
(&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) |
577-
(&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
578-
return Ok(Integral(I32(::std::i32::MIN)))
579-
},
580-
(&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) |
581-
(&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
582-
return Ok(Integral(I64(::std::i64::MIN)))
583-
},
584-
(&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) |
585-
(&LitKind::Int(n, Signed(IntTy::Is)), _) => {
586-
match tcx.sess.target.int_type {
587-
IntTy::I32 => if n == I32_OVERFLOW {
588-
return Ok(Integral(Isize(Is32(::std::i32::MIN))));
589-
},
590-
IntTy::I64 => if n == I64_OVERFLOW {
591-
return Ok(Integral(Isize(Is64(::std::i64::MIN))));
592-
},
593-
_ => bug!(),
594-
}
595-
},
596-
_ => {},
597-
}
598-
},
599-
hir::ExprUnary(hir::UnNeg, ref inner) => {
600-
// skip `--$expr`
601-
return eval_const_expr_partial(tcx, inner, ty_hint, fn_args);
602-
},
603-
_ => {},
559+
if let hir::ExprLit(ref lit) = inner.node {
560+
use syntax::ast::*;
561+
use syntax::ast::LitIntType::*;
562+
const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1;
563+
const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1;
564+
const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1;
565+
const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1;
566+
match (&lit.node, ety.map(|t| &t.sty)) {
567+
(&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) |
568+
(&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
569+
return Ok(Integral(I8(::std::i8::MIN)))
570+
},
571+
(&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) |
572+
(&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
573+
return Ok(Integral(I16(::std::i16::MIN)))
574+
},
575+
(&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) |
576+
(&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
577+
return Ok(Integral(I32(::std::i32::MIN)))
578+
},
579+
(&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) |
580+
(&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
581+
return Ok(Integral(I64(::std::i64::MIN)))
582+
},
583+
(&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) |
584+
(&LitKind::Int(n, Signed(IntTy::Is)), _) => {
585+
match tcx.sess.target.int_type {
586+
IntTy::I32 => if n == I32_OVERFLOW {
587+
return Ok(Integral(Isize(Is32(::std::i32::MIN))));
588+
},
589+
IntTy::I64 => if n == I64_OVERFLOW {
590+
return Ok(Integral(Isize(Is64(::std::i64::MIN))));
591+
},
592+
_ => bug!(),
593+
}
594+
},
595+
_ => {},
596+
}
604597
}
605598
match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? {
606599
Float(f) => Float(-f),

src/librustc_data_structures/obligation_forest/mod.rs

+27-8
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,17 @@ impl<O: ForestObligation> ObligationForest<O> {
208208
///
209209
/// This CAN be done in a snapshot
210210
pub fn register_obligation(&mut self, obligation: O) {
211-
self.register_obligation_at(obligation, None)
211+
// Ignore errors here - there is no guarantee of success.
212+
let _ = self.register_obligation_at(obligation, None);
212213
}
213214

214-
fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>) {
215-
if self.done_cache.contains(obligation.as_predicate()) { return }
215+
// returns Err(()) if we already know this obligation failed.
216+
fn register_obligation_at(&mut self, obligation: O, parent: Option<NodeIndex>)
217+
-> Result<(), ()>
218+
{
219+
if self.done_cache.contains(obligation.as_predicate()) {
220+
return Ok(())
221+
}
216222

217223
match self.waiting_cache.entry(obligation.as_predicate().clone()) {
218224
Entry::Occupied(o) => {
@@ -226,15 +232,21 @@ impl<O: ForestObligation> ObligationForest<O> {
226232
self.nodes[o.get().get()].dependents.push(parent);
227233
}
228234
}
235+
if let NodeState::Error = self.nodes[o.get().get()].state.get() {
236+
Err(())
237+
} else {
238+
Ok(())
239+
}
229240
}
230241
Entry::Vacant(v) => {
231242
debug!("register_obligation_at({:?}, {:?}) - ok",
232243
obligation, parent);
233244
v.insert(NodeIndex::new(self.nodes.len()));
234245
self.cache_list.push(obligation.as_predicate().clone());
235246
self.nodes.push(Node::new(parent, obligation));
247+
Ok(())
236248
}
237-
};
249+
}
238250
}
239251

240252
/// Convert all remaining obligations to the given error.
@@ -306,12 +318,19 @@ impl<O: ForestObligation> ObligationForest<O> {
306318
Ok(Some(children)) => {
307319
// if we saw a Some(_) result, we are not (yet) stalled
308320
stalled = false;
321+
self.nodes[index].state.set(NodeState::Success);
322+
309323
for child in children {
310-
self.register_obligation_at(child,
311-
Some(NodeIndex::new(index)));
324+
let st = self.register_obligation_at(
325+
child,
326+
Some(NodeIndex::new(index))
327+
);
328+
if let Err(()) = st {
329+
// error already reported - propagate it
330+
// to our node.
331+
self.error_at(index);
332+
}
312333
}
313-
314-
self.nodes[index].state.set(NodeState::Success);
315334
}
316335
Err(err) => {
317336
let backtrace = self.error_at(index);

src/librustc_data_structures/obligation_forest/test.rs

+40
Original file line numberDiff line numberDiff line change
@@ -418,3 +418,43 @@ fn orphan() {
418418
let errors = forest.to_errors(());
419419
assert_eq!(errors.len(), 0);
420420
}
421+
422+
#[test]
423+
fn simultaneous_register_and_error() {
424+
// check that registering a failed obligation works correctly
425+
let mut forest = ObligationForest::new();
426+
forest.register_obligation("A");
427+
forest.register_obligation("B");
428+
429+
let Outcome { completed: ok, errors: err, .. } =
430+
forest.process_obligations(&mut C(|obligation| {
431+
match *obligation {
432+
"A" => Err("An error"),
433+
"B" => Ok(Some(vec!["A"])),
434+
_ => unreachable!(),
435+
}
436+
}, |_|{}));
437+
assert_eq!(ok.len(), 0);
438+
assert_eq!(err, vec![super::Error {
439+
error: "An error",
440+
backtrace: vec!["A"]
441+
}]);
442+
443+
let mut forest = ObligationForest::new();
444+
forest.register_obligation("B");
445+
forest.register_obligation("A");
446+
447+
let Outcome { completed: ok, errors: err, .. } =
448+
forest.process_obligations(&mut C(|obligation| {
449+
match *obligation {
450+
"A" => Err("An error"),
451+
"B" => Ok(Some(vec!["A"])),
452+
_ => unreachable!(),
453+
}
454+
}, |_|{}));
455+
assert_eq!(ok.len(), 0);
456+
assert_eq!(err, vec![super::Error {
457+
error: "An error",
458+
backtrace: vec!["A"]
459+
}]);
460+
}

src/test/compile-fail/lint-type-overflow2.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#[allow(unused_variables)]
1616
fn main() {
1717
let x2: i8 = --128; //~ error: literal out of range for i8
18+
//~^ error: attempted to negate with overflow
1819

1920
let x = -3.40282348e+38_f32; //~ error: literal out of range for f32
2021
let x = 3.40282348e+38_f32; //~ error: literal out of range for f32

src/test/run-pass/issue-34503.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
struct X;
13+
trait Foo<T> {
14+
fn foo(&self) where (T, Option<T>): Ord {}
15+
fn bar(&self, x: &Option<T>) -> bool
16+
where Option<T>: Ord { *x < *x }
17+
}
18+
impl Foo<X> for () {}
19+
let _ = &() as &Foo<X>;
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Future: 'static {
12+
// The requirement for Self: Sized must prevent instantiation of
13+
// Future::forget in vtables, otherwise there's an infinite type
14+
// recursion through <Map<...> as Future>::forget.
15+
fn forget(self) where Self: Sized {
16+
Box::new(Map(self)) as Box<Future>;
17+
}
18+
}
19+
20+
struct Map<A>(A);
21+
impl<A: Future> Future for Map<A> {}
22+
23+
pub struct Promise;
24+
impl Future for Promise {}
25+
26+
fn main() {
27+
Promise.forget();
28+
}

0 commit comments

Comments
 (0)