-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Fix coherence checking for impl trait in type aliases #63934
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
r? @nikomatsakis cc @cramertj @varkor |
This is another PR that requires some thought. I'm scheduling a slot on this coming Friday (Sep 6) to do 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.
Spent some time thinking about this PR. I'm not sure yet if I think it's the right direction, but here are some interim notes.
Ping from triage @Aaron1011 What is the status of this pr? Thanks |
I'm inclined to agree. Re-reading my comment, I'm not entirely sure what I was concerned about when talking about a "smarter negative" test. If we consider opaque types as foreign, I think that will have the effect I wanted of not assuming either way whether they implement other traits. Can you update the PR to make opaque types be considered foreign? |
3908647
to
a3dd3e1
Compare
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
a3dd3e1
to
8078f50
Compare
@nikomatsakis Updated |
8078f50
to
294d0c8
Compare
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 think we also need a test focused on negative reasoning. Something like this:
trait OpaqueTrait { }
impl<T> OpaqueTrait for { }
type OpaqueType = impl OpaqueTrait;
fn mk_opaque() -> OpaqueType { () }
#[derive(Debug)]
struct D<T>(T);
trait AnotherTrait { }
impl<T: Debug> AnotherTrait for T { }
// This is in error, because we cannot assume that `OpaqueType: !Debug`.
impl AnotherTrait for D<OpaqueType> {
//^~ ERROR foo
}
Another good test would be to check for auto trait interaction:
trait OpaqueTrait { }
impl<T> OpaqueTrait for { }
type OpaqueType = impl OpaqueTrait;
fn mk_opaque() -> OpaqueType { () }
#[derive(Debug)]
struct D<T>(T);
trait AnotherTrait { }
impl<T: Send> AnotherTrait for T { }
// This is in error, because we cannot assume that `OpaqueType: !Send`.
// (We treat opaque types as "foreign types" that could grow more impls
// in the future.)
impl AnotherTrait for D<OpaqueType> {
//^~ ERROR foo
}
It would be good to create cross-crate vesions of these tests, as well.
@Aaron1011 these changes look great, and the comment explaining the reasoning is good; I left a review with a few more tests to add, but otherwise I think good to go. |
294d0c8
to
4eb3d8d
Compare
@nikomatsakis: I've added the tests you requested |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@Aaron1011 looks like you need to "bless" -- though you may also need to rebase |
Fixes rust-lang#63677 RFC rust-lang#2071 (impl-trait-existential-types) does not explicitly state how impl trait type alises should interact with coherence. However, there's only one choice which makes sense - coherence should look at the underlying type (i.e. the 'defining' type of the impl trait) of the type alias, just like we do for non-impl-trait type aliases. Specifically, impl trait type alises which resolve to a local type should be treated like a local type with respect to coherence (e.g. impl trait type aliases which resolve to a forieign type should be treated as a foreign type, and those that resolve to a local type should be treated as a local type). Since neither inherent impls nor direct trait impl (i.e. `impl MyType` or `impl MyTrait for MyType`) are allowd for type aliases, this usually does not come up. Before we ever attempt to do coherence checking, we will have errored out if an impl trait type alias was used directly in an 'impl' clause. However, during trait selection, we sometimes need to prove bounds like 'T: Sized' for some type 'T'. If 'T' is an impl trait type alias, this requires to know the coherence behavior for impl trait type aliases when we perform coherence checking. Note: Since determining the underlying type of an impl trait type alias requires us to perform body type checking, this commit causes us to type check some bodies easlier than we otherwise would have. However, since this is done through a query, this shouldn't cause any problems For completeness, I've added an additional test of the coherence-related behavior of impl trait type aliases.
4eb3d8d
to
61cfe92
Compare
@nikomatsakis Fixed |
@bors r+ |
📌 Commit 61cfe92 has been approved by |
⌛ Testing commit 61cfe92 with merge a0323f8a4d1baa7815356cf42f26b2fceb4e3b20... |
… r=nikomatsakis Fix coherence checking for impl trait in type aliases **UPDATE**: This PR now treats all opaque types as remote. The original description appears below, but is no longer accurate. Fixes rust-lang#63677 [RFC 2071](rust-lang/rfcs#2071) (impl-trait-existential-types) does not explicitly state how `type_alias_impl_trait` should interact with coherence. However, there's only one choice which makes sense - coherence should look at the underlying type (i.e. the *"defining"* type of the `impl Trait`) of the type alias, just like we do for non-`impl Trait` type aliases. Specifically, `impl Trait` type aliases that resolve to a local type should be treated like a local type with respect to coherence (e.g. `impl Trait` type aliases which resolve to a foreign type should be treated as a foreign type, and those that resolve to a local type should be treated as a local type). Since neither inherent impls nor direct trait impl (i.e. `impl MyType` or `impl MyTrait for MyType`) are allowed for type aliases, this usually does not come up. Before we ever attempt to do coherence checking, we will have errored out if an `impl Trait` type alias was used directly in an `impl` clause. However, during trait selection, we sometimes need to prove bounds like `T: Sized` for some type `T`. If `T` is an impl trait type alias, this requires to know the coherence behavior for `impl Trait` type aliases when we perform coherence checking. Note: Since determining the underlying type of an `impl Trait` type alias requires us to perform body type checking, this commit causes us to type check some bodies easier than we otherwise would have. However, since this is done through a query, this shouldn't cause any problems For completeness, I've added an additional test of the coherence-related behavior of `impl Trait` type aliases. cc rust-lang#63063
@bors retry rolled up. |
Rollup of 16 pull requests Successful merges: - #63356 (Issue#63183: Add fs::read_dir() and ReadDir warning about iterator order + example) - #63934 (Fix coherence checking for impl trait in type aliases) - #64016 (Streamline `Compiler`) - #64296 (Document the unstable iter_order_by library feature) - #64443 (rustdoc: general cleanup) - #64622 (Add a cycle detector for generic `Graph`s and `mir::Body`s) - #64689 (Refactor macro by example) - #64698 (Recover on `const X = 42;` and infer type + Error Stash API) - #64702 (Remove unused dependencies) - #64717 (update mem::discriminant test to use assert_eq and assert_ne over comparison operators) - #64720 ( remove rtp.rs, and move rtpSpawn and RTP_ID_ERROR to libc) - #64721 (Fixed issue from #64447) - #64725 (fix one typo) - #64737 (fix several issues in String docs) - #64742 (relnotes: make compatibility section more sterile and fix rustc version) - #64748 (Fix #64744. Account for the Zero sub-pattern case.) Failed merges: r? @ghost
Pkgsrc changes: * Remove patch which no longer applies (but what about RPATH?) * Adapt a few patches to changed files upstream. Upstream changes: Version 1.39.0 (2019-11-07) =========================== Language -------- - [You can now create `async` functions and blocks with `async fn`, `async move {}`, and `async {}` respectively, and you can now call `.await` on async expressions.][63209] - [You can now use certain attributes on function, closure, and function pointer parameters.][64010] These attributes include `cfg`, `cfg_attr`, `allow`, `warn`, `deny`, `forbid` as well as inert helper attributes used by procedural macro attributes applied to items. e.g. ```rust fn len( #[cfg(windows)] slice: &[u16], #[cfg(not(windows))] slice: &[u8], ) -> usize { slice.len() } ``` - [You can now take shared references to bind-by-move patterns in the `if` guards of `match` arms.][63118] e.g. ```rust fn main() { let array: Box<[u8; 4]> = Box::new([1, 2, 3, 4]); match array { nums // ---- `nums` is bound by move. if nums.iter().sum::<u8>() == 10 // ^------ `.iter()` implicitly takes a reference to `nums`. => { drop(nums); // ----------- Legal as `nums` was bound by move and so we have ownership. } _ => unreachable!(), } } ``` Compiler -------- - [Added tier 3\* support for the `i686-unknown-uefi` target.][64334] - [Added tier 3 support for the `sparc64-unknown-openbsd` target.][63595] - [rustc will now trim code snippets in diagnostics to fit in your terminal.] [63402] **Note** Cargo currently doesn't use this feature. Refer to [cargo#7315][cargo/7315] to track this feature's progress. - [You can now pass `--show-output` argument to test binaries to print the output of successful tests.][62600] \* Refer to Rust's [platform support page][forge-platform-support] for more information on Rust's tiered platform support. Libraries --------- - [`Vec::new` and `String::new` are now `const` functions.][64028] - [`LinkedList::new` is now a `const` function.][63684] - [`str::len`, `[T]::len` and `str::as_bytes` are now `const` functions.][63770] - [The `abs`, `wrapping_abs`, and `overflowing_abs` numeric functions are now `const`.][63786] Stabilized APIs --------------- - [`Pin::into_inner`] - [`Instant::checked_duration_since`] - [`Instant::saturating_duration_since`] Cargo ----- - [You can now publish git dependencies if supplied with a `version`.] [cargo/7237] - [The `--all` flag has been renamed to `--workspace`.][cargo/7241] Using `--all` is now deprecated. Misc ---- - [You can now pass `-Clinker` to rustdoc to control the linker used for compiling doctests.][63834] Compatibility Notes ------------------- - [Code that was previously accepted by the old borrow checker, but rejected by the NLL borrow checker is now a hard error in Rust 2018.][63565] This was previously a warning, and will also become a hard error in the Rust 2015 edition in the 1.40.0 release. - [`rustdoc` now requires `rustc` to be installed and in the same directory to run tests.][63827] This should improve performance when running a large amount of doctests. - [The `try!` macro will now issue a deprecation warning.][62672] It is recommended to use the `?` operator instead. - [`asinh(-0.0)` now correctly returns `-0.0`.][63698] Previously this returned `0.0`. [62600]: rust-lang/rust#62600 [62672]: rust-lang/rust#62672 [63118]: rust-lang/rust#63118 [63209]: rust-lang/rust#63209 [63402]: rust-lang/rust#63402 [63565]: rust-lang/rust#63565 [63595]: rust-lang/rust#63595 [63684]: rust-lang/rust#63684 [63698]: rust-lang/rust#63698 [63770]: rust-lang/rust#63770 [63786]: rust-lang/rust#63786 [63827]: rust-lang/rust#63827 [63834]: rust-lang/rust#63834 [63927]: rust-lang/rust#63927 [63933]: rust-lang/rust#63933 [63934]: rust-lang/rust#63934 [63938]: rust-lang/rust#63938 [63940]: rust-lang/rust#63940 [63941]: rust-lang/rust#63941 [63945]: rust-lang/rust#63945 [64010]: rust-lang/rust#64010 [64028]: rust-lang/rust#64028 [64334]: rust-lang/rust#64334 [cargo/7237]: rust-lang/cargo#7237 [cargo/7241]: rust-lang/cargo#7241 [cargo/7315]: rust-lang/cargo#7315 [`Pin::into_inner`]: https://doc.rust-lang.org/std/pin/struct.Pin.html#method.into_inner [`Instant::checked_duration_since`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.checked_duration_since [`Instant::saturating_duration_since`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.saturating_duration_since
While working on PR rust-lang#63934, I accidentally reverted to an older version of the PR while working on a rebase. The PR was then merged, not with the later, approved changes, but with earlier, unapproved changes. This PR applies the changes that were *suppoesd* to be mereged in PR rust-lang#63934. All of the proper tests appear to have been merged in PR rust-lang#63934, so this PR adds no new tests Fixes rust-lang#66580
Apply proper commit from PR #63934 While working on PR #63934, I accidentally reverted to an older version of the PR while working on a rebase. The PR was then merged, not with the later, approved changes, but with earlier, unapproved changes. This PR applies the changes that were *suppoesd* to be mereged in PR #63934. All of the proper tests appear to have been merged in PR #63934, so this PR adds no new tests
UPDATE: This PR now treats all opaque types as remote. The original description appears below, but is no longer accurate.
Fixes #63677
RFC 2071 (impl-trait-existential-types) does not explicitly state how
type_alias_impl_trait
should interact with coherence. However, there's only one choice which makes sense - coherence should look at the underlying type (i.e. the "defining" type of theimpl Trait
) of the type alias, just like we do for non-impl Trait
type aliases.Specifically,
impl Trait
type aliases that resolve to a local type should be treated like a local type with respect to coherence (e.g.impl Trait
type aliases which resolve to a foreign type should be treated as a foreign type, and those that resolve to a local type should be treated as a local type).Since neither inherent impls nor direct trait impl (i.e.
impl MyType
orimpl MyTrait for MyType
) are allowed for type aliases, this usually does not come up. Before we ever attempt to do coherence checking, we will have errored out if animpl Trait
type alias was used directly in animpl
clause.However, during trait selection, we sometimes need to prove bounds like
T: Sized
for some typeT
. IfT
is an impl trait type alias, this requires to know the coherence behavior forimpl Trait
type aliases when we perform coherence checking.Note: Since determining the underlying type of an
impl Trait
type alias requires us to perform body type checking, this commit causes us to type check some bodies easier than we otherwise would have. However, since this is done through a query, this shouldn't cause any problemsFor completeness, I've added an additional test of the coherence-related behavior of
impl Trait
type aliases.cc #63063