Skip to content

Commit ed30eff

Browse files
Comments, another test
1 parent 2540c2b commit ed30eff

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs

+41-2
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,40 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
235235
}
236236
}
237237

238+
/// Assemble a list of predicates that would be present on a theoretical
239+
/// user impl for an object type. These predicates must be checked any time
240+
/// we assemble a built-in object candidate for an object type, since they
241+
/// are not implied by the well-formedness of the type.
242+
///
243+
/// For example, given the following traits:
244+
///
245+
/// ```rust,ignore (theoretical code)
246+
/// trait Foo: Baz {
247+
/// type Bar: Copy;
248+
/// }
249+
///
250+
/// trait Baz {}
251+
/// ```
252+
///
253+
/// For the dyn type `dyn Foo<Item = Ty>`, we can imagine there being a
254+
/// pair of theoretical impls:
255+
///
256+
/// ```rust,ignore (theoretical code)
257+
/// impl Foo for dyn Foo<Item = Ty>
258+
/// where
259+
/// Self: Baz,
260+
/// <Self as Foo>::Bar: Copy,
261+
/// {
262+
/// type Bar = Ty;
263+
/// }
264+
///
265+
/// impl Baz for dyn Foo<Item = Ty> {}
266+
/// ```
267+
///
268+
/// However, in order to make such impls well-formed, we need to do an
269+
/// additional step of eagerly folding the associated types in the where
270+
/// clauses of the impl. In this example, that means replacing
271+
/// `<Self as Foo>::Bar` with `Ty` in the first impl.
238272
pub(crate) fn predicates_for_object_candidate<'tcx>(
239273
ecx: &EvalCtxt<'_, 'tcx>,
240274
param_env: ty::ParamEnv<'tcx>,
@@ -247,6 +281,8 @@ pub(crate) fn predicates_for_object_candidate<'tcx>(
247281
tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.substs).predicates,
248282
);
249283
for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
284+
// FIXME(associated_const_equality): Also add associated consts to
285+
// the requirements here.
250286
if item.kind == ty::AssocKind::Type {
251287
requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs));
252288
}
@@ -290,13 +326,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
290326
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
291327
&& let Some(replacement) = self.mapping.get(&alias_ty.def_id)
292328
{
329+
// We may have a case where our object type's projection bound is higher-ranked,
330+
// but the where clauses we instantiated are not. We can solve this by instantiating
331+
// the binder at the usage site.
293332
let proj = self.ecx.instantiate_binder_with_infer(*replacement);
294-
// Technically this folder could be fallible?
333+
// FIXME: Technically this folder could be fallible?
295334
let nested = self
296335
.ecx
297336
.eq(self.param_env, alias_ty, proj.projection_ty)
298337
.expect("expected to be able to unify goal projection with dyn's projection");
299-
// Technically we could register these too..
338+
// FIXME: Technically we could register these too..
300339
assert!(nested.is_empty(), "did not expect unification to have any nested goals");
301340
proj.term.ty().unwrap()
302341
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// From #80800
3+
4+
trait SuperTrait {
5+
type A;
6+
type B;
7+
}
8+
9+
trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
10+
11+
fn transmute<A, B>(x: A) -> B {
12+
foo::<A, B, dyn Trait<A = A, B = B>>(x)
13+
//~^ ERROR type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
14+
}
15+
16+
fn foo<A, B, T: ?Sized>(x: T::A) -> B
17+
where
18+
T: Trait<B = B>,
19+
{
20+
x
21+
}
22+
23+
static X: u8 = 0;
24+
fn main() {
25+
let x = transmute::<&u8, &[u8; 1_000_000]>(&X);
26+
println!("{:?}", x[100_000]);
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0283]: type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
2+
--> $DIR/more-object-bound.rs:12:5
3+
|
4+
LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
8+
note: required by a bound in `foo`
9+
--> $DIR/more-object-bound.rs:18:8
10+
|
11+
LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
12+
| --- required by a bound in this function
13+
LL | where
14+
LL | T: Trait<B = B>,
15+
| ^^^^^^^^^^^^ required by this bound in `foo`
16+
17+
error: aborting due to previous error
18+
19+
For more information about this error, try `rustc --explain E0283`.

0 commit comments

Comments
 (0)