diff options
| author | bors <bors@rust-lang.org> | 2025-02-20 02:39:28 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-02-20 02:39:28 +0000 |
| commit | 6d3c050de81c8858e28b0e59cc9398d840edfbff (patch) | |
| tree | bbd53de4a8b2c9322a95b5cea7fd1fe635608c47 /src | |
| parent | 4e1356b95972c1a52acb9f0dd078687132ec02be (diff) | |
| parent | ed45c1187fc94990cd633db47a34696db7ffd580 (diff) | |
Auto merge of #137295 - matthiaskrgr:rollup-tdu3t39, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #135296 (interpret: adjust vtable validity check for higher-ranked types) - #137106 (Add customized compare for Link in rustdoc) - #137253 (Restrict `bevy_ecs` `ParamSet` hack) - #137262 (Make fewer crates depend on `rustc_ast_ir`) - #137263 (Register `USAGE_OF_TYPE_IR_INHERENT`, remove inherent usages) - #137266 (MIR visitor tweaks) - #137269 (Pattern Migration 2024: properly label `&` patterns whose subpatterns are from macro expansions) - #137277 (stabilize `inherent_str_constructors`) - #137281 (Tweak "expected ident" parse error to avoid talking about doc comments) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'src')
4 files changed, 92 insertions, 1 deletions
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 50c09b98db4..64dbaf9083e 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::cmp::Ordering; use rinja::Template; use rustc_data_structures::fx::FxHashSet; @@ -12,6 +13,7 @@ use crate::clean; use crate::formats::Impl; use crate::formats::item_type::ItemType; use crate::html::markdown::{IdMap, MarkdownWithToc}; +use crate::html::render::print_item::compare_names; #[derive(Clone, Copy)] pub(crate) enum ModuleLike { @@ -77,7 +79,7 @@ impl<'a> LinkBlock<'a> { } /// A link to an item. Content should not be escaped. -#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone)] +#[derive(Ord, PartialEq, Eq, Hash, Clone)] pub(crate) struct Link<'a> { /// The content for the anchor tag and title attr name: Cow<'a, str>, @@ -89,6 +91,20 @@ pub(crate) struct Link<'a> { children: Vec<Link<'a>>, } +impl PartialOrd for Link<'_> { + fn partial_cmp(&self, other: &Link<'_>) -> Option<Ordering> { + match compare_names(&self.name, &other.name) { + Ordering::Equal => (), + result => return Some(result), + } + (&self.name_html, &self.href, &self.children).partial_cmp(&( + &other.name_html, + &other.href, + &other.children, + )) + } +} + impl<'a> Link<'a> { pub fn new(href: impl Into<Cow<'a, str>>, name: impl Into<Cow<'a, str>>) -> Self { Self { href: href.into(), name: name.into(), children: vec![], name_html: None } diff --git a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs new file mode 100644 index 00000000000..7de4aef422a --- /dev/null +++ b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs @@ -0,0 +1,30 @@ +// Test that transmuting from `&dyn Trait<fn(&'static ())>` to `&dyn Trait<for<'a> fn(&'a ())>` is UB. +// +// The vtable of `() as Trait<fn(&'static ())>` and `() as Trait<for<'a> fn(&'a ())>` can have +// different entries and, because in the former the entry for `foo` is vacant, this test will +// segfault at runtime. + +trait Trait<U> { + fn foo(&self) + where + U: HigherRanked, + { + } +} +impl<T, U> Trait<U> for T {} + +trait HigherRanked {} +impl HigherRanked for for<'a> fn(&'a ()) {} + +// 2nd candidate is required so that selecting `(): Trait<fn(&'static ())>` will +// evaluate the candidates and fail the leak check instead of returning the +// only applicable candidate. +trait Unsatisfied {} +impl<T: Unsatisfied> HigherRanked for T {} + +fn main() { + let x: &dyn Trait<fn(&'static ())> = &(); + let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) }; + //~^ ERROR: wrong trait in wide pointer vtable + y.foo(); +} diff --git a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr new file mode 100644 index 00000000000..cfdf279a605 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>` + --> tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC + | +LL | let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>` + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs index 6f8adc09640..875891df233 100644 --- a/src/tools/miri/tests/pass/dyn-upcast.rs +++ b/src/tools/miri/tests/pass/dyn-upcast.rs @@ -9,6 +9,7 @@ fn main() { drop_principal(); modulo_binder(); modulo_assoc(); + bidirectional_subtyping(); } fn vtable_nop_cast() { @@ -531,3 +532,32 @@ fn modulo_assoc() { (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0); } + +fn bidirectional_subtyping() { + // Test that transmuting between subtypes of dyn traits is fine, even in the + // "wrong direction", i.e. going from a lower-ranked to a higher-ranked dyn trait. + // Note that compared to the `dyn-transmute-inner-binder` test, the `for` is on the + // *outside* here! + + trait Trait<U: ?Sized> {} + impl<T, U: ?Sized> Trait<U> for T {} + + struct Wrapper<T: ?Sized>(T); + + let x: &dyn Trait<fn(&'static ())> = &(); + let _y: &dyn for<'a> Trait<fn(&'a ())> = unsafe { std::mem::transmute(x) }; + + let x: &dyn for<'a> Trait<fn(&'a ())> = &(); + let _y: &dyn Trait<fn(&'static ())> = unsafe { std::mem::transmute(x) }; + + let x: &dyn Trait<dyn Trait<fn(&'static ())>> = &(); + let _y: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = unsafe { std::mem::transmute(x) }; + + let x: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = &(); + let _y: &dyn Trait<dyn Trait<fn(&'static ())>> = unsafe { std::mem::transmute(x) }; + + // This lowers to a ptr-to-ptr cast (which behaves like a transmute) + // and not an unsizing coercion: + let x: *const dyn for<'a> Trait<&'a ()> = &(); + let _y: *const Wrapper<dyn Trait<&'static ()>> = x as _; +} |
