Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Wrong BoundVar index when lowering impl trait parameter of parent generics #17916

Merged
merged 1 commit into from
Aug 17, 2024

Conversation

ShoyuVanilla
Copy link
Member

@ShoyuVanilla ShoyuVanilla commented Aug 17, 2024

Fixes #17711

From the following test code;

//- minicore: deref
use core::ops::Deref;

struct Struct<'a, T>(&'a T);

trait Trait {}

impl<'a, T: Deref<Target = impl Trait>> Struct<'a, T> {
    fn foo(&self) -> &Self { self }

    fn bar(&self) {
        let _ = self.foo();
    }

}

when we call register_obligations_for_call for let _ = self.foo();,

fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
let callable_ty = self.resolve_ty_shallow(callable_ty);
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
let def: CallableDefId = from_chalk(self.db, *fn_def);
let generic_predicates =
self.db.generic_predicates(GenericDefId::from_callable(self.db.upcast(), def));
for predicate in generic_predicates.iter() {
let (predicate, binders) = predicate
.clone()
.substitute(Interner, parameters)
.into_value_and_skipped_binders();
always!(binders.len(Interner) == 0); // quantified where clauses not yet handled
self.push_obligation(predicate.cast(Interner));
}

we are querying generic_predicates and it has T: Deref<Target = impl Trait> predicate from the parent impl Struct;

ImplTraitLoweringState::Variable(counter) => {
let idx = counter.get();
// Count the number of `impl Trait` things that appear within our bounds.
// Since t hose have been emitted as implicit type args already.
counter.set(idx + count_impl_traits(type_ref) as u16);
let (
_parent_params,
self_param,
type_params,
const_params,
_impl_trait_params,
lifetime_params,
) = self
.generics()
.expect("variable impl trait lowering must be in a generic def")
.provenance_split();
TyKind::BoundVar(BoundVar::new(
self.in_binders,
idx as usize
+ self_param as usize
+ type_params
+ const_params
+ lifetime_params,
))
.intern(Interner)

but as we can see above, lowering TypeRef = impl Trait doesn't take into account the parent generic parameters, so the BoundVar index here is 0, as fn foo has no generic args other than parent's,

But this BoundVar is pointing at 'a in <'a, T: Deref<Target = impl Trait>>.
So, in the first code reference register_obligations_for_call's L:1948 - .substitute(Interner, parameters), we are substituting 'a with Ty, not Lifetime and this makes panic inside the chalk.

This PR fixes this wrong BoundVar index in such cases

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 17, 2024
@Veykril
Copy link
Member

Veykril commented Aug 17, 2024

Thanks!
@bors r+

@bors
Copy link
Contributor

bors commented Aug 17, 2024

📌 Commit d7431ec has been approved by Veykril

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Aug 17, 2024

⌛ Testing commit d7431ec with merge 469b062...

@bors
Copy link
Contributor

bors commented Aug 17, 2024

☀️ Test successful - checks-actions
Approved by: Veykril
Pushing 469b062 to master...

@bors bors merged commit 469b062 into rust-lang:master Aug 17, 2024
11 checks passed
@ShoyuVanilla ShoyuVanilla deleted the issue-17711 branch August 17, 2024 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

panicked: mismatched kinds in substitution
4 participants