-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation of dyn* #101212
Initial implementation of dyn* #101212
Conversation
This PR changes MIR cc @oli-obk, @RalfJung, @JakobDegen, @davidtwco, @celinval, @vakaras Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri |
This comment has been minimized.
This comment has been minimized.
Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left some initial comments, mostly nits! the code looks pretty good
span: Span, | ||
) -> CastCheckResult<'tcx> { | ||
if cast_ty.is_dyn_star() { | ||
check_dyn_star_cast(fcx, expr, expr_ty, cast_ty) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why this is needed? Why can't this live in CastCheck
, that is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a dyn* cast check succeeds, there aren't any deferred checks we need to worry about, so it doesn't really make sense to build a CastCheck
.
I guess another way to do this would be to make CastCheck::new
return Result<Option<CastCheck>, ErrorGuaranteed>
, but this way seemed cleaner to me. I'm happy to change it though if you think that's better.
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
Outdated
Show resolved
Hide resolved
@@ -3124,6 +3156,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { | |||
layout: TyAndLayout<'tcx>, | |||
offset: Size, | |||
is_return: bool| { | |||
let span = tracing::debug_span!("adjust_for_rust_scalar"); | |||
let _enter = span.enter(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Is it possible to put #[instrument]
on the caller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you can, I haven't figured out how to do it...
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You missed the pointer_kind
function in rustc_typeck/src/check/cast.rs. I think it needs to return Some(PointerKind::Thin)
or None
for dyn*
. It didn't error because ..
was used. Please also check other usages of Dynamic
. For example I think you didn't change dyn*
anywhere to be sized.
@@ -701,6 +701,10 @@ fn codegen_stmt<'tcx>( | |||
let operand = codegen_operand(fx, operand); | |||
operand.unsize_value(fx, lval); | |||
} | |||
Rvalue::Cast(CastKind::DynStar, _, _) => { | |||
// FIXME(dyn-star) | |||
unimplemented!() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME reminder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the best way to test with the cranelift backend? I can make sure this doesn't crash cranelift.
Is this something we should fix as part of this PR, or would it be okay to do it as a follow up?
dyn* is sized here: https://github.com/rust-lang/rust/pull/101212/files#diff-34d5893dd95fe09f9a0fd3341efacd1c21853bb34ba29d9d79bb9af26bb8a0a0R1874 |
This comment has been minimized.
This comment has been minimized.
I just pushed a change that makes pointer_kind error for dyn*, like the other sized types do. That sort of seemed reasonable based on the surrounding code and comments, but I'm not 100% confident in that choice. What do you think? |
I think this is reasonable, but I'm not familiar with this code at all. r? rust-lang/compiler |
/// A sized `dyn* Trait` object | ||
/// | ||
/// These objects are represented as a `(data, vtable)` pair where `data` is a usized value | ||
/// (often a pointer to the real object, but not necessarily) and `vtable` is a pointer to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who decides the representation, where is that information (about the representation choice) encoded?
In the interpreter, it seems to always be a pointer to the real object (judging from the cast
code, which is the only new code for this atm).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The layout code sets the representation here: https://github.com/rust-lang/rust/pull/101212/files#diff-b0320c2b8868f325d83c027fc5d71732636e9763551e35895488f30fe057c6e9R627-R633
We construct these values here: https://github.com/rust-lang/rust/pull/101212/files#diff-db08b7c8b00530c7183cf2e42f25dc93b02da93fb40edadbd009eee6ad60e3a1R275-R289
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first link does not set how things are represented, via pointer or via direct inlining. I was wondering how that is decided.
However the first link does say that the data
part must be non-null, which should also be documented here.
Not sure where the second link is supposed to go; links into the 'diff' view of a PR are notoriously unrelaible...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be more stable for the second link: https://github.com/rust-lang/rust/blob/242f9c128ebd5e107fc45ea3725e4e9745ff355b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs#L275...L289
At the moment the data part is made by basically transmuting whatever we are casting into it. The tests so far all work by casting a usize
into a dyn*
, for example: src/test/ui/dyn-star/method.rs.
Longer term we want to do this conversion using a family of lang traits called something like IntoDynPointer
. I discuss this some in my blog post on async functions in traits. These would let types override the behavior. By default the implementation would probably be a straight cast for things that are already pointers and Box::new(self).into_raw()
for things that are not, but we'd like to give flexibility in where async function return futures go.
The non-null requirement in the first link is incorrect, since it's totally reasonable to do 0 as dyn* Debug
. I'll update that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see, so something somewhere checks that the LHS of an as dyn*
is ptr-sized?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will in the future, but it doesn't now iirc...
compiler/rustc_type_ir/src/sty.rs
Outdated
Sized, | ||
} | ||
|
||
// Manually implemented because deriving HashStable requires rustc_query_system, which would |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can derive HashStable_Generic
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried and got:
error[E0405]: cannot find trait `HashStableContext` in the crate root
--> compiler/rustc_type_ir/src/sty.rs:33:5
|
33 | HashStable_Generic
| ^^^^^^^^^^^^^^^^^^
| |
| not found in the crate root
| in this derive macro expansion
|
::: /home/ericholk/.cargo/registry/src/git.luolix.top-1ecc6299db9ec823/synstructure-0.12.6/src/macros.rs:94:9
|
94 | / pub fn $derives(
95 | | i: $crate::macros::TokenStream
96 | | ) -> $crate::macros::TokenStream {
| |________________________________________- in this expansion of `#[derive(HashStable_Generic)]`
A lot of other code in this file implements HashStable also, so I'm guessing there's some more fundamental reason we can't use this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to create an empty trait HashStableContext
at the crate root, and implement it for ich::StableHashingContext
in rustc_query_system
. This is a bit convoluted, but I haven't found a better solution around the cyclic dependency issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that this crate already has a lot of manual implementations for HashTable
, I think it makes more sense to do the same here and then do a separate PR that moves as many as we can over to derive
all at once. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened #101549 to do this for the other types. If that merges before this one (likely) then I'll update it here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That PR merged so I've updated this to use HashStable_Generic
here too.
@bors r+ rollup=never rollup=never is since this might have perf effects or we might want to blame it for ICEs |
☀️ Test successful - checks-actions |
Finished benchmarking commit (6153d3c): comparison URL. Overall result: ✅ improvements - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Footnotes |
Implemented for cg_clif in bjorn3/rustc_codegen_cranelift@879c86f. |
Rvalue::Cast(CastKind::DynStar, _, _) => { | ||
// FIXME(dyn-star) | ||
unimplemented!() | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eholk This doesn't look right. This gives me the feeling that Clippy might start panicking on every project that tries to use this nightly feature.
Is there a plan to address those unimplemented!
macros?
Specify `DynKind::Dyn` ref: rust-lang#101212 (comment)
Specify `DynKind::Dyn` ref: rust-lang#101212 (comment)
Resolves 5542 Prior to rust-lang/rust#101212 the `ast::TraitObjectSyntax` enum only had two variants `Dyn` and `None`. The PR that introduced the `dyn*` syntax added a new variant `DynStar`, but did not update the formatting rules to account for the new variant. Now the new `DynStar` variant is properly handled and is no longer removed by rustfmt.
Specify `DynKind::Dyn` ref: rust-lang#101212 (comment)
Initial implementation of dyn* This PR adds extremely basic and incomplete support for [dyn*](https://smallcultfollowing.com/babysteps//blog/2022/03/29/dyn-can-we-make-dyn-sized/). The goal is to get something in tree behind a flag to make collaboration easier, and also to make sure the implementation so far is not unreasonable. This PR does quite a few things: * Introduce `dyn_star` feature flag * Adds parsing for `dyn* Trait` types * Defines `dyn* Trait` as a sized type * Adds support for explicit casts, like `42usize as dyn* Debug` * Including const evaluation of such casts * Adds codegen for drop glue so things are cleaned up properly when a `dyn* Trait` object goes out of scope * Adds codegen for method calls, at least for methods that take `&self` Quite a bit is still missing, but this gives us a starting point. Note that this is never intended to become stable surface syntax for Rust, but rather `dyn*` is planned to be used as an implementation detail for async functions in dyn traits. Joint work with `@nikomatsakis` and `@compiler-errors.` r? `@bjorn3`
Initial implementation of dyn* This PR adds extremely basic and incomplete support for [dyn*](https://smallcultfollowing.com/babysteps//blog/2022/03/29/dyn-can-we-make-dyn-sized/). The goal is to get something in tree behind a flag to make collaboration easier, and also to make sure the implementation so far is not unreasonable. This PR does quite a few things: * Introduce `dyn_star` feature flag * Adds parsing for `dyn* Trait` types * Defines `dyn* Trait` as a sized type * Adds support for explicit casts, like `42usize as dyn* Debug` * Including const evaluation of such casts * Adds codegen for drop glue so things are cleaned up properly when a `dyn* Trait` object goes out of scope * Adds codegen for method calls, at least for methods that take `&self` Quite a bit is still missing, but this gives us a starting point. Note that this is never intended to become stable surface syntax for Rust, but rather `dyn*` is planned to be used as an implementation detail for async functions in dyn traits. Joint work with `@nikomatsakis` and `@compiler-errors.` r? `@bjorn3`
@@ -625,6 +625,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { | |||
tcx.intern_layout(self.scalar_pair(data_ptr, metadata)) | |||
} | |||
|
|||
ty::Dynamic(_, _, ty::DynStar) => { | |||
let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds wrong -- if you are storing a pointer here, this should use a pointer layout, not an integer layout. Integers don't carry provenance, pointers do, so this makes a difference.
I am seeing some strange behavior in trying to get this to work in Miri and it looks like provenance is getting lost... so I am guessing this might be the reason. I see in an earlier commit this was using Pointer
. Why did you change this to ptr_sized_integer?
Note that if something is either a pointer or an integer, then it must use a pointer type, not an integer type. Ptr-sized integers are a strict subset of pointers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to fix this as part of #107728 but that leads to invalid LLVM IR errors...
ty::Dynamic(_, _, ty::DynStar) => { | ||
if i == 0 { | ||
TyMaybeWithLayout::Ty(tcx.types.usize) | ||
} else if i == 1 { | ||
// FIXME(dyn-star) same FIXME as above applies here too | ||
TyMaybeWithLayout::Ty( | ||
tcx.mk_imm_ref( | ||
tcx.lifetimes.re_static, | ||
tcx.mk_array(tcx.types.usize, 3), | ||
), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there some kind of implicit invariant that this must be consistent with layout_of_uncached
? Nowadays these two functions are not even in the same crate. That seems very fragile. Am I missing something?
Cc @oli-obk
Resolves 5542 Prior to rust-lang/rust#101212 the `ast::TraitObjectSyntax` enum only had two variants `Dyn` and `None`. The PR that introduced the `dyn*` syntax added a new variant `DynStar`, but did not update the formatting rules to account for the new variant. Now the new `DynStar` variant is properly handled and is no longer removed by rustfmt.
Resolves 5542 Prior to rust-lang/rust#101212 the `ast::TraitObjectSyntax` enum only had two variants `Dyn` and `None`. The PR that introduced the `dyn*` syntax added a new variant `DynStar`, but did not update the formatting rules to account for the new variant. Now the new `DynStar` variant is properly handled and is no longer removed by rustfmt.
This PR adds extremely basic and incomplete support for dyn*. The goal is to get something in tree behind a flag to make collaboration easier, and also to make sure the implementation so far is not unreasonable. This PR does quite a few things:
dyn_star
feature flagdyn* Trait
typesdyn* Trait
as a sized type42usize as dyn* Debug
dyn* Trait
object goes out of scope&self
Quite a bit is still missing, but this gives us a starting point. Note that this is never intended to become stable surface syntax for Rust, but rather
dyn*
is planned to be used as an implementation detail for async functions in dyn traits.Joint work with @nikomatsakis and @compiler-errors.
r? @bjorn3