diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 6e3a4cae2f62b..51b2194978806 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -348,50 +348,18 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Direct(_) => { // ABI-compatible Rust types have the same `layout.abi` (up to validity ranges), // and for Scalar ABIs the LLVM type is fully determined by `layout.abi`, - // guarnateeing that we generate ABI-compatible LLVM IR. Things get tricky for - // aggregates... - if matches!(arg.layout.abi, abi::Abi::Aggregate { .. }) { - assert!( - arg.layout.is_sized(), - "`PassMode::Direct` for unsized type: {}", - arg.layout.ty - ); - // This really shouldn't happen, since `immediate_llvm_type` will use - // `layout.fields` to turn this Rust type into an LLVM type. This means all - // sorts of Rust type details leak into the ABI. However wasm sadly *does* - // currently use this mode so we have to allow it -- but we absolutely - // shouldn't let any more targets do that. - // (Also see .) - // - // The unstable abi `PtxKernel` also uses Direct for now. - // It needs to switch to something else before stabilization can happen. - // (See issue: https://github.com/rust-lang/rust/issues/117271) - assert!( - matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") - || self.conv == Conv::PtxKernel, - "`PassMode::Direct` for aggregates only allowed on wasm and `extern \"ptx-kernel\"` fns\nProblematic type: {:#?}", - arg.layout, - ); - } + // guarnateeing that we generate ABI-compatible LLVM IR. arg.layout.immediate_llvm_type(cx) } PassMode::Pair(..) => { // ABI-compatible Rust types have the same `layout.abi` (up to validity ranges), // so for ScalarPair we can easily be sure that we are generating ABI-compatible // LLVM IR. - assert!( - matches!(arg.layout.abi, abi::Abi::ScalarPair(..)), - "PassMode::Pair for type {}", - arg.layout.ty - ); llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 0, true)); llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack } => { - // `Indirect` with metadata is only for unsized types, and doesn't work with - // on-stack passing. - assert!(arg.layout.is_unsized() && !on_stack); + PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { // Construct the type of a (wide) pointer to `ty`, and pass its two fields. // Any two ABI-compatible unsized types have the same metadata type and // moreover the same metadata value leads to the same dynamic size and @@ -402,13 +370,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => { - assert!(arg.layout.is_sized()); - cx.type_ptr() - } + PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => cx.type_ptr(), PassMode::Cast { cast, pad_i32 } => { - // `Cast` means "transmute to `CastType`"; that only makes sense for sized types. - assert!(arg.layout.is_sized()); // add padding if *pad_i32 { llargument_tys.push(Reg::i32().llvm_type(cx)); diff --git a/compiler/rustc_error_codes/src/error_codes/E0178.md b/compiler/rustc_error_codes/src/error_codes/E0178.md index 0c6f918632f47..9e4e6bf8a3c8b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0178.md +++ b/compiler/rustc_error_codes/src/error_codes/E0178.md @@ -8,7 +8,6 @@ trait Foo {} struct Bar<'a> { x: &'a Foo + 'a, // error! y: &'a mut Foo + 'a, // error! - z: fn() -> Foo + 'a, // error! } ``` @@ -21,7 +20,6 @@ trait Foo {} struct Bar<'a> { x: &'a (Foo + 'a), // ok! y: &'a mut (Foo + 'a), // ok! - z: fn() -> (Foo + 'a), // ok! } ``` diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3f31ce7aa58b7..0668a63a38a3e 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1509,6 +1509,7 @@ fn check_fn_or_method<'tcx>( let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None; let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 }); // Check that the argument is a tuple and is sized + // FIXME: move this to WF check? Currently it is duplicated here and in `confirm_builtin_call` in callee.rs. if let Some(ty) = inputs.next() { wfcx.register_bound( ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall), diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index ca7679cfba06e..795079225caaf 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -13,6 +13,9 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { diagnostic_hir_wf_check, ..*providers }; } +/// HIR-based well-formedness check, for diagnostics only. +/// This is run after there was a WF error, to try get a better message pointing out what went wrong +/// here. // Ideally, this would be in `rustc_trait_selection`, but we // need access to `ItemCtxt` fn diagnostic_hir_wf_check<'tcx>( diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 6b6d1574b2bf6..1e203941e34b1 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -458,6 +458,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if fn_sig.abi == abi::Abi::RustCall { + // FIXME: move this to WF check? Currently it is duplicated here and in `check_fn_or_method` in wfcheck.rs. let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span); if let Some(ty) = fn_sig.inputs().last().copied() { self.register_bound( diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 14cd3881a068d..ddbc3a2c8d4fe 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -97,7 +97,10 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.check_pat_top(¶m.pat, param_ty, ty_span, None, None); // Check that argument is Sized. - if !params_can_be_unsized { + // FIXME: can we share this (and the return type check below) with WF-checking on function + // signatures? However, here we have much better spans available than if we fire an + // obligation for our signature to be well-formed. + if !params_can_be_unsized || !fn_sig.abi.supports_unsized_args() { fcx.require_type_is_sized( param_ty, param.pat.span, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index be225ceb84321..353220407f87d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -503,6 +503,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1 } + /// Called for any way that a path is mentioned in an expression. + /// If the path is used in a function call, `args` has the arguments, otherwise it is empty. pub(crate) fn check_expr_path( &self, qpath: &'tcx hir::QPath<'tcx>, diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs index d1efe97769925..df9a99c280be6 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/abi/call/x86_64.rs @@ -153,9 +153,9 @@ fn reg_component(cls: &[Option], i: &mut usize, size: Size) -> Option], size: Size) -> Option { +fn cast_target(cls: &[Option], size: Size) -> CastTarget { let mut i = 0; - let lo = reg_component(cls, &mut i, size)?; + let lo = reg_component(cls, &mut i, size).unwrap(); let offset = Size::from_bytes(8) * (i as u64); let mut target = CastTarget::from(lo); if size > offset { @@ -164,7 +164,7 @@ fn cast_target(cls: &[Option], size: Size) -> Option { } } assert_eq!(reg_component(cls, &mut i, Size::ZERO), None); - Some(target) + target } const MAX_INT_REGS: usize = 6; // RDI, RSI, RDX, RCX, R8, R9 @@ -227,9 +227,7 @@ where // split into sized chunks passed individually if arg.layout.is_aggregate() { let size = arg.layout.size; - if let Some(cast_target) = cast_target(cls, size) { - arg.cast_to(cast_target); - } + arg.cast_to(cast_target(cls, size)); } else { arg.extend_integer_width_to(32); } diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index 4c1f0c01a0411..c8a6dd6a45478 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -86,6 +86,15 @@ impl Abi { _ => false, } } + + /// Whether this ABI can in principle support unsized arguments. + /// There might be further restrictions such as nightly feature flags! + pub fn supports_unsized_args(self) -> bool { + match self { + Self::Rust | Self::RustCall | Self::RustIntrinsic | Self::PlatformIntrinsic => true, + _ => false, + } + } } #[derive(Copy, Clone)] diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 31da437f2e90e..e67fd546e93e2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1863,7 +1863,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } - let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(obligation.cause.body_id)); + let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { + return false; + }; + let body = self.tcx.hir().body(body); let mut visitor = ReturnsVisitor::default(); visitor.visit_body(&body); @@ -1922,15 +1925,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Point at all the `return`s in the function as they have failed trait bounds. let mut visitor = ReturnsVisitor::default(); visitor.visit_body(&body); - let typeck_results = self.typeck_results.as_ref().unwrap(); - for expr in &visitor.returns { - if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) { - let ty = self.resolve_vars_if_possible(returned_ty); - if ty.references_error() { - // don't print out the [type error] here - err.delay_as_bug(); - } else { - err.span_label(expr.span, format!("this returned value is of type `{ty}`")); + if let Some(typeck_results) = self.typeck_results.as_ref() { + for expr in &visitor.returns { + if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) { + let ty = self.resolve_vars_if_possible(returned_ty); + if ty.references_error() { + // don't print out the [type error] here + err.delay_as_bug(); + } else { + err.span_label( + expr.span, + format!("this returned value is of type `{ty}`"), + ); + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fe5b625e4836d..240e3a63fd2af 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -727,9 +727,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.out.extend(obligations); } - ty::FnPtr(_) => { - // let the loop iterate into the argument/return - // types appearing in the fn signature + ty::FnPtr(fn_sig) => { + // The loop iterates into the argument/return types appearing in the fn + // signature, but we need to do some extra checks. + self.compute_fn_sig_obligations(fn_sig) } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { @@ -806,6 +807,22 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } + /// Add the obligations for this signature to be well-formed to `out`. + fn compute_fn_sig_obligations(&mut self, sig: ty::PolyFnSig<'tcx>) { + // The return type must always be sized. + // FIXME(RalfJung): is skip_binder right? It's what the type walker used in `compute` also does. + self.require_sized(sig.skip_binder().output(), traits::SizedReturnType); + // For non-Rust ABIs, the argument type must always be sized. + // FIXME(RalfJung): we don't do the Rust ABI check here, since that depends on feature gates + // and it's not clear to me whether WF depending on feature gates (which can differ across + // crates) is possible or not. + if !sig.skip_binder().abi.supports_unsized_args() { + for &arg in sig.skip_binder().inputs() { + self.require_sized(arg, traits::SizedArgumentType(None)); + } + } + } + #[instrument(level = "debug", skip(self))] fn nominal_obligations( &mut self, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index fcf6626bbf05e..40a9497b73371 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -327,6 +327,74 @@ fn adjust_for_rust_scalar<'tcx>( } } +/// Ensure that the ABI makes basic sense. +fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) { + fn fn_arg_sanity_check<'tcx>( + cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + arg: &ArgAbi<'tcx, Ty<'tcx>>, + ) { + match &arg.mode { + PassMode::Ignore => {} + PassMode::Direct(_) => { + // Here the Rust type is used to determine the actual ABI, so we have to be very + // careful. Scalar/ScalarPair is fine, since backends will generally use + // `layout.abi` and ignore everything else. We should just reject `Aggregate` + // entirely here, but some targets need to be fixed first. + if matches!(arg.layout.abi, Abi::Aggregate { .. }) { + assert!( + arg.layout.is_sized(), + "`PassMode::Direct` for unsized type in ABI: {:#?}", + fn_abi + ); + // This really shouldn't happen, since `immediate_llvm_type` will use + // `layout.fields` to turn this Rust type into an LLVM type. This means all + // sorts of Rust type details leak into the ABI. However wasm sadly *does* + // currently use this mode so we have to allow it -- but we absolutely + // shouldn't let any more targets do that. + // (Also see .) + // + // The unstable abi `PtxKernel` also uses Direct for now. + // It needs to switch to something else before stabilization can happen. + // (See issue: https://github.com/rust-lang/rust/issues/117271) + assert!( + matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") + || fn_abi.conv == Conv::PtxKernel, + "`PassMode::Direct` for aggregates only allowed on wasm and `extern \"ptx-kernel\"` fns\nProblematic type: {:#?}", + arg.layout, + ); + } + } + PassMode::Pair(_, _) => { + // Similar to `Direct`, we need to make sure that backends use `layout.abi` and + // ignore the rest of the layout. + assert!( + matches!(arg.layout.abi, Abi::ScalarPair(..)), + "PassMode::Pair for type {}", + arg.layout.ty + ); + } + PassMode::Cast { .. } => { + // `Cast` means "transmute to `CastType`"; that only makes sense for sized types. + assert!(arg.layout.is_sized()); + } + PassMode::Indirect { meta_attrs: None, .. } => { + // No metadata, must be sized. + assert!(arg.layout.is_sized()); + } + PassMode::Indirect { meta_attrs: Some(_), on_stack, .. } => { + // With metadata. Must be unsized and not on the stack. + assert!(arg.layout.is_unsized() && !on_stack); + } + } + } + + for arg in fn_abi.args.iter() { + fn_arg_sanity_check(cx, fn_abi, arg); + } + fn_arg_sanity_check(cx, fn_abi, &fn_abi.ret); +} + // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) // arguments of this method, into a separate `struct`. #[tracing::instrument(level = "debug", skip(cx, caller_location, fn_def_id, force_thin_self_ptr))] @@ -453,6 +521,7 @@ fn fn_abi_new_uncached<'tcx>( }; fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id)?; debug!("fn_abi_new_uncached = {:?}", fn_abi); + fn_abi_sanity_check(cx, &fn_abi); Ok(cx.tcx.arena.alloc(fn_abi)) } diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 0cdf229711ad0..008a28a1c3732 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -37,9 +37,11 @@ // revisions: wasi //[wasi] compile-flags: --target wasm32-wasi //[wasi] needs-llvm-components: webassembly -// revisions: nvptx64 -//[nvptx64] compile-flags: --target nvptx64-nvidia-cuda -//[nvptx64] needs-llvm-components: nvptx +// FIXME: disabled on nvptx64 since the target ABI fails the sanity check +/* revisions: nvptx64 + [nvptx64] compile-flags: --target nvptx64-nvidia-cuda + [nvptx64] needs-llvm-components: nvptx +*/ #![feature(rustc_attrs, unsized_fn_params, transparent_unions)] #![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)] #![allow(unused, improper_ctypes_definitions, internal_features)] @@ -307,19 +309,30 @@ mod arrays { } // Some tests with unsized types (not all wrappers are compatible with that). +macro_rules! assert_abi_compatible_unsized { + ($name:ident, $t1:ty, $t2:ty) => { + mod $name { + use super::*; + // Declaring a `type` doesn't even check well-formedness, so we also declare a function. + fn check_wf(_x: $t1, _y: $t2) {} + // Can only test arguments and only the Rust ABI, since it's unsized. + #[rustc_abi(assert_eq)] + type TestRust = (fn($t1), fn($t2)); + } + }; +} macro_rules! test_transparent_unsized { ($name:ident, $t:ty) => { mod $name { use super::*; - assert_abi_compatible!(wrap1, $t, Wrapper1<$t>); - assert_abi_compatible!(wrap1_reprc, ReprC1<$t>, ReprC1>); - assert_abi_compatible!(wrap2, $t, Wrapper2<$t>); - assert_abi_compatible!(wrap2_reprc, ReprC1<$t>, ReprC1>); + assert_abi_compatible_unsized!(wrap1, $t, Wrapper1<$t>); + assert_abi_compatible_unsized!(wrap1_reprc, ReprC1<$t>, ReprC1>); + assert_abi_compatible_unsized!(wrap2, $t, Wrapper2<$t>); + assert_abi_compatible_unsized!(wrap2_reprc, ReprC1<$t>, ReprC1>); } }; } -#[cfg(not(any(target_arch = "mips64", target_arch = "sparc64")))] mod unsized_ { use super::*; test_transparent_unsized!(str_, str); diff --git a/tests/ui/abi/issue-94223.rs b/tests/ui/abi/issue-94223.rs deleted file mode 100644 index 79d6b94031bc2..0000000000000 --- a/tests/ui/abi/issue-94223.rs +++ /dev/null @@ -1,8 +0,0 @@ -// check-pass -#![allow(improper_ctypes_definitions)] -#![crate_type = "lib"] - -// Check that computing the fn abi for `bad`, with a external ABI fn ptr that is not FFI-safe, does -// not ICE. - -pub fn bad(f: extern "C" fn([u8])) {} diff --git a/tests/ui/associated-types/associated-types-unsized.fixed b/tests/ui/associated-types/associated-types-unsized.fixed deleted file mode 100644 index 328c8f944e2e0..0000000000000 --- a/tests/ui/associated-types/associated-types-unsized.fixed +++ /dev/null @@ -1,14 +0,0 @@ -// run-rustfix -#![allow(dead_code, unused_variables)] - -trait Get { - type Value: ?Sized; - fn get(&self) -> ::Value; -} - -fn foo(t: T) where ::Value: Sized { - let x = t.get(); //~ ERROR the size for values of type -} - -fn main() { -} diff --git a/tests/ui/associated-types/associated-types-unsized.rs b/tests/ui/associated-types/associated-types-unsized.rs index bdba4c7ff16a1..8fa83fee35f8c 100644 --- a/tests/ui/associated-types/associated-types-unsized.rs +++ b/tests/ui/associated-types/associated-types-unsized.rs @@ -1,4 +1,3 @@ -// run-rustfix #![allow(dead_code, unused_variables)] trait Get { @@ -8,6 +7,7 @@ trait Get { fn foo(t: T) { let x = t.get(); //~ ERROR the size for values of type + //~| ERROR the size for values of type } fn main() { diff --git a/tests/ui/associated-types/associated-types-unsized.stderr b/tests/ui/associated-types/associated-types-unsized.stderr index bec9b1500c9d7..bd27c44e25c3a 100644 --- a/tests/ui/associated-types/associated-types-unsized.stderr +++ b/tests/ui/associated-types/associated-types-unsized.stderr @@ -1,5 +1,18 @@ error[E0277]: the size for values of type `::Value` cannot be known at compilation time - --> $DIR/associated-types-unsized.rs:10:9 + --> $DIR/associated-types-unsized.rs:9:15 + | +LL | let x = t.get(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `::Value` + = note: the return type of a function must have a statically known size +help: consider further restricting the associated type + | +LL | fn foo(t: T) where ::Value: Sized { + | ++++++++++++++++++++++++++++++ + +error[E0277]: the size for values of type `::Value` cannot be known at compilation time + --> $DIR/associated-types-unsized.rs:9:9 | LL | let x = t.get(); | ^ doesn't have a size known at compile-time @@ -12,6 +25,6 @@ help: consider further restricting the associated type LL | fn foo(t: T) where ::Value: Sized { | ++++++++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-return-type-must-be-sized.rs b/tests/ui/closures/closure-return-type-must-be-sized.rs index 8cfa0291229bd..a12f3a09afc19 100644 --- a/tests/ui/closures/closure-return-type-must-be-sized.rs +++ b/tests/ui/closures/closure-return-type-must-be-sized.rs @@ -52,21 +52,21 @@ impl A for Box { fn main() { a::foo:: dyn A>(); //~ ERROR E0277 - a::bar:: dyn A, _>(); //~ ERROR E0277 + a::bar:: dyn A, _>(); //~ ERROR cannot have an unboxed trait object a::baz:: dyn A>(); //~ ERROR E0277 a::foo:: Box>(); // ok a::bar:: Box, _>(); // ok a::baz:: Box>(); // ok b::foo:: dyn A>(); //~ ERROR E0277 - b::bar:: dyn A, _>(); //~ ERROR E0277 + b::bar:: dyn A, _>(); //~ ERROR cannot have an unboxed trait object b::baz:: dyn A>(); //~ ERROR E0277 b::foo:: Box>(); // ok b::bar:: Box, _>(); // ok b::baz:: Box>(); // ok c::foo:: dyn A>(); //~ ERROR E0277 - c::bar:: dyn A, _>(); //~ ERROR E0277 + c::bar:: dyn A, _>(); //~ ERROR cannot have an unboxed trait object c::baz:: dyn A>(); //~ ERROR E0277 c::foo:: Box>(); // ok c::bar:: Box, _>(); // ok diff --git a/tests/ui/closures/closure-return-type-must-be-sized.stderr b/tests/ui/closures/closure-return-type-must-be-sized.stderr index d4fc723fa8176..215a49f10232f 100644 --- a/tests/ui/closures/closure-return-type-must-be-sized.stderr +++ b/tests/ui/closures/closure-return-type-must-be-sized.stderr @@ -7,19 +7,16 @@ LL | a::foo:: dyn A>(); = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` -error[E0277]: the size for values of type `dyn A` cannot be known at compilation time +error[E0746]: return type cannot have an unboxed trait object --> $DIR/closure-return-type-must-be-sized.rs:55:14 | LL | a::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` - = note: required because it appears within the type `fn() -> dyn A` -note: required by a bound in `a::bar` - --> $DIR/closure-return-type-must-be-sized.rs:14:19 +help: box the return type, and wrap all of the returned values in `Box::new` | -LL | pub fn bar R, R: ?Sized>() {} - | ^^^^^^^^^^^^^ required by this bound in `bar` +LL | a::bar:: dyn A>, _>(); + | ++++ + error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:56:5 @@ -39,19 +36,16 @@ LL | b::foo:: dyn A>(); = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` -error[E0277]: the size for values of type `dyn A` cannot be known at compilation time +error[E0746]: return type cannot have an unboxed trait object --> $DIR/closure-return-type-must-be-sized.rs:62:14 | LL | b::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` - = note: required because it appears within the type `fn() -> dyn A` -note: required by a bound in `b::bar` - --> $DIR/closure-return-type-must-be-sized.rs:28:19 +help: box the return type, and wrap all of the returned values in `Box::new` | -LL | pub fn bar R, R: ?Sized>() {} - | ^^^^^^^^^ required by this bound in `bar` +LL | b::bar:: dyn A>, _>(); + | ++++ + error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:63:5 @@ -71,19 +65,16 @@ LL | c::foo:: dyn A>(); = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` = note: required because it appears within the type `fn() -> dyn A` -error[E0277]: the size for values of type `dyn A` cannot be known at compilation time +error[E0746]: return type cannot have an unboxed trait object --> $DIR/closure-return-type-must-be-sized.rs:69:14 | LL | c::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` - = note: required because it appears within the type `fn() -> dyn A` -note: required by a bound in `c::bar` - --> $DIR/closure-return-type-must-be-sized.rs:42:19 +help: box the return type, and wrap all of the returned values in `Box::new` | -LL | pub fn bar R, R: ?Sized>() {} - | ^^^^^^^^^^^^ required by this bound in `bar` +LL | c::bar:: dyn A>, _>(); + | ++++ + error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:70:5 @@ -96,4 +87,5 @@ LL | c::baz:: dyn A>(); error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0746. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/E0178.rs b/tests/ui/did_you_mean/E0178.rs index 095df640c38f2..cf1db9f61c691 100644 --- a/tests/ui/did_you_mean/E0178.rs +++ b/tests/ui/did_you_mean/E0178.rs @@ -6,7 +6,7 @@ struct Bar<'a> { w: &'a Foo + Copy, //~ ERROR expected a path x: &'a Foo + 'a, //~ ERROR expected a path y: &'a mut Foo + 'a, //~ ERROR expected a path - z: fn() -> Foo + 'a, //~ ERROR expected a path + z: fn() -> &'static Foo + 'a, //~ ERROR expected a path } fn main() { diff --git a/tests/ui/did_you_mean/E0178.stderr b/tests/ui/did_you_mean/E0178.stderr index 58ac6e90823f6..e2b60bdfebd5a 100644 --- a/tests/ui/did_you_mean/E0178.stderr +++ b/tests/ui/did_you_mean/E0178.stderr @@ -16,11 +16,11 @@ error[E0178]: expected a path on the left-hand side of `+`, not `&'a mut Foo` LL | y: &'a mut Foo + 'a, | ^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'a mut (Foo + 'a)` -error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo` +error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> &'static Foo` --> $DIR/E0178.rs:9:8 | -LL | z: fn() -> Foo + 'a, - | ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses? +LL | z: fn() -> &'static Foo + 'a, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ perhaps you forgot parentheses? error: aborting due to 4 previous errors diff --git a/tests/ui/function-pointer/unsized-ret.rs b/tests/ui/function-pointer/unsized-ret.rs index 79009c5cb6c07..3695c9b5454dd 100644 --- a/tests/ui/function-pointer/unsized-ret.rs +++ b/tests/ui/function-pointer/unsized-ret.rs @@ -9,6 +9,7 @@ fn foo, T:std::marker::Tuple>(f: Option, t: T) { fn main() { foo:: str, _>(None, ()); //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| ERROR the size for values of type `str` cannot be known at compilation time foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); //~^ ERROR the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time diff --git a/tests/ui/function-pointer/unsized-ret.stderr b/tests/ui/function-pointer/unsized-ret.stderr index dcfec53eeb950..ca43ff22fc49e 100644 --- a/tests/ui/function-pointer/unsized-ret.stderr +++ b/tests/ui/function-pointer/unsized-ret.stderr @@ -4,16 +4,20 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | foo:: str, _>(None, ()); | ^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> str`, the trait `Sized` is not implemented for `str` - = note: required because it appears within the type `fn() -> str` -note: required by a bound in `foo` - --> $DIR/unsized-ret.rs:5:11 + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-ret.rs:10:27 | -LL | fn foo, T:std::marker::Tuple>(f: Option, t: T) { - | ^^^^^ required by this bound in `foo` +LL | foo:: str, _>(None, ()); + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time - --> $DIR/unsized-ret.rs:13:11 + --> $DIR/unsized-ret.rs:14:11 | LL | foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -26,6 +30,6 @@ note: required by a bound in `foo` LL | fn foo, T:std::marker::Tuple>(f: Option, t: T) { | ^^^^^ required by this bound in `foo` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-50761.rs b/tests/ui/issues/issue-50761.rs index 1bf494ba8f97e..b5d6f3ded308c 100644 --- a/tests/ui/issues/issue-50761.rs +++ b/tests/ui/issues/issue-50761.rs @@ -14,7 +14,7 @@ mod b { } impl Builder { - pub fn with_a(&mut self, _a: fn() -> dyn (::a::A)) {} + pub fn with_a(&mut self, _a: fn(dyn (::a::A)) -> Box) {} } } diff --git a/tests/ui/lint/lint-ctypes-94223-2.rs b/tests/ui/lint/lint-ctypes-94223-2.rs new file mode 100644 index 0000000000000..f98ae0958d009 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-94223-2.rs @@ -0,0 +1,35 @@ +#![crate_type = "lib"] +#![deny(improper_ctypes_definitions)] + +// Test is split in two files since some warnings arise during WF-checking +// and some later, so we can't get them all in the same file. + +pub fn bad(f: extern "C" fn([u8])) {} +//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + +pub fn bad_twice(f: Result) {} +//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + +struct BadStruct(extern "C" fn([u8])); +//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + +enum BadEnum { + A(extern "C" fn([u8])), + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +enum BadUnion { + A(extern "C" fn([u8])), + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +pub trait FooTrait { + type FooType; +} + +pub struct FfiUnsafe; + +#[allow(improper_ctypes_definitions)] +extern "C" fn f(_: FfiUnsafe) { + unimplemented!() +} diff --git a/tests/ui/lint/lint-ctypes-94223-2.stderr b/tests/ui/lint/lint-ctypes-94223-2.stderr new file mode 100644 index 0000000000000..439bbaedeb4f4 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-94223-2.stderr @@ -0,0 +1,53 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/lint-ctypes-94223-2.rs:7:15 + | +LL | pub fn bad(f: extern "C" fn([u8])) {} + | ^^^^^^^^^^^^^^^^^^^ 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 + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/lint-ctypes-94223-2.rs:10:49 + | +LL | pub fn bad_twice(f: Result) {} + | ^^^^^^^^^^^^^^^^^^^ 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 + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/lint-ctypes-94223-2.rs:13:18 + | +LL | struct BadStruct(extern "C" fn([u8])); + | ^^^^^^^^^^^^^^^^^^^ 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 + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/lint-ctypes-94223-2.rs:17:7 + | +LL | A(extern "C" fn([u8])), + | ^^^^^^^^^^^^^^^^^^^ 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 + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/lint-ctypes-94223-2.rs:22:7 + | +LL | A(extern "C" fn([u8])), + | ^^^^^^^^^^^^^^^^^^^ 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 + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lint/lint-ctypes-94223.rs b/tests/ui/lint/lint-ctypes-94223.rs index ac24f61b0ac7a..2084f090c507a 100644 --- a/tests/ui/lint/lint-ctypes-94223.rs +++ b/tests/ui/lint/lint-ctypes-94223.rs @@ -1,25 +1,8 @@ #![crate_type = "lib"] #![deny(improper_ctypes_definitions)] -pub fn bad(f: extern "C" fn([u8])) {} -//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe - -pub fn bad_twice(f: Result) {} -//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe -//~^^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe - -struct BadStruct(extern "C" fn([u8])); -//~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe - -enum BadEnum { - A(extern "C" fn([u8])), - //~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe -} - -enum BadUnion { - A(extern "C" fn([u8])), - //~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe -} +// Test is split in two files since some warnings arise during WF-checking +// and some later, so we can't get them all in the same file. type Foo = extern "C" fn([u8]); //~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe diff --git a/tests/ui/lint/lint-ctypes-94223.stderr b/tests/ui/lint/lint-ctypes-94223.stderr index bd127cf60044c..95e7de202adb4 100644 --- a/tests/ui/lint/lint-ctypes-94223.stderr +++ b/tests/ui/lint/lint-ctypes-94223.stderr @@ -1,8 +1,8 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:4:15 + --> $DIR/lint-ctypes-94223.rs:7:12 | -LL | pub fn bad(f: extern "C" fn([u8])) {} - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | type Foo = extern "C" fn([u8]); + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | = help: consider using a raw pointer instead = note: slices have no C equivalent @@ -12,62 +12,8 @@ note: the lint level is defined here LL | #![deny(improper_ctypes_definitions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `extern` fn uses type `[u8]`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:7:28 - | -LL | pub fn bad_twice(f: Result) {} - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider using a raw pointer instead - = note: slices have no C equivalent - -error: `extern` fn uses type `[u8]`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:7:49 - | -LL | pub fn bad_twice(f: Result) {} - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider using a raw pointer instead - = note: slices have no C equivalent - -error: `extern` fn uses type `[u8]`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:11:18 - | -LL | struct BadStruct(extern "C" fn([u8])); - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider using a raw pointer instead - = note: slices have no C equivalent - -error: `extern` fn uses type `[u8]`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:15:7 - | -LL | A(extern "C" fn([u8])), - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider using a raw pointer instead - = note: slices have no C equivalent - -error: `extern` fn uses type `[u8]`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:20:7 - | -LL | A(extern "C" fn([u8])), - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider using a raw pointer instead - = note: slices have no C equivalent - -error: `extern` fn uses type `[u8]`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:24:12 - | -LL | type Foo = extern "C" fn([u8]); - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe - | - = help: consider using a raw pointer instead - = note: slices have no C equivalent - error: `extern` fn uses type `Option<&::FooType>`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:31:20 + --> $DIR/lint-ctypes-94223.rs:14:20 | LL | pub type Foo2 = extern "C" fn(Option<&::FooType>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -76,7 +22,7 @@ LL | pub type Foo2 = extern "C" fn(Option<&::FooType>); = note: enum has no representation hint error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:41:17 + --> $DIR/lint-ctypes-94223.rs:24:17 | LL | pub static BAD: extern "C" fn(FfiUnsafe) = f; | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -84,13 +30,13 @@ LL | pub static BAD: extern "C" fn(FfiUnsafe) = f; = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes-94223.rs:34:1 + --> $DIR/lint-ctypes-94223.rs:17:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:44:30 + --> $DIR/lint-ctypes-94223.rs:27:30 | LL | pub static BAD_TWICE: Result = Ok(f); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -98,13 +44,13 @@ LL | pub static BAD_TWICE: Result $DIR/lint-ctypes-94223.rs:34:1 + --> $DIR/lint-ctypes-94223.rs:17:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:44:56 + --> $DIR/lint-ctypes-94223.rs:27:56 | LL | pub static BAD_TWICE: Result = Ok(f); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -112,13 +58,13 @@ LL | pub static BAD_TWICE: Result $DIR/lint-ctypes-94223.rs:34:1 + --> $DIR/lint-ctypes-94223.rs:17:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:48:22 + --> $DIR/lint-ctypes-94223.rs:31:22 | LL | pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f; | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -126,10 +72,10 @@ LL | pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f; = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes-94223.rs:34:1 + --> $DIR/lint-ctypes-94223.rs:17:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs index ba473653ecfe3..a0a49b8418afd 100644 --- a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs +++ b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs @@ -14,4 +14,8 @@ fn foo, T: Tuple>(f: Option, t: T) { fn main() { foo:: str, _>(None, ()); //~^ expected a `Fn<_>` closure, found `fn() -> str` + //~| not well-formed + //~| not well-formed + //~| not well-formed + //~| not well-formed } diff --git a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr index 4eaa259617bac..20a0893ef5c18 100644 --- a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr +++ b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr @@ -11,6 +11,30 @@ note: required by a bound in `foo` LL | fn foo, T: Tuple>(f: Option, t: T) { | ^^^^^ required by this bound in `foo` -error: aborting due to previous error +error: the type `fn() -> str` is not well-formed + --> $DIR/builtin-fn-must-return-sized.rs:15:11 + | +LL | foo:: str, _>(None, ()); + | ^^^^^^^^^^^ + +error: the type `fn() -> str` is not well-formed + --> $DIR/builtin-fn-must-return-sized.rs:15:5 + | +LL | foo:: str, _>(None, ()); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: the type `Option str>` is not well-formed + --> $DIR/builtin-fn-must-return-sized.rs:15:27 + | +LL | foo:: str, _>(None, ()); + | ^^^^ + +error: the type `fn() -> str` is not well-formed + --> $DIR/builtin-fn-must-return-sized.rs:15:27 + | +LL | foo:: str, _>(None, ()); + | ^^^^ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs index ffb778a014140..32c1ae42d8124 100644 --- a/tests/ui/traits/test-2.rs +++ b/tests/ui/traits/test-2.rs @@ -13,5 +13,6 @@ fn main() { (Box::new(10) as Box).dup(); //~^ ERROR E0038 //~| ERROR E0038 - //~| ERROR E0038 + //~| ERROR cannot have an unboxed trait object + //~| ERROR trait `bar` cannot be made into an object } diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr index 74a0fc42708e3..8d1d73b639d55 100644 --- a/tests/ui/traits/test-2.stderr +++ b/tests/ui/traits/test-2.stderr @@ -60,6 +60,17 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } = help: consider moving `dup` to another trait = help: consider moving `blah` to another trait +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/test-2.rs:13:36 + | +LL | (Box::new(10) as Box).dup(); + | ^^^ doesn't have a size known at compile-time + | +help: box the return type, and wrap all of the returned values in `Box::new` + | +LL | (Box::new(10) as Box).Box(); + | ++++ + + error[E0038]: the trait `bar` cannot be made into an object --> $DIR/test-2.rs:13:6 | @@ -78,7 +89,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } = help: consider moving `blah` to another trait = note: required for the cast from `Box<{integer}>` to `Box` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0038, E0107. +Some errors have detailed explanations: E0038, E0107, E0746. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/type/issue-58355.rs b/tests/ui/type/issue-58355.rs index 3b62fdece403b..599db1ab66543 100644 --- a/tests/ui/type/issue-58355.rs +++ b/tests/ui/type/issue-58355.rs @@ -1,7 +1,7 @@ #![crate_type = "lib"] pub fn foo(callback: fn() -> dyn ToString) { + //~^ ERROR: cannot have an unboxed trait object let mut x: Option dyn ToString>> = None; x = Some(Box::new(callback)); - //~^ ERROR: the size for values of type `dyn ToString` cannot be known at compilation time } diff --git a/tests/ui/type/issue-58355.stderr b/tests/ui/type/issue-58355.stderr index 67078bcfe89ad..d63b9ddc18b3a 100644 --- a/tests/ui/type/issue-58355.stderr +++ b/tests/ui/type/issue-58355.stderr @@ -1,13 +1,14 @@ -error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time - --> $DIR/issue-58355.rs:5:14 +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-58355.rs:3:22 | -LL | x = Some(Box::new(callback)); - | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +LL | pub fn foo(callback: fn() -> dyn ToString) { + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString` - = note: required because it appears within the type `fn() -> dyn ToString` - = note: required for the cast from `Box dyn ToString>` to `Box (dyn ToString + 'static)>` +help: box the return type, and wrap all of the returned values in `Box::new` + | +LL | pub fn foo(callback: Box dyn ToString>) { + | ++++ + error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.rs b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs index 635d34f822914..346f376316cd5 100644 --- a/tests/ui/unsized-locals/issue-30276-feature-flagged.rs +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs @@ -6,3 +6,4 @@ struct Test([i32]); fn main() { let _x: fn(_) -> Test = Test; } //~^the size for values of type `[i32]` cannot be known at compilation time +//~|the size for values of type `[i32]` cannot be known at compilation time diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr index b6002cf895f0e..6fe10c6687657 100644 --- a/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr @@ -7,6 +7,20 @@ LL | #![feature(unsized_locals)] = note: see issue #48055 for more information = note: `#[warn(incomplete_features)]` on by default +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-30276-feature-flagged.rs:7:13 + | +LL | let _x: fn(_) -> Test = Test; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Test`, the trait `Sized` is not implemented for `[i32]` +note: required because it appears within the type `Test` + --> $DIR/issue-30276-feature-flagged.rs:4:8 + | +LL | struct Test([i32]); + | ^^^^ + = note: the return type of a function must have a statically known size + error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/issue-30276-feature-flagged.rs:7:29 | @@ -17,6 +31,6 @@ LL | let _x: fn(_) -> Test = Test; = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-30276.rs b/tests/ui/unsized-locals/issue-30276.rs index 9c4bf062a40e9..d04e1b929033f 100644 --- a/tests/ui/unsized-locals/issue-30276.rs +++ b/tests/ui/unsized-locals/issue-30276.rs @@ -3,3 +3,4 @@ struct Test([i32]); fn main() { let _x: fn(_) -> Test = Test; } //~^the size for values of type `[i32]` cannot be known at compilation time +//~|the size for values of type `[i32]` cannot be known at compilation time diff --git a/tests/ui/unsized-locals/issue-30276.stderr b/tests/ui/unsized-locals/issue-30276.stderr index 8cccbd792da5c..b193b73c8ba8e 100644 --- a/tests/ui/unsized-locals/issue-30276.stderr +++ b/tests/ui/unsized-locals/issue-30276.stderr @@ -1,3 +1,17 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-30276.rs:4:13 + | +LL | let _x: fn(_) -> Test = Test; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Test`, the trait `Sized` is not implemented for `[i32]` +note: required because it appears within the type `Test` + --> $DIR/issue-30276.rs:1:8 + | +LL | struct Test([i32]); + | ^^^^ + = note: the return type of a function must have a statically known size + error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/issue-30276.rs:4:29 | @@ -8,6 +22,6 @@ LL | let _x: fn(_) -> Test = Test; = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr index 8bbe317ec74ec..c5624bb611b78 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -8,10 +8,10 @@ LL | #![feature(unsized_locals, unsized_fn_params)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/issue-50940-with-feature.rs:6:5 + --> $DIR/issue-50940-with-feature.rs:6:10 | LL | A as fn(str) -> A; - | ^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `A`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `A` diff --git a/tests/ui/unsized-locals/issue-50940.stderr b/tests/ui/unsized-locals/issue-50940.stderr index 8f09b460e004b..9a82634f0d2ee 100644 --- a/tests/ui/unsized-locals/issue-50940.stderr +++ b/tests/ui/unsized-locals/issue-50940.stderr @@ -1,12 +1,16 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/issue-50940.rs:3:5 + --> $DIR/issue-50940.rs:3:10 | LL | A as fn(str) -> A; - | ^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `str` - = note: all function arguments must have a statically known size - = help: unsized fn params are gated as an unstable feature + = help: within `A`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `A` + --> $DIR/issue-50940.rs:2:12 + | +LL | struct A(X); + | ^ + = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/tests/ui/unsized-locals/unsized-param-in-extern-c-decl-issue-115845.rs b/tests/ui/unsized-locals/unsized-param-in-extern-c-decl-issue-115845.rs new file mode 100644 index 0000000000000..38324da731fb8 --- /dev/null +++ b/tests/ui/unsized-locals/unsized-param-in-extern-c-decl-issue-115845.rs @@ -0,0 +1,6 @@ +#![feature(unsized_tuple_coercion)] +#![feature(unsized_fn_params)] + +pub extern "C" fn declare_bad(_x: str) {} //~ERROR: cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/unsized-locals/unsized-param-in-extern-c-decl-issue-115845.stderr b/tests/ui/unsized-locals/unsized-param-in-extern-c-decl-issue-115845.stderr new file mode 100644 index 0000000000000..924c8e0ea12fd --- /dev/null +++ b/tests/ui/unsized-locals/unsized-param-in-extern-c-decl-issue-115845.stderr @@ -0,0 +1,15 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-param-in-extern-c-decl-issue-115845.rs:4:31 + | +LL | pub extern "C" fn declare_bad(_x: str) {} + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | pub extern "C" fn declare_bad(_x: &str) {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/unsized-param-in-fn-ptr-issue-115845.rs b/tests/ui/unsized-locals/unsized-param-in-fn-ptr-issue-115845.rs new file mode 100644 index 0000000000000..dec9e8a5192aa --- /dev/null +++ b/tests/ui/unsized-locals/unsized-param-in-fn-ptr-issue-115845.rs @@ -0,0 +1,15 @@ +#![feature(unsized_tuple_coercion)] +#![feature(unsized_fn_params)] + +fn bad() -> extern "C" fn(([u8],)) { //~ERROR: cannot be known at compilation time + todo!() +} +fn bad2() -> (fn() -> str) { //~ERROR: cannot be known at compilation time + todo!() +} + +fn main() { + let f = bad(); + let slice: Box<([u8],)> = Box::new(([1; 8],)); + f(*slice); +} diff --git a/tests/ui/unsized-locals/unsized-param-in-fn-ptr-issue-115845.stderr b/tests/ui/unsized-locals/unsized-param-in-fn-ptr-issue-115845.stderr new file mode 100644 index 0000000000000..a9bfa350a6db6 --- /dev/null +++ b/tests/ui/unsized-locals/unsized-param-in-fn-ptr-issue-115845.stderr @@ -0,0 +1,22 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-param-in-fn-ptr-issue-115845.rs:4:13 + | +LL | fn bad() -> extern "C" fn(([u8],)) { + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `([u8],)` + = note: all function arguments must have a statically known size + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-param-in-fn-ptr-issue-115845.rs:7:15 + | +LL | fn bad2() -> (fn() -> str) { + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/return-unsized-from-trait-method.rs b/tests/ui/unsized/return-unsized-from-trait-method.rs index f053f4b0af89c..478e1db1050c6 100644 --- a/tests/ui/unsized/return-unsized-from-trait-method.rs +++ b/tests/ui/unsized/return-unsized-from-trait-method.rs @@ -7,7 +7,7 @@ trait Foo { fn foo(f: Option<&dyn Foo>) { if let Some(f) = f { let _ = f.foo(); - //~^ ERROR cannot move a value of type `[u8]` + //~^ ERROR cannot be known at compilation time } } diff --git a/tests/ui/unsized/return-unsized-from-trait-method.stderr b/tests/ui/unsized/return-unsized-from-trait-method.stderr index 671d409937cac..28321a54eff0c 100644 --- a/tests/ui/unsized/return-unsized-from-trait-method.stderr +++ b/tests/ui/unsized/return-unsized-from-trait-method.stderr @@ -1,9 +1,12 @@ -error[E0161]: cannot move a value of type `[u8]` - --> $DIR/return-unsized-from-trait-method.rs:9:17 +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/return-unsized-from-trait-method.rs:9:19 | LL | let _ = f.foo(); - | ^^^^^^^ the size of `[u8]` cannot be statically determined + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the return type of a function must have a statically known size error: aborting due to previous error -For more information about this error, try `rustc --explain E0161`. +For more information about this error, try `rustc --explain E0277`.