From 439ff69d909a0add54b1ea1e093bc838693d1e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Apr 2017 04:40:31 -0700 Subject: [PATCH 1/6] Add a way to get shorter spans until `char` for pointing at defs ```rust error[E0072]: recursive type `X` has infinite size --> file.rs:10:1 | 10 | struct X { | ^^^^^^^^ recursive type has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `X` representable ``` vs ```rust error[E0072]: recursive type `X` has infinite size --> file.rs:10:1 | 10 | struct X { | _^ starting here... 11 | | x: X, 12 | | } | |_^ ...ending here: recursive type has infinite size | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `X` representable ``` --- src/librustc/traits/error_reporting.rs | 28 +++++++++----------- src/libsyntax/codemap.rs | 19 +++++++++++++ src/test/ui/resolve/issue-3907-2.stderr | 2 +- src/test/{compile-fail => ui/span}/E0072.rs | 3 +-- src/test/ui/span/E0072.stderr | 10 +++++++ src/test/ui/span/multiline-span-E0072.rs | 20 ++++++++++++++ src/test/ui/span/multiline-span-E0072.stderr | 16 +++++++++++ 7 files changed, 80 insertions(+), 18 deletions(-) rename src/test/{compile-fail => ui/span}/E0072.rs (84%) create mode 100644 src/test/ui/span/E0072.stderr create mode 100644 src/test/ui/span/multiline-span-E0072.rs create mode 100644 src/test/ui/span/multiline-span-E0072.stderr diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 152dd6ac3000f..dc85353c21986 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -293,22 +293,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(val) => Some(val), None => { span_err!(self.tcx.sess, err_sp, E0272, - "the #[rustc_on_unimplemented] \ - attribute on \ - trait definition for {} refers to \ - non-existent type parameter {}", - trait_str, s); + "the #[rustc_on_unimplemented] attribute on trait \ + definition for {} refers to non-existent type \ + parameter {}", + trait_str, s); errored = true; None } }, _ => { span_err!(self.tcx.sess, err_sp, E0273, - "the #[rustc_on_unimplemented] attribute \ - on trait definition for {} must have \ - named format arguments, eg \ - `#[rustc_on_unimplemented = \ - \"foo {{T}}\"]`", trait_str); + "the #[rustc_on_unimplemented] attribute on trait \ + definition for {} must have named format arguments, eg \ + `#[rustc_on_unimplemented = \"foo {{T}}\"]`", + trait_str); errored = true; None } @@ -449,8 +447,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "impl has stricter requirements than trait"); if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { - err.span_label(trait_item_span, - &format!("definition of `{}` from trait", item_name)); + let span = self.tcx.sess.codemap().def_span(trait_item_span); + err.span_label(span, &format!("definition of `{}` from trait", item_name)); } err.span_label( @@ -652,6 +650,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { assert!(type_def_id.is_local()); let span = self.hir.span_if_local(type_def_id).unwrap(); + let span = self.sess.codemap().def_span(span); let mut err = struct_span_err!(self.sess, span, E0072, "recursive type `{}` has infinite size", self.item_path_str(type_def_id)); @@ -669,13 +668,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { -> DiagnosticBuilder<'tcx> { let trait_str = self.item_path_str(trait_def_id); + let span = self.sess.codemap().def_span(span); let mut err = struct_span_err!( self.sess, span, E0038, "the trait `{}` cannot be made into an object", trait_str); - err.span_label(span, &format!( - "the trait `{}` cannot be made into an object", trait_str - )); + err.span_label(span, &format!("the trait `{}` cannot be made into an object", trait_str)); let mut reported_violations = FxHashSet(); for violation in violations { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 4d67390d44234..da2d0a33d1a10 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -441,6 +441,25 @@ impl CodeMap { } } + /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char` + pub fn span_until_char(&self, sp: Span, c: char) -> Span { + match self.span_to_snippet(sp) { + Ok(snippet) => { + let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right(); + if snippet.len() > 0 && !snippet.contains('\n') { + Span { hi: BytePos(sp.lo.0 + snippet.len() as u32), ..sp } + } else { + sp + } + } + _ => sp, + } + } + + pub fn def_span(&self, sp: Span) -> Span { + self.span_until_char(sp, '{') + } + pub fn get_filemap(&self, filename: &str) -> Option> { for fm in self.files.borrow().iter() { if filename == fm.name { diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr index ef02250e21cdf..2ef8c830eb2fe 100644 --- a/src/test/ui/resolve/issue-3907-2.stderr +++ b/src/test/ui/resolve/issue-3907-2.stderr @@ -2,7 +2,7 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object --> $DIR/issue-3907-2.rs:20:1 | 20 | fn bar(_x: Foo) {} - | ^^^^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object | = note: method `bar` has no receiver diff --git a/src/test/compile-fail/E0072.rs b/src/test/ui/span/E0072.rs similarity index 84% rename from src/test/compile-fail/E0072.rs rename to src/test/ui/span/E0072.rs index e6de7921b3036..18ade4f1ab68e 100644 --- a/src/test/compile-fail/E0072.rs +++ b/src/test/ui/span/E0072.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct ListNode { //~ ERROR E0072 - //~| NOTE recursive type has infinite size +struct ListNode { head: u8, tail: Option, } diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr new file mode 100644 index 0000000000000..5204390ef9d2a --- /dev/null +++ b/src/test/ui/span/E0072.stderr @@ -0,0 +1,10 @@ +error[E0072]: recursive type `ListNode` has infinite size + --> $DIR/E0072.rs:11:1 + | +11 | struct ListNode { + | ^^^^^^^^^^^^^^^ recursive type has infinite size + | + = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable + +error: aborting due to previous error + diff --git a/src/test/ui/span/multiline-span-E0072.rs b/src/test/ui/span/multiline-span-E0072.rs new file mode 100644 index 0000000000000..323e7fb5a42c0 --- /dev/null +++ b/src/test/ui/span/multiline-span-E0072.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// It should just use the entire body instead of pointing at the next two lines +struct +ListNode +{ + head: u8, + tail: Option, +} + +fn main() { +} diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr new file mode 100644 index 0000000000000..58cdc50230063 --- /dev/null +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -0,0 +1,16 @@ +error[E0072]: recursive type `ListNode` has infinite size + --> $DIR/multiline-span-E0072.rs:12:1 + | +12 | struct + | _^ starting here... +13 | | ListNode +14 | | { +15 | | head: u8, +16 | | tail: Option, +17 | | } + | |_^ ...ending here: recursive type has infinite size + | + = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable + +error: aborting due to previous error + From 0a69bf4cdd01a279f8b99280de950e0083c85725 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 18 Apr 2017 08:57:56 -0700 Subject: [PATCH 2/6] Bump stage0 to fix ARM LLVM There was a serious ARM codegen bug in LLVM that was fixed by #40779, also backported to beta. This updates stage0 to 1.17.0-beta.3 to pick up that change, so ARM can bootstrap natively again. Fixes #41291 cc @arielb1 --- src/stage0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stage0.txt b/src/stage0.txt index 60fbcadf49157..dc6931c1d0bdd 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,4 +12,4 @@ # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was # released on `$date` -rustc: beta-2017-03-21 +rustc: beta-2017-04-05 From cba0c6ad6da735d00819d5a0df3953b3a8ebfe3e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 18 Apr 2017 23:59:25 +0300 Subject: [PATCH 3/6] rustc_trans: do not treat byval as using up registers. --- src/librustc_trans/cabi_x86_64.rs | 6 +++--- .../run-make/extern-fn-struct-passing-abi/test.c | 15 +++++++++++++++ .../run-make/extern-fn-struct-passing-abi/test.rs | 8 ++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index 2daebf5cf3d6b..2cfab7df8b30b 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -229,12 +229,12 @@ pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType }; if in_mem { - // `sret` / `byval` parameter thus one less integer register available - int_regs -= 1; - arg.make_indirect(ccx); if is_arg { arg.attrs.set(ArgAttribute::ByVal); + } else { + // `sret` parameter thus one less integer register available + int_regs -= 1; } } else { // split into sized chunks passed individually diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.c b/src/test/run-make/extern-fn-struct-passing-abi/test.c index 4e09928edc6d1..44a940a17a98a 100644 --- a/src/test/run-make/extern-fn-struct-passing-abi/test.c +++ b/src/test/run-make/extern-fn-struct-passing-abi/test.c @@ -137,6 +137,21 @@ void byval_rect_with_float(int32_t a, int32_t b, float c, int32_t d, assert(s.d == 556); } +// System V x86_64 ABI: +// a, b, d, e, f should be byval pointer (on the stack) +// g passed via register (fixes #41375) +// +// Win64 ABI: +// a, b, d, e, f, g should be byval pointer +void byval_rect_with_many_huge(struct Huge a, struct Huge b, struct Huge c, + struct Huge d, struct Huge e, struct Huge f, + struct Rect g) { + assert(g.a == 123); + assert(g.b == 456); + assert(g.c == 789); + assert(g.d == 420); +} + // System V x86_64 & Win64 ABI: // a, b should be in registers // s should be split across 2 integer registers diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.rs b/src/test/run-make/extern-fn-struct-passing-abi/test.rs index ff845a644b114..aaae7ae4fb49b 100644 --- a/src/test/run-make/extern-fn-struct-passing-abi/test.rs +++ b/src/test/run-make/extern-fn-struct-passing-abi/test.rs @@ -64,6 +64,8 @@ extern { fn byval_rect_with_float(a: i32, b: i32, c: f32, d: i32, e: i32, f: i32, s: Rect); + fn byval_rect_with_many_huge(a: Huge, b: Huge, c: Huge, d: Huge, e: Huge, f: Huge, g: Rect); + fn split_rect(a: i32, b: i32, s: Rect); fn split_rect_floats(a: f32, b: f32, s: FloatRect); @@ -95,6 +97,12 @@ fn main() { byval_many_rect(1, 2, 3, 4, 5, 6, s); byval_rect_floats(1., 2., 3., 4., 5., 6., 7., s, u); byval_rect_with_float(1, 2, 3.0, 4, 5, 6, s); + byval_rect_with_many_huge(v, v, v, v, v, v, Rect { + a: 123, + b: 456, + c: 789, + d: 420 + }); split_rect(1, 2, s); split_rect_floats(1., 2., u); split_rect_with_floats(1, 2, 3.0, 4, 5.0, 6, s); From 295bcdb715871ef3ba0258c75dad885b7315a162 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 13 Apr 2017 02:48:46 -0700 Subject: [PATCH 4/6] Override ToOwned::clone_into for Path and OsStr The only non-overridden one remaining is the CStr impl, which cannot be optimized as doing so would break CString's second invariant. --- src/libstd/ffi/os_str.rs | 18 +++++++++++++++++- src/libstd/lib.rs | 1 + src/libstd/path.rs | 12 ++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index bf3f41b13c184..b90192dd8af24 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -677,7 +677,13 @@ impl Borrow for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for OsStr { type Owned = OsString; - fn to_owned(&self) -> OsString { self.to_os_string() } + fn to_owned(&self) -> OsString { + self.to_os_string() + } + fn clone_into(&self, target: &mut OsString) { + target.clear(); + target.push(self); + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -863,4 +869,14 @@ mod tests { let boxed = >::default(); assert!(boxed.is_empty()); } + + #[test] + fn test_os_str_clone_into() { + let mut os_string = OsString::with_capacity(123); + os_string.push("hello"); + let os_str = OsStr::new("bonjour"); + os_str.clone_into(&mut os_string); + assert_eq!(os_str, os_string); + assert!(os_string.capacity() >= 123); + } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 8de6e1a24f1f2..367779bb701c8 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -311,6 +311,7 @@ #![feature(str_utf16)] #![feature(test, rustc_private)] #![feature(thread_local)] +#![feature(toowned_clone_into)] #![feature(try_from)] #![feature(unboxed_closures)] #![feature(unicode)] diff --git a/src/libstd/path.rs b/src/libstd/path.rs index db446d88900c1..fcbd3705e881f 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1322,6 +1322,9 @@ impl ToOwned for Path { fn to_owned(&self) -> PathBuf { self.to_path_buf() } + fn clone_into(&self, target: &mut PathBuf) { + self.inner.clone_into(&mut target.inner); + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -3722,4 +3725,13 @@ mod tests { assert_eq!(&*boxed, &*path_buf); assert_eq!(&*path_buf, path); } + + #[test] + fn test_clone_into() { + let mut path_buf = PathBuf::from("supercalifragilisticexpialidocious"); + let path = Path::new("short"); + path.clone_into(&mut path_buf); + assert_eq!(path, path_buf); + assert!(path_buf.into_os_string().capacity() >= 15); + } } From aa6c2b1cb73edad3ca1e8068151dd7254a3ebce1 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 18 Apr 2017 15:48:19 -0400 Subject: [PATCH 5/6] propagate obligations during overlap check --- src/librustc/traits/coherence.rs | 8 ++++---- src/test/run-pass/issue-41298.rs | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass/issue-41298.rs diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 383fab3fcd766..a943ef30e534b 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -55,16 +55,15 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, debug!("overlap: b_impl_header={:?}", b_impl_header); // Do `a` and `b` unify? If not, no overlap. - match selcx.infcx().eq_impl_headers(true, + let obligations = match selcx.infcx().eq_impl_headers(true, &ObligationCause::dummy(), &a_impl_header, &b_impl_header) { Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + obligations } Err(_) => return None - } + }; debug!("overlap: unification check succeeded"); @@ -78,6 +77,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, .map(|p| Obligation { cause: ObligationCause::dummy(), recursion_depth: 0, predicate: p }) + .chain(obligations) .find(|o| !selcx.evaluate_obligation(o)); if let Some(failing_obligation) = opt_failing_obligation { diff --git a/src/test/run-pass/issue-41298.rs b/src/test/run-pass/issue-41298.rs new file mode 100644 index 0000000000000..2b9baa746748b --- /dev/null +++ b/src/test/run-pass/issue-41298.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Function { t: T, f: F } + +impl Function R> { fn foo() { } } +impl Function R> { fn bar() { } } + +fn main() { } From 93e10977d8b0ccd2cdc41f30e187e6ebecd3240b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 18 Apr 2017 15:48:32 -0400 Subject: [PATCH 6/6] propagate other obligations that were left out cc #32730 -- I left exactly one instance where I wasn't sure of the right behavior. --- src/librustc/infer/mod.rs | 10 +++++++--- src/librustc/traits/fulfill.rs | 10 ++++++++++ src/librustc/traits/specialize/mod.rs | 7 +++---- src/librustc_driver/test.rs | 6 +++--- src/librustc_typeck/check/compare_method.rs | 7 +++---- src/librustc_typeck/check/dropck.rs | 5 ++--- src/librustc_typeck/lib.rs | 17 ++++++++++++----- 7 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index a1bafe113e415..4d8b31a33cdef 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1597,9 +1597,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // generic so we don't have to do anything quite this // terrible. let trace = TypeTrace::dummy(self.tcx); - self.equate(true, trace, a, b).map(|InferOk { obligations, .. }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.equate(true, trace, a, b).map(|InferOk { obligations: _, .. }| { + // We can intentionally ignore obligations here, since + // this is part of a simple test for general + // "equatability". However, it's not entirely clear + // that we *ought* to be, perhaps a better thing would + // be to use a mini-fulfillment context or something + // like that. }) }) } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index d771be077ae3a..d49affa3e872c 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -184,6 +184,16 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { }); } + pub fn register_predicate_obligations(&mut self, + infcx: &InferCtxt<'a, 'gcx, 'tcx>, + obligations: Vec>) + { + for obligation in obligations { + self.register_predicate_obligation(infcx, obligation); + } + } + + pub fn region_obligations(&self, body_id: ast::NodeId) -> &[RegionObligation<'tcx>] diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 92b7c736d42fd..5f02688be34bc 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -218,7 +218,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, -> Result<&'tcx Substs<'tcx>, ()> { let selcx = &mut SelectionContext::new(&infcx); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); - let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx, + let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx, target_impl, target_substs); @@ -227,9 +227,8 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, &ObligationCause::dummy(), source_trait_ref, target_trait_ref) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()) + Ok(InferOk { obligations: o, .. }) => { + obligations.extend(o); } Err(_) => { debug!("fulfill_implication: {:?} does not unify with {:?}", diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 44e291a44c777..7447fba3038ea 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -376,7 +376,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { match self.sub(t1, t2) { Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) once obligations are being propagated, assert the right thing. + // None of these tests should require nested obligations: assert!(obligations.is_empty()); } Err(ref e) => { @@ -400,7 +400,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) { match self.lub(t1, t2) { Ok(InferOk { obligations, value: t }) => { - // FIXME(#32730) once obligations are being propagated, assert the right thing. + // None of these tests should require nested obligations: assert!(obligations.is_empty()); self.assert_eq(t, t_lub); @@ -415,7 +415,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { match self.glb(t1, t2) { Err(e) => panic!("unexpected error computing LUB: {:?}", e), Ok(InferOk { obligations, value: t }) => { - // FIXME(#32730) once obligations are being propagated, assert the right thing. + // None of these tests should require nested obligations: assert!(obligations.is_empty()); self.assert_eq(t, t_glb); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 8a6853461a5e8..ae70049cc5bdc 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -294,10 +294,9 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("compare_impl_method: trait_fty={:?}", trait_fty); let sub_result = infcx.sub_types(false, &cause, impl_fty, trait_fty) - .map(|InferOk { obligations, .. }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - }); + .map(|InferOk { obligations, .. }| { + inh.register_predicates(obligations); + }); if let Err(terr) = sub_result { debug!("sub_types failed: impl ty {:?}, trait ty {:?}", diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 9f41373dab1b7..b71ff58ccec33 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -82,7 +82,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id); - tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|infcx| { + tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| { let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); @@ -97,8 +97,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id); match infcx.eq_types(true, cause, named_type, fresh_impl_self_ty) { Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + fulfillment_cx.register_predicate_obligations(infcx, obligations); } Err(_) => { let item_span = tcx.hir.span(self_type_node_id); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index e9a606dc0ab1d..0754b52cf280a 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -109,7 +109,7 @@ use rustc::infer::InferOk; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::Providers; -use rustc::traits::{ObligationCause, ObligationCauseCode, Reveal}; +use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal}; use session::config; use util::common::time; @@ -153,15 +153,22 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| { + tcx.infer_ctxt((), Reveal::UserFacing).enter(|ref infcx| { + let mut fulfill_cx = FulfillmentContext::new(); match infcx.eq_types(false, &cause, expected, actual) { Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - true + fulfill_cx.register_predicate_obligations(infcx, obligations); } Err(err) => { infcx.report_mismatched_types(cause, expected, actual, err).emit(); + return false; + } + } + + match fulfill_cx.select_all_or_error(infcx) { + Ok(()) => true, + Err(errors) => { + infcx.report_fulfillment_errors(&errors); false } }