Skip to content

Commit

Permalink
Auto merge of #797 - lowr:fix/discriminant-kind-panic, r=compiler-errors
Browse files Browse the repository at this point in the history
fix: generalize types before generating built-in `Normalize` clauses

When we generate built-in `Normalize` clauses, `self_ty` in the original goal may contain bound variables that prevent us from using it as-is. We need to universally quantify over the bound variables before passing it to trait-specific clause generators, which we've been failing to do for `DiscriminantKind`.

cc rust-lang/rust-analyzer#15113
  • Loading branch information
bors committed Jun 24, 2023
2 parents 9318f7f + b1c01a8 commit 7c8c3d2
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 28 deletions.
36 changes: 9 additions & 27 deletions chalk-solve/src/clauses/builtin_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,39 +83,21 @@ pub fn add_builtin_assoc_program_clauses<I: Interner>(
well_known: WellKnownTrait,
self_ty: Ty<I>,
) -> Result<(), Floundered> {
match well_known {
// If `self_ty` contains bound vars, we want to universally quantify them.
// `Generalize` collects them for us.
let generalized = generalize::Generalize::apply(db.interner(), self_ty);
builder.push_binders(generalized, |builder, self_ty| match well_known {
WellKnownTrait::FnOnce => {
// If `self_ty` contains bound vars, we want to universally quantify them.
// `Generalize` collects them for us.
let generalized = generalize::Generalize::apply(db.interner(), self_ty);

builder.push_binders(generalized, |builder, self_ty| {
fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty);
Ok(())
})
}
WellKnownTrait::Pointee => {
// If `self_ty` contains bound vars, we want to universally quantify them.
// `Generalize` collects them for us.
let generalized = generalize::Generalize::apply(db.interner(), self_ty);

builder.push_binders(generalized, |builder, self_ty| {
pointee::add_pointee_program_clauses(db, builder, self_ty)?;
Ok(())
})
fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty);
Ok(())
}
WellKnownTrait::Pointee => pointee::add_pointee_program_clauses(db, builder, self_ty),
WellKnownTrait::DiscriminantKind => {
discriminant_kind::add_discriminant_clauses(db, builder, self_ty)
}
WellKnownTrait::Generator => {
let generalized = generalize::Generalize::apply(db.interner(), self_ty);

builder.push_binders(generalized, |builder, self_ty| {
generator::add_generator_program_clauses(db, builder, self_ty)
})
}
WellKnownTrait::Generator => generator::add_generator_program_clauses(db, builder, self_ty),
_ => Ok(()),
}
})
}

/// Returns type of the last field of the input struct, which is useful for `Sized` and related
Expand Down
2 changes: 1 addition & 1 deletion chalk-solve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ pub trait RustIrDatabase<I: Interner>: Debug {
sanitize_debug_name(|f| I::debug_fn_def_id(fn_def_id, f))
}

// Retrieves the discriminant type for a type (mirror of rustc `TyS::discriminant_ty`)
// Retrieves the discriminant type for a type (mirror of rustc `Ty::discriminant_ty`)
fn discriminant_type(&self, ty: Ty<I>) -> Ty<I>;
}

Expand Down
22 changes: 22 additions & 0 deletions tests/test/discriminant_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,25 @@ fn discriminant_kind_assoc() {
}
}
}

#[test]
fn discriminant_kind_with_infer_var() {
test! {
program {
#[lang(discriminant_kind)]
trait DiscriminantKind {
type Discriminant;
}

enum Option<T> {}
}

goal {
exists<T> {
Normalize(<Option<T> as DiscriminantKind>::Discriminant -> isize)
}
} yields {
expect![[r#"Unique; for<?U0> { substitution [?0 := ^0.0] }"#]]
}
}
}

0 comments on commit 7c8c3d2

Please sign in to comment.