diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 71ae54bedce..1a97fc505fd 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -561,17 +561,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We just want to check sizedness, so instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. - let arg_span = args.get(i).map(|a| a.span); - let span = arg_span.unwrap_or(expr.span); + let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); let input = self.replace_bound_vars_with_fresh_vars( span, infer::LateBoundRegionConversionTime::FnCall, fn_sig.input(i), ); - self.require_type_is_sized( - self.normalize_associated_types_in(span, input), + self.require_type_is_sized_deferred( + input, span, - traits::SizedArgumentType(arg_span), + traits::SizedArgumentType(None), ); } } @@ -586,11 +585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::LateBoundRegionConversionTime::FnCall, fn_sig.output(), ); - self.require_type_is_sized( - self.normalize_associated_types_in(expr.span, output), - expr.span, - traits::SizedReturnType, - ); + self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); } // We always require that the type provided as the value for diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 20d25d508d2..1f47aabefde 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -442,6 +442,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + pub fn require_type_is_sized_deferred( + &self, + ty: Ty<'tcx>, + span: Span, + code: traits::ObligationCauseCode<'tcx>, + ) { + if !ty.references_error() { + self.deferred_sized_obligations.borrow_mut().push((ty, span, code)); + } + } + pub fn register_bound( &self, ty: Ty<'tcx>, diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index f3115fc5c02..cd152eb97f1 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -35,6 +35,11 @@ pub struct Inherited<'a, 'tcx> { pub(super) fulfillment_cx: RefCell>>, + // Some additional `Sized` obligations badly affect type inference. + // These obligations are added in a later stage of typeck. + pub(super) deferred_sized_obligations: + RefCell, Span, traits::ObligationCauseCode<'tcx>)>>, + // When we process a call like `c()` where `c` is a closure type, // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or // `FnOnce` closure. In that case, we defer full resolution of the @@ -112,6 +117,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { infcx, fulfillment_cx: RefCell::new(>::new(tcx)), locals: RefCell::new(Default::default()), + deferred_sized_obligations: RefCell::new(Vec::new()), deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), deferred_transmute_checks: RefCell::new(Vec::new()), diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index fb675212e3f..07c202859cc 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -466,6 +466,11 @@ fn typeck_with_fallback<'tcx>( fcx.resolve_rvalue_scopes(def_id.to_def_id()); fcx.resolve_generator_interiors(def_id.to_def_id()); + for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { + let ty = fcx.normalize_ty(span, ty); + fcx.require_type_is_sized(ty, span, code); + } + fcx.select_all_obligations_or_error(); if !fcx.infcx.is_tainted_by_errors() { diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-1.rs b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs index 53358b183cb..5ff7b19d894 100644 --- a/src/test/incremental/const-generics/hash-tyvid-regression-1.rs +++ b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs @@ -9,6 +9,7 @@ where use std::convert::TryFrom; <[T; N.get()]>::try_from(()) //~^ error: the trait bound + //~| error: the trait bound //~| error: mismatched types } diff --git a/src/test/ui/associated-types/associated-types-path-2.rs b/src/test/ui/associated-types/associated-types-path-2.rs index c993e1d2720..00066efccb8 100644 --- a/src/test/ui/associated-types/associated-types-path-2.rs +++ b/src/test/ui/associated-types/associated-types-path-2.rs @@ -29,12 +29,14 @@ pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR `u32: Foo` is not satisfied //~| ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f1_uint_int() { f1(2u32, 4i32); //~^ ERROR `u32: Foo` is not satisfied //~| ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied } pub fn f2_int() { diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr index 5edd5c864e1..206f4902410 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -31,6 +31,14 @@ note: required by a bound in `f1` LL | pub fn f1(a: T, x: T::A) {} | ^^^ required by this bound in `f1` +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:29:5 + | +LL | f1(2u32, 4u32); + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32` + | + = help: the trait `Foo` is implemented for `i32` + error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:29:14 | @@ -40,7 +48,7 @@ LL | f1(2u32, 4u32); = help: the trait `Foo` is implemented for `i32` error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:35:8 + --> $DIR/associated-types-path-2.rs:36:8 | LL | f1(2u32, 4i32); | -- ^^^^ the trait `Foo` is not implemented for `u32` @@ -55,7 +63,15 @@ LL | pub fn f1(a: T, x: T::A) {} | ^^^ required by this bound in `f1` error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:35:14 + --> $DIR/associated-types-path-2.rs:36:5 + | +LL | f1(2u32, 4i32); + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32` + | + = help: the trait `Foo` is implemented for `i32` + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:36:14 | LL | f1(2u32, 4i32); | ^^^^ the trait `Foo` is not implemented for `u32` @@ -63,7 +79,7 @@ LL | f1(2u32, 4i32); = help: the trait `Foo` is implemented for `i32` error[E0308]: mismatched types - --> $DIR/associated-types-path-2.rs:41:18 + --> $DIR/associated-types-path-2.rs:43:18 | LL | let _: i32 = f2(2i32); | --- ^^^^^^^^ expected `i32`, found `u32` @@ -75,7 +91,7 @@ help: you can convert a `u32` to an `i32` and panic if the converted value doesn LL | let _: i32 = f2(2i32).try_into().unwrap(); | ++++++++++++++++++++ -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr index b7757740d9e..0f7520ef7f8 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr +++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr @@ -18,11 +18,8 @@ LL | foo(*x); | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | foo(&*x); - | + error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/issue-28098.rs b/src/test/ui/iterators/issue-28098.rs index c4addaccefc..80c77edae9e 100644 --- a/src/test/ui/iterators/issue-28098.rs +++ b/src/test/ui/iterators/issue-28098.rs @@ -1,12 +1,15 @@ fn main() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator other() } @@ -16,9 +19,12 @@ pub fn other() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator diff --git a/src/test/ui/iterators/issue-28098.stderr b/src/test/ui/iterators/issue-28098.stderr index 53b610c1723..3256e57d436 100644 --- a/src/test/ui/iterators/issue-28098.stderr +++ b/src/test/ui/iterators/issue-28098.stderr @@ -8,8 +8,16 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:5:14 + --> $DIR/issue-28098.rs:7:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -18,7 +26,7 @@ LL | for _ in false {} = note: required for `bool` to implement `IntoIterator` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:8:28 + --> $DIR/issue-28098.rs:10:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -28,12 +36,18 @@ LL | let _ = Iterator::next(&mut ()); = help: the trait `Iterator` is not implemented for `()` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:17:28 + --> $DIR/issue-28098.rs:10:13 | LL | let _ = Iterator::next(&mut ()); - | -------------- ^^^^^^^ `()` is not an iterator - | | - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` @@ -47,8 +61,34 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:25:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:25:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:23:14 + --> $DIR/issue-28098.rs:29:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator @@ -56,6 +96,14 @@ LL | for _ in false {} = help: the trait `Iterator` is not implemented for `bool` = note: required for `bool` to implement `IntoIterator` -error: aborting due to 6 previous errors +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs index 79c40f650db..a32fd456623 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.rs +++ b/src/test/ui/on-unimplemented/multiple-impls.rs @@ -32,8 +32,14 @@ impl Index> for [i32] { fn main() { Index::index(&[] as &[i32], 2u32); //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 } diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index d47a398412f..d628b159a66 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -11,8 +11,19 @@ LL | Index::index(&[] as &[i32], 2u32); <[i32] as Index>> <[i32] as Index>> +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:33:5 + | +LL | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:35:33 + --> $DIR/multiple-impls.rs:37:33 | LL | Index::index(&[] as &[i32], Foo(2u32)); | ------------ ^^^^^^^^^ on impl for Foo @@ -24,8 +35,19 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); <[i32] as Index>> <[i32] as Index>> +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:37:5 + | +LL | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:37:33 + --> $DIR/multiple-impls.rs:41:33 | LL | Index::index(&[] as &[i32], Bar(2u32)); | ------------ ^^^^^^^^^ on impl for Bar @@ -37,6 +59,50 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); <[i32] as Index>> <[i32] as Index>> -error: aborting due to 3 previous errors +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:41:5 + | +LL | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:33:5 + | +LL | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:37:5 + | +LL | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:41:5 + | +LL | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs index b03e1f7c6a8..d0537810ce1 100644 --- a/src/test/ui/on-unimplemented/on-impl.rs +++ b/src/test/ui/on-unimplemented/on-impl.rs @@ -21,4 +21,6 @@ impl Index for [i32] { fn main() { Index::::index(&[1, 2, 3] as &[i32], 2u32); //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 } diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index 01315b85409..2253c5992a6 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -9,6 +9,24 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); = help: the trait `Index` is not implemented for `[i32]` = help: the trait `Index` is implemented for `[i32]` -error: aborting due to previous error +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:22:5 + | +LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the trait `Index` is implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:22:5 + | +LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the trait `Index` is implemented for `[i32]` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs index 939b3c5223c..ec86213f862 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.rs @@ -3,6 +3,7 @@ use std::ops::Add; fn main() { >::add(1, 2); //~^ ERROR cannot add `u32` to `i32` + //~| ERROR cannot add `u32` to `i32` >::add(1u32, 2); //~^ ERROR mismatched types >::add(1, 2u32); diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index f08c81bc1e9..eaab6ff3d9a 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -19,7 +19,7 @@ LL | >::add(1, 2); and 48 others error[E0308]: mismatched types - --> $DIR/ufcs-qpath-self-mismatch.rs:6:28 + --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 | LL | >::add(1u32, 2); | ---------------------- ^^^^ expected `i32`, found `u32` @@ -37,7 +37,7 @@ LL | >::add(1i32, 2); | ~~~ error[E0308]: mismatched types - --> $DIR/ufcs-qpath-self-mismatch.rs:8:31 + --> $DIR/ufcs-qpath-self-mismatch.rs:9:31 | LL | >::add(1, 2u32); | ---------------------- ^^^^ expected `i32`, found `u32` @@ -54,7 +54,25 @@ help: change the type of the numeric literal from `u32` to `i32` LL | >::add(1, 2i32); | ~~~ -error: aborting due to 3 previous errors +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 + | +LL | >::add(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | + = help: the trait `Add` is not implemented for `i32` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> + and 48 others + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr index f5491552a45..71bbdf5dec7 100644 --- a/src/test/ui/unsized/issue-30355.stderr +++ b/src/test/ui/unsized/issue-30355.stderr @@ -5,11 +5,8 @@ LL | &X(*Y) | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | &X(&*Y) - | + error: aborting due to previous error