diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index bc157d6feea..631f7a740c4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -393,7 +393,7 @@ fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { self.expr_ty = fcx.resolved_type(self.span, self.expr_ty); - self.cast_ty = fcx.resolved_type(self.span, self.cast_ty); + self.cast_ty = fcx.structurally_resolved_type(self.span, self.cast_ty); debug!("check_cast({}, {:?} as {:?})", self.expr.id, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 666b8e06522..610510c5c74 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2127,23 +2127,23 @@ fn resolve_generator_interiors(&self, def_id: DefId) { } } - fn apply_diverging_fallback_to_type(&self, ty: Ty<'tcx>) { - assert!(ty.is_ty_infer()); - if self.type_var_diverges(ty) { - debug!("default_type_parameters: defaulting `{:?}` to `!` because it diverges", ty); - self.demand_eqtype(syntax_pos::DUMMY_SP, ty, self.tcx.mk_diverging_default()); - } - } - - fn apply_numeric_fallback_to_type(&self, ty: Ty<'tcx>) { + // Tries to apply a fallback to `ty` if it is an unsolved variable. + // 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>) { use rustc::ty::error::UnconstrainedNumeric::Neither; use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; assert!(ty.is_ty_infer()); let fallback = match self.type_is_unconstrained_numeric(ty) { + _ if self.is_tainted_by_errors() => self.tcx().types.err, UnconstrainedInt => self.tcx.types.i32, UnconstrainedFloat => self.tcx.types.f64, - Neither => return, + Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(), + Neither => return }; debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback); self.demand_eqtype(syntax_pos::DUMMY_SP, ty, fallback); @@ -2158,21 +2158,8 @@ fn select_all_obligations_or_error(&self) { self.select_obligations_where_possible(); - // Apply fallbacks to unsolved variables. - // Non-numerics get replaced with ! or () (depending on whether - // feature(never_type) is enabled), unconstrained ints with i32, - // unconstrained floats with f64. for ty in &self.unsolved_variables() { - if self.is_tainted_by_errors() { - // Defaulting inference variables becomes very dubious if we have - // encountered type-checking errors. In that case, - // just resolve all uninstanted type variables to TyError. - debug!("default_type_parameters: defaulting `{:?}` to error", ty); - self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx().types.err); - } else { - self.apply_diverging_fallback_to_type(ty); - self.apply_numeric_fallback_to_type(ty); - } + self.apply_fallback_if_possible(ty); } let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); @@ -4942,18 +4929,11 @@ fn check_impl_trait(&self, // If no resolution is possible, then an error is reported. // Numeric inference variables may be left unresolved. pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - let mut ty = self.resolve_type_vars_with_obligations(ty); + let ty = self.resolve_type_vars_with_obligations(ty); if !ty.is_ty_var() { ty } else { - // Try divering fallback. - self.apply_diverging_fallback_to_type(ty); - ty = self.resolve_type_vars_with_obligations(ty); - if !ty.is_ty_var() { - ty - } else { // Fallback failed, error. - self.must_be_known_in_context(sp, ty) - } + self.must_be_known_in_context(sp, ty) } } @@ -4963,9 +4943,7 @@ pub fn resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { if !ty.is_ty_infer() { return ty; } else { - // Try diverging or numeric fallback. - self.apply_diverging_fallback_to_type(ty); - self.apply_numeric_fallback_to_type(ty); + self.apply_fallback_if_possible(ty); ty = self.resolve_type_vars_with_obligations(ty); if !ty.is_ty_infer() { ty diff --git a/src/test/ui/mismatched_types/issue-26480.rs b/src/test/ui/mismatched_types/issue-26480-1.rs similarity index 91% rename from src/test/ui/mismatched_types/issue-26480.rs rename to src/test/ui/mismatched_types/issue-26480-1.rs index 33c5e74fafa..36a30ccb0fc 100644 --- a/src/test/ui/mismatched_types/issue-26480.rs +++ b/src/test/ui/mismatched_types/issue-26480-1.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: --error-format=human extern { fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64; @@ -28,12 +29,7 @@ macro_rules! write { }} } -macro_rules! cast { - ($x:expr) => ($x as ()) //~ ERROR non-primitive cast -} - fn main() { let hello = ['H', 'e', 'y']; write!(hello); - cast!(2); } diff --git a/src/test/ui/mismatched_types/issue-26480-1.stderr b/src/test/ui/mismatched_types/issue-26480-1.stderr new file mode 100644 index 00000000000..326b427b0fb --- /dev/null +++ b/src/test/ui/mismatched_types/issue-26480-1.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-26480-1.rs:27:19 + | +27 | $arr.len() * size_of($arr[0])); //~ ERROR mismatched types + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize +... +34 | write!(hello); + | -------------- in this macro invocation + +error: aborting due to previous error + diff --git a/src/test/ui/mismatched_types/issue-26480-2.rs b/src/test/ui/mismatched_types/issue-26480-2.rs new file mode 100644 index 00000000000..7015e5909e9 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-26480-2.rs @@ -0,0 +1,18 @@ +// 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. +// compile-flags: --error-format=human + +macro_rules! cast { + ($x:expr) => ($x as ()) //~ ERROR non-primitive cast +} + +fn main() { + cast!(2); +} diff --git a/src/test/ui/mismatched_types/issue-26480-2.stderr b/src/test/ui/mismatched_types/issue-26480-2.stderr new file mode 100644 index 00000000000..3f6dcccdedb --- /dev/null +++ b/src/test/ui/mismatched_types/issue-26480-2.stderr @@ -0,0 +1,13 @@ +error[E0605]: non-primitive cast: `i32` as `()` + --> $DIR/issue-26480-2.rs:13:19 + | +13 | ($x:expr) => ($x as ()) //~ ERROR non-primitive cast + | ^^^^^^^^ +... +17 | cast!(2); + | --------- in this macro invocation + | + = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait + +error: aborting due to previous error + diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index 1b056486ad9..27698c864c3 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -7,16 +7,5 @@ error[E0308]: mismatched types 37 | write!(hello); | -------------- in this macro invocation -error[E0605]: non-primitive cast: `i32` as `()` - --> $DIR/issue-26480.rs:32:19 - | -32 | ($x:expr) => ($x as ()) //~ ERROR non-primitive cast - | ^^^^^^^^ -... -38 | cast!(2); - | --------- in this macro invocation - | - = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait - -error: aborting due to 2 previous errors +error: aborting due to previous error