diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 2978921fc620..dae5ba14bfb5 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -399,7 +399,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { // For backwards compatibility we apply numeric fallback here. This means that in: // `let x = 100; x as u8;`, we infer `x` to `i32` rather than `u8`. if self.expr_ty.is_ty_infer() { - fcx.apply_fallback_if_possible(self.expr_ty, Fallback::Numeric); + fcx.fallback_if_possible(self.expr_ty, Fallback::Numeric); self.expr_ty = fcx.structurally_resolved_type(self.span, self.expr_ty); } self.cast_ty = fcx.structurally_resolved_type(self.span, self.cast_ty); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 57e40ec19af7..b1645ed92283 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -858,9 +858,19 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fcx }; - fcx.select_obligations_where_possible(); - fcx.closure_analyze(body); fcx.check_casts(); + + // All type checking constraints were added, try to fallback unsolved variables. + fcx.select_obligations_where_possible(); + for ty in &fcx.unsolved_variables() { + fcx.fallback_if_possible(ty, Fallback::Full); + } + fcx.select_obligations_where_possible(); + + // Closure and generater analysis may run after fallback + // because they doen't constrain other type variables. + fcx.closure_analyze(body); + assert!(fcx.deferred_call_resolutions.borrow().is_empty()); fcx.resolve_generator_interiors(def_id); fcx.select_all_obligations_or_error(); @@ -2137,9 +2147,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Non-numerics get replaced with ! or () (depending on whether // feature(never_type) is enabled), unconstrained ints with i32, // unconstrained floats with f64. - // Defaulting inference variables becomes very dubious if we have - // encountered type-checking errors. In that case, fallback to TyError. - fn apply_fallback_if_possible(&self, ty: Ty<'tcx>, fallback: Fallback) { + // Fallback becomes very dubious if we have encountered type-checking errors. + // In that case, fallback to TyError. + fn fallback_if_possible(&self, ty: Ty<'tcx>, fallback: Fallback) { use rustc::ty::error::UnconstrainedNumeric::Neither; use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; @@ -2162,22 +2172,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn select_all_obligations_or_error(&self) { debug!("select_all_obligations_or_error"); - - // upvar inference should have ensured that all deferred call - // resolutions are handled by now. - assert!(self.deferred_call_resolutions.borrow().is_empty()); - - self.select_obligations_where_possible(); - - for ty in &self.unsolved_variables() { - self.apply_fallback_if_possible(ty, Fallback::Full); - } - - let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); - - match fulfillment_cx.select_all_or_error(self) { - Ok(()) => { } - Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); } + if let Err(errors) = self.fulfillment_cx.borrow_mut().select_all_or_error(&self) { + self.report_fulfillment_errors(&errors, self.inh.body_id); } } diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index dca9ab1b5415..f4beb44b82dc 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -1,13 +1,13 @@ -error[E0277]: the trait bound `std::cell::UnsafeCell<{integer}>: std::panic::RefUnwindSafe` is not satisfied in `std::cell::Cell<{integer}>` +error[E0277]: the trait bound `std::cell::UnsafeCell: std::panic::RefUnwindSafe` is not satisfied in `std::cell::Cell` --> $DIR/interior-mutability.rs:15:5 | 15 | catch_unwind(|| { x.set(23); }); //~ ERROR the trait bound - | ^^^^^^^^^^^^ the type std::cell::UnsafeCell<{integer}> may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | ^^^^^^^^^^^^ the type std::cell::UnsafeCell may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `std::cell::Cell<{integer}>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<{integer}>` - = note: required because it appears within the type `std::cell::Cell<{integer}>` - = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::Cell<{integer}>` - = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:15:18: 15:35 x:&std::cell::Cell<{integer}>]` + = help: within `std::cell::Cell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` + = note: required because it appears within the type `std::cell::Cell` + = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::Cell` + = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:15:18: 15:35 x:&std::cell::Cell]` = note: required by `std::panic::catch_unwind` error: aborting due to previous error