Skip to content
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

Trait upcasting coercion (part4) #88010

Closed
wants to merge 2 commits into from

Conversation

crlf0710
Copy link
Member

This is a incomplete version of trait upcasting unsafety checking. I think it's working in principle, however i think i meet a problem here. How can i know Box<T> or Arc<T>'s internal pointer can be seen as "always-valid"?

cc @RalfJung

@rust-highfive
Copy link
Collaborator

r? @davidtwco

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 13, 2021
@crlf0710 crlf0710 added S-experimental Status: Ongoing experiment that does not require reviewing and won't be merged in its current state. F-trait_upcasting `#![feature(trait_upcasting)]` and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 13, 2021
@crlf0710 crlf0710 changed the title Trait upcasting part3 Trait upcasting coercion (part3) Aug 13, 2021
@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
configure: rust.channel         := nightly
configure: rust.debug-assertions := True
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
skip untracked path cpu-usage.csv during rustfmt invocations
skip untracked path src/doc/book/ during rustfmt invocations
skip untracked path src/doc/rust-by-example/ during rustfmt invocations
skip untracked path src/llvm-project/ during rustfmt invocations
Diff in /checkout/compiler/rustc_mir/src/transform/mod.rs at line 5:
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::visit::Visitor as _;
 use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
Diff in /checkout/compiler/rustc_mir/src/transform/mod.rs at line 12:
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_span::{Span, Symbol};
-use rustc_hir::lang_items::LangItem;
 use std::borrow::Cow;
 
 
Running `"/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/rustfmt" "--config-path" "/checkout" "--edition" "2018" "--unstable-features" "--skip-children" "--check" "/checkout/compiler/rustc_mir/src/transform/simplify.rs" "/checkout/compiler/rustc_mir/src/transform/deduplicate_blocks.rs" "/checkout/compiler/rustc_mir/src/transform/mod.rs" "/checkout/compiler/rustc_mir/src/transform/multiple_return_terminators.rs" "/checkout/compiler/rustc_mir/src/transform/separate_const_switch.rs" "/checkout/compiler/rustc_mir/src/transform/check_packed_ref.rs" "/checkout/compiler/rustc_mir/src/transform/lower_intrinsics.rs" "/checkout/compiler/rustc_mir/src/transform/abort_unwinding_calls.rs"` failed.
If you're running `tidy`, try again with `--bless`. Or, if you just want to format code, run `./x.py fmt` instead.

@@ -625,3 +628,27 @@ fn promoted_mir<'tcx>(

tcx.arena.alloc(promoted)
}

pub(crate) fn custom_coerce_unsize_info<'tcx>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this function would be better put somewhere in rustc_mir/src/util?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should i create a new module in util for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If none of the others seem to fit, yeah.

@@ -132,6 +132,24 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
self.register_violations(&violations, &unsafe_blocks);
}
},
Rvalue::Cast(kind, source, mir_cast_ty) => {
if let CastKind::Pointer(ty::adjustment::PointerCast::Unsize) = kind {
let mir_source_ty = match *source {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to use Operand::ty here, right?

Copy link
Member Author

@crlf0710 crlf0710 Aug 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure, since this is earlier than codegen phase, if i'm not misunderstanding it. I'll take a look.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has nothing to do with codegen. I think you basically inlined Operand::ty here.

fn is_trait_upcasting_coercion_pointee(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> bool {
match (source.kind(), target.kind()) {
(&ty::Dynamic(data_a, ..), &ty::Dynamic(data_b, ..)) => {
data_a.principal_def_id() != data_b.principal_def_id()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it okay to allow casts where data_a.principal_def_id() == data_b.principal_def_id()? Please add a comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok!

//~^ ERROR mismatched types
}

fn main() {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these two separate files?

Please also add some casts that are okay.

Does this hit the last match arm in is_trait_upcasting_coercion_from_raw_pointer?

Copy link
Member Author

@crlf0710 crlf0710 Aug 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a separate file because the "mismatched types" error will prevent unsafety checker from running at all, it seems. I don't really know whether error recovery is possible at all in this case. This test case is just the status quo. I'll leave comments, when the unsafety checking implementation is ready.

Please also add some casts that are okay.

I will, thanks!

Does this hit the last match arm in is_trait_upcasting_coercion_from_raw_pointer?

No it doesn't, the unsafety checker is not yet running in this case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it doesn't, the unsafety checker is not yet running in this case.

Okay, then the other test should definitely do something to hit that arm.

@RalfJung
Copy link
Member

however i think i meet a problem here. How can i know Box or Arc's internal pointer can be seen as "always-valid"?

Good question. Currently you seem to be doing some kind of recursion here, but I am not sure what this means in terms of the resulting behavior.

Is it correct that that Adt arm in is_trait_upcasting_coercion_from_raw_pointer can only be reached for types that implement CoerceUnsized?

Cc @rust-lang/lang

@crlf0710
Copy link
Member Author

crlf0710 commented Aug 14, 2021

@RalfJung i think the answer is yes, according to CoerceUnsized documentation. It even covers all the Non-ADT cases, like the reference and raw pointer types.

On the other hand the reference says something unintuitive: It says TyCtor(T) to TyCtor(U). Not sure if whether this clause is intended to cover the CoerceUnsized cases.

I think my current problem is that, the CoerceUnsized trait doesn't say anything semantically about what's happening underhood. It is defined in a very structured typing approach.

@RalfJung
Copy link
Member

Yeah, it sounds like for full expressivity we'd need CoerceUnsizedUnsafe -- for smart pointers that wrap a raw pointer and don't guarantee via a custom invariant that it is valid.

For now, I think assuming they are safe to cast (if the recursive check succeeds) makes sense. But this should be added to the list of unresolved questions for trait coercions, to be brought up in the stabilization report.

Also there should be tests for things like *const Cell<dyn T> to *const Cell<dyn U>, to ensure that this requires unsafe (if it works at all).

@crlf0710 crlf0710 changed the title Trait upcasting coercion (part3) Trait upcasting coercion (part4) Aug 18, 2021
@crlf0710
Copy link
Member Author

I'll let this PR wait on #88135 a little, and discuss more about CoerceUnsized during the review of that pr.

@crlf0710
Copy link
Member Author

#88135 has landed, and i created #88239 for a less ad-hoc approach to gather feedback and discussions.

@davidtwco davidtwco assigned RalfJung and unassigned davidtwco Aug 23, 2021
@RalfJung
Copy link
Member

I'll be pretty busy for some time since I am moving, so I am probably not the best reviewer here.

@crlf0710
Copy link
Member Author

That's ok, after some discussions i think this is not the prefered approach here. Closing for now, but might get back to this if necessary.

@crlf0710 crlf0710 closed this Aug 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-trait_upcasting `#![feature(trait_upcasting)]` S-experimental Status: Ongoing experiment that does not require reviewing and won't be merged in its current state.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants