Skip to content

Commit 1b32e5d

Browse files
committed
Auto merge of #778 - lowr:fix/projection-ty-self, r=jackh726
Fix `Self` type retrieval from `ProjectionTy` As I understand it, a `ProjectionTy`'s substitution is in the order of the args for the associated type, and then the args for its parent (i.e. impl or trait). `ProjectionTy::self_type_parameter()` has been returning the first type argument in the substitution, which is not the `Self` type its callers would expect when the associated type has its own type parameters. The added test shows the problem: it fails in current master as the recursive solver reports ambiguity after it gets wrong `Self` type and flounders in [here](https://github.com/rust-lang/chalk/blob/c8bc9aae199d5c424044f6608eb1e553648bce2c/chalk-solve/src/clauses.rs#L615-L622). It hasn't been uncovered because all the traits in tests for GATs are not `#[non_enumerable]` (and rust-analyzer hasn't implemented GATs yet).
2 parents c8bc9aa + 7bc0c59 commit 1b32e5d

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

chalk-ir/src/lib.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,17 +1643,6 @@ pub struct ProjectionTy<I: Interner> {
16431643

16441644
impl<I: Interner> Copy for ProjectionTy<I> where I::InternedSubstitution: Copy {}
16451645

1646-
impl<I: Interner> ProjectionTy<I> {
1647-
/// Gets the type parameters of the `Self` type in this alias type.
1648-
pub fn self_type_parameter(&self, interner: I) -> Ty<I> {
1649-
self.substitution
1650-
.iter(interner)
1651-
.find_map(move |p| p.ty(interner))
1652-
.unwrap()
1653-
.clone()
1654-
}
1655-
}
1656-
16571646
/// An opaque type `opaque type T<..>: Trait = HiddenTy`.
16581647
#[derive(Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable, HasInterner)]
16591648
pub struct OpaqueTy<I: Interner> {

chalk-solve/src/clauses.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -603,11 +603,12 @@ pub fn program_clauses_that_could_match<I: Interner>(
603603
// ```
604604
let associated_ty_datum = db.associated_ty_data(proj.associated_ty_id);
605605
let trait_id = associated_ty_datum.trait_id;
606-
let trait_parameters = db.trait_parameters_from_projection(proj);
606+
let trait_ref = db.trait_ref_from_projection(proj);
607+
let trait_parameters = trait_ref.substitution.as_parameters(interner);
607608

608609
let trait_datum = db.trait_datum(trait_id);
609610

610-
let self_ty = proj.self_type_parameter(interner);
611+
let self_ty = trait_ref.self_type_parameter(interner);
611612
if let TyKind::InferenceVar(_, _) = self_ty.kind(interner) {
612613
panic!("Inference vars not allowed when getting program clauses");
613614
}
@@ -804,10 +805,11 @@ fn push_alias_alias_eq_clause<I: Interner>(
804805
alias: AliasTy<I>,
805806
) {
806807
let interner = builder.interner();
807-
assert_eq!(
808-
*projection_ty.self_type_parameter(interner).kind(interner),
809-
TyKind::Alias(alias.clone())
810-
);
808+
let self_ty = builder
809+
.db
810+
.trait_ref_from_projection(&projection_ty)
811+
.self_type_parameter(interner);
812+
assert_eq!(*self_ty.kind(interner), TyKind::Alias(alias.clone()));
811813

812814
// TODO: instead generate clauses without reference to the specific type parameters of the goal?
813815
let generalized = generalize::Generalize::apply(interner, (projection_ty, ty, alias));

chalk-solve/src/rust_ir.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,11 @@ pub struct FnDefDatumBound<I: Interner> {
214214
}
215215

216216
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
217+
// FIXME: unignore the doctest below when GATs hit stable.
217218
/// A rust intermediate representation (rust_ir) of a Trait Definition. For
218219
/// example, given the following rust code:
219220
///
220-
/// ```compile_fail
221+
/// ```ignore
221222
/// use std::fmt::Debug;
222223
///
223224
/// trait Foo<T>

tests/test/projection.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,33 @@ fn forall_projection_gat() {
687687
}
688688
}
689689

690+
#[test]
691+
fn gat_in_non_enumerable_trait() {
692+
test! {
693+
program {
694+
#[non_enumerable]
695+
trait Deref { }
696+
697+
#[non_enumerable]
698+
trait PointerFamily {
699+
type Pointer<T>: Deref;
700+
}
701+
}
702+
703+
goal {
704+
forall<T> {
705+
forall<U> {
706+
if (T: PointerFamily) {
707+
<T as PointerFamily>::Pointer<U>: Deref
708+
}
709+
}
710+
}
711+
} yields {
712+
expect![[r#"Unique"#]]
713+
}
714+
}
715+
}
716+
690717
#[test]
691718
fn normalize_under_binder() {
692719
test! {

0 commit comments

Comments
 (0)