Skip to content

Commit d7a1a28

Browse files
authored
Rollup merge of rust-lang#138174 - compiler-errors:elaborate-unsize-self-pred, r=BoxyUwU
Elaborate trait assumption in `receiver_is_dispatchable` Fixes rust-lang#138172. See comment on the linked test. Probably not a fix for the general problem, bc I think this may still be incomplete for other weird `where` clauses on the receiver. But 🤷, supertraits seems like an obvious one to fix.
2 parents c6845de + c170d0f commit d7a1a28

File tree

5 files changed

+105
-12
lines changed

5 files changed

+105
-12
lines changed

compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ use super::elaborate;
2424
use crate::infer::TyCtxtInferExt;
2525
pub use crate::traits::DynCompatibilityViolation;
2626
use crate::traits::query::evaluate_obligation::InferCtxtExt;
27-
use crate::traits::{MethodViolationCode, Obligation, ObligationCause, util};
27+
use crate::traits::{
28+
MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util,
29+
};
2830

2931
/// Returns the dyn-compatibility violations that affect HIR ty lowering.
3032
///
@@ -579,8 +581,8 @@ fn receiver_is_dispatchable<'tcx>(
579581
let unsized_receiver_ty =
580582
receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
581583

582-
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
583-
// `U: ?Sized` is already implied here
584+
// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
585+
// its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
584586
let param_env = {
585587
let param_env = tcx.param_env(method.def_id);
586588

@@ -598,10 +600,13 @@ fn receiver_is_dispatchable<'tcx>(
598600
ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
599601
};
600602

601-
let caller_bounds =
602-
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
603-
604-
ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds))
603+
normalize_param_env_or_error(
604+
tcx,
605+
ty::ParamEnv::new(tcx.mk_clauses_from_iter(
606+
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
607+
)),
608+
ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
609+
)
605610
};
606611

607612
// Receiver: DispatchFromDyn<Receiver[Self => U]>

tests/ui/associated-types/issue-59324.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub trait ThriftService<Bug: NotFoo>:
1515
{
1616
fn get_service(
1717
//~^ ERROR the trait bound `Bug: Foo` is not satisfied
18+
//~| ERROR the trait bound `Bug: Foo` is not satisfied
1819
&self,
1920
) -> Self::AssocType;
2021
//~^ ERROR the trait bound `Bug: Foo` is not satisfied

tests/ui/associated-types/issue-59324.stderr

+16-5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied
3232
|
3333
LL | / fn get_service(
3434
LL | |
35+
LL | |
3536
LL | | &self,
3637
LL | | ) -> Self::AssocType;
3738
| |_________________________^ the trait `Foo` is not implemented for `Bug`
@@ -41,8 +42,18 @@ help: consider further restricting type parameter `Bug` with trait `Foo`
4142
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
4243
| +++++
4344

45+
error[E0277]: the trait bound `Bug: Foo` is not satisfied
46+
--> $DIR/issue-59324.rs:16:5
47+
|
48+
LL | / fn get_service(
49+
LL | |
50+
LL | |
51+
LL | | &self,
52+
LL | | ) -> Self::AssocType;
53+
| |_________________________^ the trait `Foo` is not implemented for `Bug`
54+
4455
error[E0277]: the trait bound `(): Foo` is not satisfied
45-
--> $DIR/issue-59324.rs:23:29
56+
--> $DIR/issue-59324.rs:24:29
4657
|
4758
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
4859
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
@@ -54,7 +65,7 @@ LL | pub trait Foo: NotFoo {
5465
| ^^^^^^^^^^^^^^^^^^^^^
5566

5667
error[E0277]: the trait bound `Bug: Foo` is not satisfied
57-
--> $DIR/issue-59324.rs:19:10
68+
--> $DIR/issue-59324.rs:20:10
5869
|
5970
LL | ) -> Self::AssocType;
6071
| ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
@@ -65,7 +76,7 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
6576
| +++++
6677

6778
error[E0277]: the trait bound `(): Foo` is not satisfied
68-
--> $DIR/issue-59324.rs:23:29
79+
--> $DIR/issue-59324.rs:24:29
6980
|
7081
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
7182
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
@@ -78,7 +89,7 @@ LL | pub trait Foo: NotFoo {
7889
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
7990

8091
error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time
81-
--> $DIR/issue-59324.rs:23:29
92+
--> $DIR/issue-59324.rs:24:29
8293
|
8394
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
8495
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -95,6 +106,6 @@ help: function arguments must have a statically known size, borrowed types alway
95106
LL | fn with_factory<H>(factory: &dyn ThriftService<()>) {}
96107
| +
97108

98-
error: aborting due to 7 previous errors
109+
error: aborting due to 8 previous errors
99110

100111
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//@ check-pass
2+
3+
#![feature(derive_coerce_pointee)]
4+
#![feature(arbitrary_self_types)]
5+
6+
use std::ops::Deref;
7+
use std::marker::CoercePointee;
8+
use std::sync::Arc;
9+
10+
trait MyTrait<T> {}
11+
12+
#[derive(CoercePointee)]
13+
#[repr(transparent)]
14+
struct MyArc<T: ?Sized + MyTrait<u8>>(Arc<T>);
15+
16+
impl<T: ?Sized + MyTrait<u8>> Deref for MyArc<T> {
17+
type Target = T;
18+
fn deref(&self) -> &T {
19+
&self.0
20+
}
21+
}
22+
23+
trait Mirror {
24+
type Assoc;
25+
}
26+
impl<T> Mirror for T {
27+
type Assoc = T;
28+
}
29+
30+
// This is variant on "tests/ui/self/dyn-dispatch-requires-supertrait.rs" but with
31+
// a supertrait that requires normalization to match the pred in the old solver.
32+
trait MyOtherTrait: MyTrait<<u8 as Mirror>::Assoc> {
33+
fn foo(self: MyArc<Self>);
34+
}
35+
36+
fn test(_: MyArc<dyn MyOtherTrait>) {}
37+
38+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//@ check-pass
2+
3+
#![feature(derive_coerce_pointee)]
4+
#![feature(arbitrary_self_types)]
5+
6+
use std::ops::Deref;
7+
use std::marker::CoercePointee;
8+
use std::sync::Arc;
9+
10+
trait MyTrait {}
11+
12+
#[derive(CoercePointee)]
13+
#[repr(transparent)]
14+
struct MyArc<T>
15+
where
16+
T: MyTrait + ?Sized,
17+
{
18+
inner: Arc<T>
19+
}
20+
21+
impl<T: MyTrait + ?Sized> Deref for MyArc<T> {
22+
type Target = T;
23+
fn deref(&self) -> &T {
24+
&self.inner
25+
}
26+
}
27+
28+
// Proving that `MyArc<Self>` is dyn-dispatchable requires proving `MyArc<T>` implements
29+
// `DispatchFromDyn<MyArc<U>>`. The `DispatchFromDyn` impl that is generated from the
30+
// `CoercePointee` implementation requires the pointee impls `MyTrait`, but previously we
31+
// were only assuming the pointee impl'd `MyOtherTrait`. Elaboration comes to the rescue here.
32+
trait MyOtherTrait: MyTrait {
33+
fn foo(self: MyArc<Self>);
34+
}
35+
36+
fn test(_: MyArc<dyn MyOtherTrait>) {}
37+
38+
fn main() {}

0 commit comments

Comments
 (0)