Comments, another test
This commit is contained in:
parent
2540c2b761
commit
ed30efff3b
3 changed files with 87 additions and 2 deletions
|
@ -235,6 +235,40 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assemble a list of predicates that would be present on a theoretical
|
||||||
|
/// user impl for an object type. These predicates must be checked any time
|
||||||
|
/// we assemble a built-in object candidate for an object type, since they
|
||||||
|
/// are not implied by the well-formedness of the type.
|
||||||
|
///
|
||||||
|
/// For example, given the following traits:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore (theoretical code)
|
||||||
|
/// trait Foo: Baz {
|
||||||
|
/// type Bar: Copy;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// trait Baz {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// For the dyn type `dyn Foo<Item = Ty>`, we can imagine there being a
|
||||||
|
/// pair of theoretical impls:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore (theoretical code)
|
||||||
|
/// impl Foo for dyn Foo<Item = Ty>
|
||||||
|
/// where
|
||||||
|
/// Self: Baz,
|
||||||
|
/// <Self as Foo>::Bar: Copy,
|
||||||
|
/// {
|
||||||
|
/// type Bar = Ty;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl Baz for dyn Foo<Item = Ty> {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// However, in order to make such impls well-formed, we need to do an
|
||||||
|
/// additional step of eagerly folding the associated types in the where
|
||||||
|
/// clauses of the impl. In this example, that means replacing
|
||||||
|
/// `<Self as Foo>::Bar` with `Ty` in the first impl.
|
||||||
pub(crate) fn predicates_for_object_candidate<'tcx>(
|
pub(crate) fn predicates_for_object_candidate<'tcx>(
|
||||||
ecx: &EvalCtxt<'_, 'tcx>,
|
ecx: &EvalCtxt<'_, 'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
@ -247,6 +281,8 @@ pub(crate) fn predicates_for_object_candidate<'tcx>(
|
||||||
tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.substs).predicates,
|
tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.substs).predicates,
|
||||||
);
|
);
|
||||||
for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
|
for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
|
||||||
|
// FIXME(associated_const_equality): Also add associated consts to
|
||||||
|
// the requirements here.
|
||||||
if item.kind == ty::AssocKind::Type {
|
if item.kind == ty::AssocKind::Type {
|
||||||
requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs));
|
requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs));
|
||||||
}
|
}
|
||||||
|
@ -290,13 +326,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
|
||||||
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
|
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
|
||||||
&& let Some(replacement) = self.mapping.get(&alias_ty.def_id)
|
&& let Some(replacement) = self.mapping.get(&alias_ty.def_id)
|
||||||
{
|
{
|
||||||
|
// We may have a case where our object type's projection bound is higher-ranked,
|
||||||
|
// but the where clauses we instantiated are not. We can solve this by instantiating
|
||||||
|
// the binder at the usage site.
|
||||||
let proj = self.ecx.instantiate_binder_with_infer(*replacement);
|
let proj = self.ecx.instantiate_binder_with_infer(*replacement);
|
||||||
// Technically this folder could be fallible?
|
// FIXME: Technically this folder could be fallible?
|
||||||
let nested = self
|
let nested = self
|
||||||
.ecx
|
.ecx
|
||||||
.eq(self.param_env, alias_ty, proj.projection_ty)
|
.eq(self.param_env, alias_ty, proj.projection_ty)
|
||||||
.expect("expected to be able to unify goal projection with dyn's projection");
|
.expect("expected to be able to unify goal projection with dyn's projection");
|
||||||
// Technically we could register these too..
|
// FIXME: Technically we could register these too..
|
||||||
assert!(nested.is_empty(), "did not expect unification to have any nested goals");
|
assert!(nested.is_empty(), "did not expect unification to have any nested goals");
|
||||||
proj.term.ty().unwrap()
|
proj.term.ty().unwrap()
|
||||||
} else {
|
} else {
|
||||||
|
|
27
tests/ui/traits/new-solver/more-object-bound.rs
Normal file
27
tests/ui/traits/new-solver/more-object-bound.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
// From #80800
|
||||||
|
|
||||||
|
trait SuperTrait {
|
||||||
|
type A;
|
||||||
|
type B;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
|
||||||
|
|
||||||
|
fn transmute<A, B>(x: A) -> B {
|
||||||
|
foo::<A, B, dyn Trait<A = A, B = B>>(x)
|
||||||
|
//~^ ERROR type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<A, B, T: ?Sized>(x: T::A) -> B
|
||||||
|
where
|
||||||
|
T: Trait<B = B>,
|
||||||
|
{
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
static X: u8 = 0;
|
||||||
|
fn main() {
|
||||||
|
let x = transmute::<&u8, &[u8; 1_000_000]>(&X);
|
||||||
|
println!("{:?}", x[100_000]);
|
||||||
|
}
|
19
tests/ui/traits/new-solver/more-object-bound.stderr
Normal file
19
tests/ui/traits/new-solver/more-object-bound.stderr
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
error[E0283]: type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
|
||||||
|
--> $DIR/more-object-bound.rs:12:5
|
||||||
|
|
|
||||||
|
LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
|
||||||
|
note: required by a bound in `foo`
|
||||||
|
--> $DIR/more-object-bound.rs:18:8
|
||||||
|
|
|
||||||
|
LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
|
||||||
|
| --- required by a bound in this function
|
||||||
|
LL | where
|
||||||
|
LL | T: Trait<B = B>,
|
||||||
|
| ^^^^^^^^^^^^ required by this bound in `foo`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0283`.
|
Loading…
Add table
Add a link
Reference in a new issue