From 62ef411631efb25134e29da76fcdb7802aa94bd4 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 19 Sep 2024 11:19:35 +0200 Subject: Feature gate boolean lit support in cfg predicates --- compiler/rustc_span/src/symbol.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'compiler/rustc_span/src') diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8f226b26bef..ea8c5f135ab 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -543,6 +543,7 @@ symbols! { cfg_accessible, cfg_attr, cfg_attr_multi, + cfg_boolean_literals, cfg_doctest, cfg_eval, cfg_fmt_debug, -- cgit 1.4.1-3-g733a5 From 4547c0a990b88700812c4e5d14c383bdc7167c31 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 13:25:38 +1100 Subject: Avoid another `&Lrc<..>` in a return value. --- compiler/rustc_span/src/lib.rs | 2 +- compiler/rustc_span/src/source_map/tests.rs | 2 +- src/tools/clippy/clippy_utils/src/source.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_span/src') diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b55465ddef7..5b1be5bca05 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1380,7 +1380,7 @@ pub enum ExternalSourceKind { } impl ExternalSource { - pub fn get_source(&self) -> Option<&Lrc> { + pub fn get_source(&self) -> Option<&str> { match self { ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), _ => None, diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 360baec273d..5b39706f3ad 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -257,7 +257,7 @@ fn t10() { ); imported_src_file.add_external_src(|| Some(unnormalized.to_string())); assert_eq!( - imported_src_file.external_src.borrow().get_source().unwrap().as_ref(), + imported_src_file.external_src.borrow().get_source().unwrap(), normalized, "imported source file should be normalized" ); diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs index 4ad7575e720..eecbfb3936a 100644 --- a/src/tools/clippy/clippy_utils/src/source.rs +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -287,6 +287,7 @@ impl SourceFileRange { self.sf .src .as_ref() + .map(|src| src.as_str()) .or_else(|| self.sf.external_src.get().and_then(|src| src.get_source())) .and_then(|x| x.get(self.range.clone())) } -- cgit 1.4.1-3-g733a5 From 2e7a52b22fe222316a48093547f6312252c20f0f Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Wed, 9 Oct 2024 18:37:30 +0200 Subject: Rename feature object_safe_for_dispatch to dyn_compatible_for_dispatch --- compiler/rustc_feature/src/removed.rs | 4 ++ compiler/rustc_feature/src/unstable.rs | 15 ++-- compiler/rustc_hir_analysis/src/coherence/mod.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/dyn_compatibility.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 2 +- compiler/rustc_trait_selection/src/traits/wf.rs | 2 +- tests/crashes/120241-2.rs | 2 +- tests/crashes/120241.rs | 2 +- tests/crashes/120482.rs | 2 +- tests/crashes/125512.rs | 2 +- tests/crashes/128176.rs | 2 +- tests/crashes/130521.rs | 2 +- .../coherence-unsafe-trait-object-impl.rs | 2 +- .../feature-gate-dyn_compatible_for_dispatch.rs | 41 +++++++++++ ...feature-gate-dyn_compatible_for_dispatch.stderr | 83 ++++++++++++++++++++++ .../feature-gate-object_safe_for_dispatch.rs | 41 ----------- .../feature-gate-object_safe_for_dispatch.stderr | 83 ---------------------- ...d-copy-bound.dyn_compatible_for_dispatch.stderr | 40 +++++++++++ ...ited-copy-bound.object_safe_for_dispatch.stderr | 40 ----------- tests/ui/kindck/kindck-inherited-copy-bound.rs | 8 +-- ...iated-consts.dyn_compatible_for_dispatch.stderr | 19 +++++ ...sociated-consts.object_safe_for_dispatch.stderr | 19 ----- .../object-safety-associated-consts.rs | 4 +- ...ety-generics.dyn_compatible_for_dispatch.stderr | 35 +++++++++ ...safety-generics.object_safe_for_dispatch.stderr | 35 --------- tests/ui/object-safety/object-safety-generics.rs | 8 +-- ...entions-Self.dyn_compatible_for_dispatch.stderr | 35 +++++++++ ...y-mentions-Self.object_safe_for_dispatch.stderr | 35 --------- .../object-safety/object-safety-mentions-Self.rs | 4 +- ...ty-no-static.dyn_compatible_for_dispatch.stderr | 27 +++++++ ...afety-no-static.object_safe_for_dispatch.stderr | 27 ------- tests/ui/object-safety/object-safety-no-static.rs | 4 +- ...fety-sized-2.dyn_compatible_for_dispatch.stderr | 18 +++++ ...-safety-sized-2.object_safe_for_dispatch.stderr | 18 ----- tests/ui/object-safety/object-safety-sized-2.rs | 4 +- ...safety-sized.dyn_compatible_for_dispatch.stderr | 18 +++++ ...ct-safety-sized.object_safe_for_dispatch.stderr | 18 ----- tests/ui/object-safety/object-safety-sized.rs | 4 +- .../downcast-unsafe-trait-objects.rs | 23 ++++++ .../manual-self-impl-for-unsafe-obj.current.stderr | 15 ++++ .../manual-self-impl-for-unsafe-obj.next.stderr | 15 ++++ .../manual-self-impl-for-unsafe-obj.rs | 69 ++++++++++++++++++ .../static-dispatch-unsafe-object.rs | 37 ++++++++++ .../downcast-unsafe-trait-objects.rs | 23 ------ .../manual-self-impl-for-unsafe-obj.current.stderr | 15 ---- .../manual-self-impl-for-unsafe-obj.next.stderr | 15 ---- .../manual-self-impl-for-unsafe-obj.rs | 69 ------------------ .../static-dispatch-unsafe-object.rs | 37 ---------- ...-object-safe.dyn_compatible_for_dispatch.stderr | 22 ++++++ ...not-object-safe.object_safe_for_dispatch.stderr | 22 ------ .../self/arbitrary-self-types-not-object-safe.rs | 6 +- tests/ui/suggestions/issue-104328.rs | 2 +- tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs | 2 +- tests/ui/wf/wf-convert-unsafe-trait-obj.rs | 2 +- tests/ui/wf/wf-unsafe-trait-obj-match.rs | 2 +- 56 files changed, 548 insertions(+), 542 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs create mode 100644 tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs delete mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr create mode 100644 tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs create mode 100644 tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs delete mode 100644 tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs create mode 100644 tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr delete mode 100644 tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr (limited to 'compiler/rustc_span/src') diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd0963d4e3..c275ad31b87 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -154,6 +154,10 @@ declare_features! ( /// then removed. But there was no utility storing it separately, so now /// it's in this list. (removed, no_stack_check, "1.0.0", None, None), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). + /// Renamed to `dyn_compatible_for_dispatch`. + (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561), + Some("renamed to `dyn_compatible_for_dispatch`")), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) (removed, on_unimplemented, "1.40.0", None, None), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c5530097e96..110ffa75b05 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -259,6 +259,14 @@ declare_features! ( (unstable, doc_notable_trait, "1.52.0", Some(45040)), /// Allows using the `may_dangle` attribute (RFC 1327). (unstable, dropck_eyepatch, "1.10.0", Some(34761)), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. + /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and + /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. + /// + /// Renamed from `object_safe_for_dispatch`. + /// + /// [^1]: Formerly known as "object safe". + (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), /// Allows using `#[link_name="llvm.*"]`. @@ -544,13 +552,6 @@ declare_features! ( (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)), /// Allows `for` binders in where-clauses (incomplete, non_lifetime_binders, "1.69.0", Some(108185)), - /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. - /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and - /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. - /// - /// [^1]: Formerly known as "object safe". - // FIXME(dyn_compat_renaming): Rename feature. - (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using fields with slice type in offset_of! diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 69d36426447..eea5a16ac6f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -199,7 +199,7 @@ fn check_object_overlap<'tcx>( for component_def_id in component_def_ids { if !tcx.is_dyn_compatible(component_def_id) { // FIXME(dyn_compat_renaming): Rename test and update comment. - // Without the 'object_safe_for_dispatch' feature this is an error + // Without the 'dyn_compatible_for_dispatch' feature this is an error // which will be reported by wfcheck. Ignore it here. // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. // With the feature enabled, the trait is not implemented automatically, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8aa129c6cd..9e2df848309 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -776,6 +776,7 @@ symbols! { dropck_eyepatch, dropck_parametricity, dylib, + dyn_compatible_for_dispatch, dyn_metadata, dyn_star, dyn_trait, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 191eda4d347..45e7de942fb 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -639,8 +639,8 @@ fn object_ty_for_trait<'tcx>( /// contained by the trait object, because the object that needs to be coerced is behind /// a pointer. /// -/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result -/// in a new check that `Trait` is dyn-compatible, creating a cycle (until object_safe_for_dispatch +/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in +/// a new check that `Trait` is dyn-compatible, creating a cycle (until dyn_compatible_for_dispatch /// is stabilized, see tracking issue ). /// Instead, we fudge a little by introducing a new type parameter `U` such that /// `Self: Unsize` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. @@ -674,7 +674,7 @@ fn receiver_is_dispatchable<'tcx>( // the type `U` in the query // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now. - // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can + // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome")); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 084b61115db..20adda6f0de 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -881,7 +881,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { + if !self.infcx.tcx.features().dyn_compatible_for_dispatch { principal.with_self_ty(self.tcx(), self_ty) } else if self.tcx().is_dyn_compatible(principal.def_id()) { principal.with_self_ty(self.tcx(), self_ty) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7e140ecfee0..a849cdfe125 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -829,7 +829,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // obligations that don't refer to Self and // checking those - let defer_to_coercion = tcx.features().object_safe_for_dispatch; + let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch; if !defer_to_coercion { if let Some(principal) = data.principal_def_id() { diff --git a/tests/crashes/120241-2.rs b/tests/crashes/120241-2.rs index 9c4a3a50293..91ec3362090 100644 --- a/tests/crashes/120241-2.rs +++ b/tests/crashes/120241-2.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] #![feature(unsized_fn_params)] fn guard(_s: Copy) -> bool { diff --git a/tests/crashes/120241.rs b/tests/crashes/120241.rs index f18347a006c..b4fcb903714 100644 --- a/tests/crashes/120241.rs +++ b/tests/crashes/120241.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; diff --git a/tests/crashes/120482.rs b/tests/crashes/120482.rs index 6cbc2009c5f..a395855d796 100644 --- a/tests/crashes/120482.rs +++ b/tests/crashes/120482.rs @@ -1,6 +1,6 @@ //@ known-bug: #120482 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn bar(&self, x: &Self); diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs index 1672b24a114..37dbdf2f32f 100644 --- a/tests/crashes/125512.rs +++ b/tests/crashes/125512.rs @@ -1,6 +1,6 @@ //@ known-bug: rust-lang/rust#125512 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; } diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs index 70fada4f0fe..970ad9ff2cd 100644 --- a/tests/crashes/128176.rs +++ b/tests/crashes/128176.rs @@ -1,7 +1,7 @@ //@ known-bug: rust-lang/rust#128176 #![feature(generic_const_exprs)] -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait X { type Y; } diff --git a/tests/crashes/130521.rs b/tests/crashes/130521.rs index 2d30b658024..7c078ab5790 100644 --- a/tests/crashes/130521.rs +++ b/tests/crashes/130521.rs @@ -1,6 +1,6 @@ //@ known-bug: #130521 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] struct Vtable(dyn Cap); trait Cap<'a> {} diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs index 9859a226efd..16baf0958a6 100644 --- a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs +++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs @@ -1,7 +1,7 @@ // Check that unsafe trait object do not implement themselves // automatically -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized { fn call(&self); diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs new file mode 100644 index 00000000000..2dbba370a51 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs @@ -0,0 +1,41 @@ +// Test that the use of the dyn-incompatible trait objects +// are gated by the `dyn_compatible_for_dispatch` feature gate. + +trait DynIncompatible1: Sized {} + +trait DynIncompatible2 { + fn static_fn() {} +} + +trait DynIncompatible3 { + fn foo(&self); +} + +trait DynIncompatible4 { + fn foo(&self, s: &Self); +} + +fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + //~^ ERROR E0038 + loop {} +} + +fn takes_non_object_safe_box(obj: Box) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_rc() -> std::rc::Rc { + //~^ ERROR E0038 + loop {} +} + +trait Trait {} + +impl Trait for dyn DynIncompatible1 {} +//~^ ERROR E0038 + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..3cb73dfd52c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr @@ -0,0 +1,83 @@ +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:39 + | +LL | fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 + | +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error[E0038]: the trait `DynIncompatible2` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:45 + | +LL | fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8 + | +LL | trait DynIncompatible2 { + | ---------------- this trait cannot be made into an object... +LL | fn static_fn() {} + | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter +help: consider turning `static_fn` into a method by giving it a `&self` argument + | +LL | fn static_fn(&self) {} + | +++++ +help: alternatively, consider constraining `static_fn` so it does not apply to trait objects + | +LL | fn static_fn() where Self: Sized {} + | +++++++++++++++++ + +error[E0038]: the trait `DynIncompatible3` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:39 + | +LL | fn takes_non_object_safe_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8 + | +LL | trait DynIncompatible3 { + | ---------------- this trait cannot be made into an object... +LL | fn foo(&self); + | ^^^ ...because method `foo` has generic type parameters + = help: consider moving `foo` to another trait + +error[E0038]: the trait `DynIncompatible4` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:47 + | +LL | fn return_non_object_safe_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22 + | +LL | trait DynIncompatible4 { + | ---------------- this trait cannot be made into an object... +LL | fn foo(&self, s: &Self); + | ^^^^^ ...because method `foo` references the `Self` type in this parameter + = help: consider moving `foo` to another trait + +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:38:16 + | +LL | impl Trait for dyn DynIncompatible1 {} + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 + | +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs deleted file mode 100644 index 37348e476d4..00000000000 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Test that the use of the non object-safe trait objects -// are gated by `object_safe_for_dispatch` feature gate. - -trait NonObjectSafe1: Sized {} - -trait NonObjectSafe2 { - fn static_fn() {} -} - -trait NonObjectSafe3 { - fn foo(&self); -} - -trait NonObjectSafe4 { - fn foo(&self, s: &Self); -} - -fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - //~^ ERROR E0038 - loop {} -} - -fn takes_non_object_safe_box(obj: Box) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_rc() -> std::rc::Rc { - //~^ ERROR E0038 - loop {} -} - -trait Trait {} - -impl Trait for dyn NonObjectSafe1 {} -//~^ ERROR E0038 - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr deleted file mode 100644 index fd5ed9c40f7..00000000000 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ /dev/null @@ -1,83 +0,0 @@ -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39 - | -LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 - | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - -error[E0038]: the trait `NonObjectSafe2` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:45 - | -LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe2` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:7:8 - | -LL | trait NonObjectSafe2 { - | -------------- this trait cannot be made into an object... -LL | fn static_fn() {} - | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter -help: consider turning `static_fn` into a method by giving it a `&self` argument - | -LL | fn static_fn(&self) {} - | +++++ -help: alternatively, consider constraining `static_fn` so it does not apply to trait objects - | -LL | fn static_fn() where Self: Sized {} - | +++++++++++++++++ - -error[E0038]: the trait `NonObjectSafe3` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39 - | -LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8 - | -LL | trait NonObjectSafe3 { - | -------------- this trait cannot be made into an object... -LL | fn foo(&self); - | ^^^ ...because method `foo` has generic type parameters - = help: consider moving `foo` to another trait - -error[E0038]: the trait `NonObjectSafe4` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:47 - | -LL | fn return_non_object_safe_rc() -> std::rc::Rc { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22 - | -LL | trait NonObjectSafe4 { - | -------------- this trait cannot be made into an object... -LL | fn foo(&self, s: &Self); - | ^^^^^ ...because method `foo` references the `Self` type in this parameter - = help: consider moving `foo` to another trait - -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 - | -LL | impl Trait for dyn NonObjectSafe1 {} - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 - | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..b4424f4750e --- /dev/null +++ b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,40 @@ +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied + --> $DIR/kindck-inherited-copy-bound.rs:21:16 + | +LL | take_param(&x); + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` + | | + | required by a bound introduced by this call + | +note: required for `Box<{integer}>` to implement `Foo` + --> $DIR/kindck-inherited-copy-bound.rs:14:14 + | +LL | impl Foo for T { + | ---- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `take_param` + --> $DIR/kindck-inherited-copy-bound.rs:17:17 + | +LL | fn take_param(foo: &T) { } + | ^^^ required by this bound in `take_param` + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/kindck-inherited-copy-bound.rs:28:13 + | +LL | let z = &x as &dyn Foo; + | ^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/kindck-inherited-copy-bound.rs:10:13 + | +LL | trait Foo : Copy { + | --- ^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for the cast from `&Box` to `&dyn Foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr deleted file mode 100644 index b4424f4750e..00000000000 --- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,40 +0,0 @@ -error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied - --> $DIR/kindck-inherited-copy-bound.rs:21:16 - | -LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` - | | - | required by a bound introduced by this call - | -note: required for `Box<{integer}>` to implement `Foo` - --> $DIR/kindck-inherited-copy-bound.rs:14:14 - | -LL | impl Foo for T { - | ---- ^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required by a bound in `take_param` - --> $DIR/kindck-inherited-copy-bound.rs:17:17 - | -LL | fn take_param(foo: &T) { } - | ^^^ required by this bound in `take_param` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:28:13 - | -LL | let z = &x as &dyn Foo; - | ^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/kindck-inherited-copy-bound.rs:10:13 - | -LL | trait Foo : Copy { - | --- ^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - = note: required for the cast from `&Box` to `&dyn Foo` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0038, E0277. -For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.rs b/tests/ui/kindck/kindck-inherited-copy-bound.rs index c785736f42e..dda95229ddf 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.rs +++ b/tests/ui/kindck/kindck-inherited-copy-bound.rs @@ -1,8 +1,8 @@ // Test that Copy bounds inherited by trait are checked. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::any::Any; @@ -19,7 +19,7 @@ fn take_param(foo: &T) { } fn a() { let x: Box<_> = Box::new(3); take_param(&x); //[curr]~ ERROR E0277 - //[object_safe_for_dispatch]~^ ERROR E0277 + //[dyn_compatible_for_dispatch]~^ ERROR E0277 } fn b() { @@ -28,7 +28,7 @@ fn b() { let z = &x as &dyn Foo; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn main() { } diff --git a/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..5b98cc35505 --- /dev/null +++ b/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-associated-consts.rs:14:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-associated-consts.rs:9:11 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | const X: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr deleted file mode 100644 index 5b98cc35505..00000000000 --- a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | const X: usize; - | ^ ...because it contains this associated `const` - = help: consider moving `X` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/object-safety/object-safety-associated-consts.rs index a090214bbb4..fc7b372b782 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.rs +++ b/tests/ui/object-safety/object-safety-associated-consts.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with associated consts. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { const X: usize; diff --git a/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..4686b994b33 --- /dev/null +++ b/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:20:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:27:5 + | +LL | t as &dyn Bar + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr deleted file mode 100644 index 4686b994b33..00000000000 --- a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | fn bar(&self, t: T); - | ^^^ ...because method `bar` has generic type parameters - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 - | -LL | t as &dyn Bar - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | fn bar(&self, t: T); - | ^^^ ...because method `bar` has generic type parameters - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/object-safety/object-safety-generics.rs index f005a689ac4..b51555aa500 100644 --- a/tests/ui/object-safety/object-safety-generics.rs +++ b/tests/ui/object-safety/object-safety-generics.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with generic methods, unless `where Self : Sized` is // present. -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { @@ -18,14 +18,14 @@ trait Quux { fn make_bar(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t as &dyn Bar - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 //[curr]~| ERROR E0038 } diff --git a/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..d0efb9c587e --- /dev/null +++ b/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:24:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:11:22 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, x: &Self); + | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait + = note: required for the cast from `&T` to `&dyn Bar` + +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:30:5 + | +LL | t + | ^ `Baz` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:15:22 + | +LL | trait Baz { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> Self; + | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait + = note: required for the cast from `&T` to `&dyn Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr deleted file mode 100644 index d0efb9c587e..00000000000 --- a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 - | -LL | trait Bar { - | --- this trait cannot be made into an object... -LL | fn bar(&self, x: &Self); - | ^^^^^ ...because method `bar` references the `Self` type in this parameter - = help: consider moving `bar` to another trait - = note: required for the cast from `&T` to `&dyn Bar` - -error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 - | -LL | t - | ^ `Baz` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 - | -LL | trait Baz { - | --- this trait cannot be made into an object... -LL | fn baz(&self) -> Self; - | ^^^^ ...because method `baz` references the `Self` type in its return type - = help: consider moving `baz` to another trait - = note: required for the cast from `&T` to `&dyn Baz` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/object-safety/object-safety-mentions-Self.rs index 1311faf97bc..84c229e252d 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.rs +++ b/tests/ui/object-safety/object-safety-mentions-Self.rs @@ -2,9 +2,9 @@ // form traits that make use of `Self` in an argument or return // position, unless `where Self : Sized` is present.. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { diff --git a/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..52f6865b6f3 --- /dev/null +++ b/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:22:27 + | +LL | let b: Box = Box::new(Bar); + | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-no-static.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo() {} + | ^^^ ...because associated function `foo` has no `self` parameter + = help: only type `Bar` implements the trait, consider using it directly instead + = note: required for the cast from `Box` to `Box` +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) {} + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | +++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr deleted file mode 100644 index 52f6865b6f3..00000000000 --- a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 - | -LL | let b: Box = Box::new(Bar); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | fn foo() {} - | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `Bar` implements the trait, consider using it directly instead - = note: required for the cast from `Box` to `Box` -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self) {} - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized {} - | +++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.rs b/tests/ui/object-safety/object-safety-no-static.rs index 4f4e03d734e..54af16fe18e 100644 --- a/tests/ui/object-safety/object-safety-no-static.rs +++ b/tests/ui/object-safety/object-safety-no-static.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Foo { fn foo() {} diff --git a/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..99066c104b7 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized-2.rs:16:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized-2.rs:9:18 + | +LL | trait Bar + | --- this trait cannot be made into an object... +LL | where Self : Sized + | ^^^^^ ...because it requires `Self: Sized` + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr deleted file mode 100644 index 99066c104b7..00000000000 --- a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 - | -LL | trait Bar - | --- this trait cannot be made into an object... -LL | where Self : Sized - | ^^^^^ ...because it requires `Self: Sized` - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/object-safety/object-safety-sized-2.rs index cfb5d588d70..f5edd287f24 100644 --- a/tests/ui/object-safety/object-safety-sized-2.rs +++ b/tests/ui/object-safety/object-safety-sized-2.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar where Self : Sized diff --git a/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..5ce713375a4 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized.rs:14:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized.rs:8:12 + | +LL | trait Bar: Sized { + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for the cast from `&T` to `&dyn Bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr deleted file mode 100644 index 5ce713375a4..00000000000 --- a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 - | -LL | t - | ^ `Bar` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 - | -LL | trait Bar: Sized { - | --- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - = note: required for the cast from `&T` to `&dyn Bar` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/object-safety/object-safety-sized.rs index f4d6c945b33..4c4fe3f8f25 100644 --- a/tests/ui/object-safety/object-safety-sized.rs +++ b/tests/ui/object-safety/object-safety-sized.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar: Sized { fn bar(&self, t: T); diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs new file mode 100644 index 00000000000..e9206789756 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs @@ -0,0 +1,23 @@ +// Check that we if we get ahold of an object unsafe trait +// object with auto traits and lifetimes, we can downcast it +// +//@ check-pass + +#![feature(dyn_compatible_for_dispatch)] + +trait Trait: Sized {} + +fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait { + t +} + +fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't)) + -> &'b (dyn Trait + 't) +where + 'a: 'b, + 't: 'a + 'b, +{ + t +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr new file mode 100644 index 00000000000..1489791b20d --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr new file mode 100644 index 00000000000..1489791b20d --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs new file mode 100644 index 00000000000..37e6f948ad1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -0,0 +1,69 @@ +// Check that we can manually implement an object-unsafe trait for its trait object. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ run-pass + +#![feature(dyn_compatible_for_dispatch)] + +trait Bad { + fn stat() -> char { + 'A' + } + fn virt(&self) -> char { + 'B' + } + fn indirect(&self) -> char { + Self::stat() + } +} + +trait Good { + fn good_virt(&self) -> char { //~ WARN methods `good_virt` and `good_indirect` are never used + panic!() + } + fn good_indirect(&self) -> char { + panic!() + } +} + +impl<'a> Bad for dyn Bad + 'a { + fn stat() -> char { + 'C' + } + fn virt(&self) -> char { + 'D' + } +} + +struct Struct {} + +impl Bad for Struct {} + +impl Good for Struct {} + +fn main() { + let s = Struct {}; + + let mut res = String::new(); + + // Directly call static. + res.push(Struct::stat()); // "A" + res.push(::stat()); // "AC" + + let good: &dyn Good = &s; + + // These look similar enough... + let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) }; + + // Call virtual. + res.push(s.virt()); // "ACB" + res.push(bad.virt()); // "ACBD" + + // Indirectly call static. + res.push(s.indirect()); // "ACBDA" + res.push(bad.indirect()); // "ACBDAC" + + assert_eq!(&res, "ACBDAC"); +} diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs new file mode 100644 index 00000000000..c38928a9f44 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs @@ -0,0 +1,37 @@ +// Check that we can statically dispatch methods for object +// unsafe trait objects, directly and indirectly +// +//@ check-pass + +#![feature(dyn_compatible_for_dispatch)] + +trait Statics { + fn plain() {} + fn generic() {} +} + +trait Trait: Sized {} + +impl<'a> Statics for dyn Trait + 'a {} + +fn static_poly() { + T::plain(); + T::generic::(); +} + +fn inferred_poly(t: &T) { + static_poly::(); + T::plain(); + T::generic::(); +} + +fn call(t: &dyn Trait) { + static_poly::(); + inferred_poly(t); +} + +fn main() { + static_poly::(); + ::plain(); + ::generic::() +} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs deleted file mode 100644 index d4337dcb165..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Check that we if we get ahold of an object unsafe trait -// object with auto traits and lifetimes, we can downcast it -// -//@ check-pass - -#![feature(object_safe_for_dispatch)] - -trait Trait: Sized {} - -fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait { - t -} - -fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't)) - -> &'b (dyn Trait + 't) -where - 'a: 'b, - 't: 'a + 'b, -{ - t -} - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr deleted file mode 100644 index 1489791b20d..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: methods `good_virt` and `good_indirect` are never used - --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 - | -LL | trait Good { - | ---- methods in this trait -LL | fn good_virt(&self) -> char { - | ^^^^^^^^^ -... -LL | fn good_indirect(&self) -> char { - | ^^^^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr deleted file mode 100644 index 1489791b20d..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: methods `good_virt` and `good_indirect` are never used - --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8 - | -LL | trait Good { - | ---- methods in this trait -LL | fn good_virt(&self) -> char { - | ^^^^^^^^^ -... -LL | fn good_indirect(&self) -> char { - | ^^^^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs deleted file mode 100644 index a020d91fb14..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Check that we can manually implement an object-unsafe trait for its trait object. - -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@ run-pass - -#![feature(object_safe_for_dispatch)] - -trait Bad { - fn stat() -> char { - 'A' - } - fn virt(&self) -> char { - 'B' - } - fn indirect(&self) -> char { - Self::stat() - } -} - -trait Good { - fn good_virt(&self) -> char { //~ WARN methods `good_virt` and `good_indirect` are never used - panic!() - } - fn good_indirect(&self) -> char { - panic!() - } -} - -impl<'a> Bad for dyn Bad + 'a { - fn stat() -> char { - 'C' - } - fn virt(&self) -> char { - 'D' - } -} - -struct Struct {} - -impl Bad for Struct {} - -impl Good for Struct {} - -fn main() { - let s = Struct {}; - - let mut res = String::new(); - - // Directly call static. - res.push(Struct::stat()); // "A" - res.push(::stat()); // "AC" - - let good: &dyn Good = &s; - - // These look similar enough... - let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) }; - - // Call virtual. - res.push(s.virt()); // "ACB" - res.push(bad.virt()); // "ACBD" - - // Indirectly call static. - res.push(s.indirect()); // "ACBDA" - res.push(bad.indirect()); // "ACBDAC" - - assert_eq!(&res, "ACBDAC"); -} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs deleted file mode 100644 index cbf76a6830b..00000000000 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Check that we can statically dispatch methods for object -// unsafe trait objects, directly and indirectly -// -//@ check-pass - -#![feature(object_safe_for_dispatch)] - -trait Statics { - fn plain() {} - fn generic() {} -} - -trait Trait: Sized {} - -impl<'a> Statics for dyn Trait + 'a {} - -fn static_poly() { - T::plain(); - T::generic::(); -} - -fn inferred_poly(t: &T) { - static_poly::(); - T::plain(); - T::generic::(); -} - -fn call(t: &dyn Trait) { - static_poly::(); - inferred_poly(t); -} - -fn main() { - static_poly::(); - ::plain(); - ::generic::() -} diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr new file mode 100644 index 00000000000..fda07765c66 --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr @@ -0,0 +1,22 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + | +LL | fn foo(self: &Rc) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + = help: only type `usize` implements the trait, consider using it directly instead + = note: required for the cast from `Rc` to `Rc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr deleted file mode 100644 index fda07765c66..00000000000 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 - | -LL | fn foo(self: &Rc) -> usize; - | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` -... -LL | let x = Rc::new(5usize) as Rc; - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | fn foo(self: &Rc) -> usize; - | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on - = help: only type `usize` implements the trait, consider using it directly instead - = note: required for the cast from `Rc` to `Rc` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.rs b/tests/ui/self/arbitrary-self-types-not-object-safe.rs index 0053eb5f739..940b2f1e8e2 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.rs +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.rs @@ -1,6 +1,6 @@ -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::rc::Rc; @@ -33,7 +33,7 @@ fn make_foo() { let x = Rc::new(5usize) as Rc; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn make_bar() { diff --git a/tests/ui/suggestions/issue-104328.rs b/tests/ui/suggestions/issue-104328.rs index c3707baf79f..2b0fbdb8d35 100644 --- a/tests/ui/suggestions/issue-104328.rs +++ b/tests/ui/suggestions/issue-104328.rs @@ -1,4 +1,4 @@ -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Foo { fn f() {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs index ffdb49a3be5..e32b04c4715 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects inside a Box -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs index 143b854ed6b..6f386352819 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects by ref -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-unsafe-trait-obj-match.rs index c8731a8ecaf..07e90538b85 100644 --- a/tests/ui/wf/wf-unsafe-trait-obj-match.rs +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.rs @@ -1,7 +1,7 @@ // Check that we do not allow coercions to object // unsafe trait objects in match arms -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} -- cgit 1.4.1-3-g733a5 From b7297ac4407e25f7872cd061246196cd4c8b485b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:08:48 -0400 Subject: Add gate for precise capturing in traits --- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++++++++++++----- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + .../feature-gate-precise_capturing_in_traits.rs | 6 ++++++ .../feature-gate-precise_capturing_in_traits.stderr | 13 +++++++++++++ .../precise-capturing/forgot-to-capture-type.stderr | 3 +++ .../precise-capturing/redundant.rpitit.stderr | 6 ++++++ .../rpitit-captures-more-method-lifetimes.stderr | 3 +++ tests/ui/impl-trait/precise-capturing/rpitit.stderr | 3 +++ .../impl-trait/precise-capturing/self-capture.stderr | 3 +++ 10 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr (limited to 'compiler/rustc_span/src') diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b26797f4203..35af4d63cc7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1573,11 +1573,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Feature gate for RPITIT + use<..> match origin { rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => { - if let Some(span) = bounds.iter().find_map(|bound| match *bound { - ast::GenericBound::Use(_, span) => Some(span), - _ => None, - }) { - self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span }); + if !self.tcx.features().precise_capturing_in_traits + && let Some(span) = bounds.iter().find_map(|bound| match *bound { + ast::GenericBound::Use(_, span) => Some(span), + _ => None, + }) + { + let mut diag = + self.tcx.dcx().create_err(errors::NoPreciseCapturesOnRpitit { span }); + add_feature_diagnostics( + &mut diag, + self.tcx.sess, + sym::precise_capturing_in_traits, + ); + diag.emit(); } } _ => {} diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 380e36fe405..19a6960cf4d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -565,6 +565,8 @@ declare_features! ( (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), + /// Allows `use<..>` precise capturign on impl Trait in traits. + (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1527600e764..683f59a8999 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1479,6 +1479,7 @@ symbols! { powif64, pre_dash_lto: "pre-lto", precise_capturing, + precise_capturing_in_traits, precise_pointer_size_matching, pref_align_of, prefetch_read_data, diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs new file mode 100644 index 00000000000..308b41dfc68 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs @@ -0,0 +1,6 @@ +trait Foo { + fn test() -> impl Sized + use; + //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr new file mode 100644 index 00000000000..b2c6bf61124 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr @@ -0,0 +1,13 @@ +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/feature-gate-precise_capturing_in_traits.rs:2:31 + | +LL | fn test() -> impl Sized + use; + | ^^^^^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index d9be9d543e4..23d6a3bd11e 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -5,6 +5,9 @@ LL | fn bar() -> impl Sized + use<>; | ^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `impl Trait` must mention all type parameters in scope in `use<...>` --> $DIR/forgot-to-capture-type.rs:1:23 diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr index 213888356e5..27f8ff92d3e 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr @@ -5,6 +5,9 @@ LL | fn in_trait() -> impl Sized + use<'a, Self>; | ^^^^^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits --> $DIR/redundant.rs:21:35 @@ -13,6 +16,9 @@ LL | fn in_trait() -> impl Sized + use<'a> {} | ^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index b390a23eef4..ffd9646a403 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -5,6 +5,9 @@ LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: return type captures more lifetimes than trait definition --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 5a120df9f04..c162875f327 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -5,6 +5,9 @@ LL | fn hello() -> impl PartialEq + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list --> $DIR/rpitit.rs:9:19 diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr index c1974600f30..45ebc429d88 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr +++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr @@ -5,6 +5,9 @@ LL | fn bar<'a>() -> impl Sized + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error -- cgit 1.4.1-3-g733a5 From 0d8a978e8a55b08778ec6ee861c2c5ed6703eb6c Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Fri, 5 Jan 2024 21:04:41 -0700 Subject: intrinsics.fmuladdf{16,32,64,128}: expose llvm.fmuladd.* semantics Add intrinsics `fmuladd{f16,f32,f64,f128}`. This computes `(a * b) + c`, to be fused if the code generator determines that (i) the target instruction set has support for a fused operation, and (ii) that the fused operation is more efficient than the equivalent, separate pair of `mul` and `add` instructions. https://llvm.org/docs/LangRef.html#llvm-fmuladd-intrinsic MIRI support is included for f32 and f64. The codegen_cranelift uses the `fma` function from libc, which is a correct implementation, but without the desired performance semantic. I think this requires an update to cranelift to expose a suitable instruction in its IR. I have not tested with codegen_gcc, but it should behave the same way (using `fma` from libc). --- .../rustc_codegen_cranelift/src/intrinsics/mod.rs | 5 +- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 3 ++ compiler/rustc_codegen_llvm/src/context.rs | 5 ++ compiler/rustc_codegen_llvm/src/intrinsic.rs | 5 ++ compiler/rustc_hir_analysis/src/check/intrinsic.rs | 13 ++++++ compiler/rustc_span/src/symbol.rs | 4 ++ library/core/src/intrinsics.rs | 53 ++++++++++++++++++++++ src/tools/miri/src/intrinsics/mod.rs | 31 +++++++++++++ src/tools/miri/tests/pass/float.rs | 18 ++++++++ .../pass/intrinsics/fmuladd_nondeterministic.rs | 44 ++++++++++++++++++ tests/ui/intrinsics/intrinsic-fmuladd.rs | 42 +++++++++++++++++ 11 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs create mode 100644 tests/ui/intrinsics/intrinsic-fmuladd.rs (limited to 'compiler/rustc_span/src') diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 19e5adc2538..35f0ccff3f9 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -328,6 +328,9 @@ fn codegen_float_intrinsic_call<'tcx>( sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => ("fma", 3, fx.tcx.types.f64, types::F64), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f64 sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32), sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64), sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32), @@ -381,7 +384,7 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); let res = match intrinsic { - sym::fmaf32 | sym::fmaf64 => { + sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) } sym::copysignf32 | sym::copysignf64 => { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 945eedf5556..972d6632140 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -66,6 +66,9 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => "fmaf", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => "fma", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f64 sym::fabsf32 => "fabsf", sym::fabsf64 => "fabs", sym::minnumf32 => "fminf", diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 0a116971e07..c836dd5473f 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -884,6 +884,11 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64); ifn!("llvm.fma.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fmuladd.f16", fn(t_f16, t_f16, t_f16) -> t_f16); + ifn!("llvm.fmuladd.f32", fn(t_f32, t_f32, t_f32) -> t_f32); + ifn!("llvm.fmuladd.f64", fn(t_f64, t_f64, t_f64) -> t_f64); + ifn!("llvm.fmuladd.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fabs.f16", fn(t_f16) -> t_f16); ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32); ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 30c6f08e894..bfe623e7fc3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -86,6 +86,11 @@ fn get_simple_intrinsic<'ll>( sym::fmaf64 => "llvm.fma.f64", sym::fmaf128 => "llvm.fma.f128", + sym::fmuladdf16 => "llvm.fmuladd.f16", + sym::fmuladdf32 => "llvm.fmuladd.f32", + sym::fmuladdf64 => "llvm.fmuladd.f64", + sym::fmuladdf128 => "llvm.fmuladd.f128", + sym::fabsf16 => "llvm.fabs.f16", sym::fabsf32 => "llvm.fabs.f32", sym::fabsf64 => "llvm.fabs.f64", diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 25e219ef3f2..06317a3b304 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -357,6 +357,19 @@ pub fn check_intrinsic_type( (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) } + sym::fmuladdf16 => { + (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16) + } + sym::fmuladdf32 => { + (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32) + } + sym::fmuladdf64 => { + (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64) + } + sym::fmuladdf128 => { + (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) + } + sym::fabsf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8e0009695db..cc3bda99a11 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -914,6 +914,10 @@ symbols! { fmt_debug, fmul_algebraic, fmul_fast, + fmuladdf128, + fmuladdf16, + fmuladdf32, + fmuladdf64, fn_align, fn_delegation, fn_must_use, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d7a2f1909ca..061fba9a1f7 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1795,6 +1795,59 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; + /// Returns `a * b + c` for `f16` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; + /// Returns `a * b + c` for `f32` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; + /// Returns `a * b + c` for `f64` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; + /// Returns `a * b + c` for `f128` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; + /// Returns the absolute value of an `f16`. /// /// The stabilized version of this intrinsic is diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 665dd7c441a..9f772cfa982 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -295,6 +295,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } + "fmuladdf32" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f32()?; + let b = this.read_scalar(b)?.to_f32()?; + let c = this.read_scalar(c)?.to_f32()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "fmuladdf64" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f64()?; + let b = this.read_scalar(b)?.to_f64()?; + let c = this.read_scalar(c)?.to_f64()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "powf32" => { let [f1, f2] = check_arg_count(args)?; let f1 = this.read_scalar(f1)?.to_f32()?; diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 6ab18a5345e..853d3e80517 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -30,6 +30,7 @@ fn main() { libm(); test_fast(); test_algebraic(); + test_fmuladd(); } trait Float: Copy + PartialEq + Debug { @@ -1041,3 +1042,20 @@ fn test_algebraic() { test_operations_f32(11., 2.); test_operations_f32(10., 15.); } + +fn test_fmuladd() { + use std::intrinsics::{fmuladdf32, fmuladdf64}; + + #[inline(never)] + pub fn test_operations_f32(a: f32, b: f32, c: f32) { + assert_approx_eq!(unsafe { fmuladdf32(a, b, c) }, a * b + c); + } + + #[inline(never)] + pub fn test_operations_f64(a: f64, b: f64, c: f64) { + assert_approx_eq!(unsafe { fmuladdf64(a, b, c) }, a * b + c); + } + + test_operations_f32(0.1, 0.2, 0.3); + test_operations_f64(1.1, 1.2, 1.3); +} diff --git a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs new file mode 100644 index 00000000000..b46cf1ddf65 --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs @@ -0,0 +1,44 @@ +#![feature(core_intrinsics)] +use std::intrinsics::{fmuladdf32, fmuladdf64}; + +fn main() { + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f64); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. + let x = unsafe { fmuladdf64(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf64` failed to be evaluated as both fused and unfused" + ); + + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f32); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. + let x = unsafe { fmuladdf32(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf32` failed to be evaluated as both fused and unfused" + ); +} diff --git a/tests/ui/intrinsics/intrinsic-fmuladd.rs b/tests/ui/intrinsics/intrinsic-fmuladd.rs new file mode 100644 index 00000000000..d03297884f7 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-fmuladd.rs @@ -0,0 +1,42 @@ +//@ run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::*; + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => {{ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); + }}; +} + +fn main() { + unsafe { + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + assert_approx_eq!(fmuladdf32(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf32(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf32(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf32(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf32(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf32(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf32(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf32(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf32(-3.2, 2.4, neg_inf), neg_inf); + } + unsafe { + let nan: f64 = f64::NAN; + let inf: f64 = f64::INFINITY; + let neg_inf: f64 = f64::NEG_INFINITY; + assert_approx_eq!(fmuladdf64(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf64(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf64(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf64(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf64(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf64(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf64(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf64(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf64(-3.2, 2.4, neg_inf), neg_inf); + } +} -- cgit 1.4.1-3-g733a5