Merge pull request #19182 from ShoyuVanilla/issue-19177

fix: Binding wrong associated type when lowering bounds like `T: Trait<Assoc = U>`
This commit is contained in:
Chayim Refael Friedman 2025-02-22 21:32:46 +00:00 committed by GitHub
commit 9df88ff0f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 7 deletions

View file

@ -10,7 +10,7 @@ use hir_def::{
generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget},
path::{GenericArg, GenericArgs, Path, PathSegment, PathSegments}, path::{GenericArg, GenericArgs, Path, PathSegment, PathSegments},
resolver::{ResolveValueResult, TypeNs, ValueNs}, resolver::{ResolveValueResult, TypeNs, ValueNs},
type_ref::{TypeBound, TypeRef}, type_ref::{TypeBound, TypeRef, TypesMap},
GenericDefId, GenericParamId, ItemContainerId, Lookup, TraitId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TraitId,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
@ -838,15 +838,21 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
(_, ImplTraitLoweringMode::Param | ImplTraitLoweringMode::Variable) => { (_, ImplTraitLoweringMode::Param | ImplTraitLoweringMode::Variable) => {
// Find the generic index for the target of our `bound` // Find the generic index for the target of our `bound`
let target_param_idx = let target_param_idx =
self.ctx.resolver.where_predicates_in_scope().find_map(|(p, _)| { self.ctx.resolver.where_predicates_in_scope().find_map(
match p { |(p, (_, types_map))| match p {
WherePredicate::TypeBound { WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeOrConstParam(idx), target: WherePredicateTypeTarget::TypeOrConstParam(idx),
bound: b, bound: b,
} if b == bound => Some(idx), } if std::ptr::eq::<TypesMap>(
_ => None, self.ctx.types_map,
types_map,
) && bound == b =>
{
Some(idx)
} }
}); _ => None,
},
);
let ty = if let Some(target_param_idx) = target_param_idx { let ty = if let Some(target_param_idx) = target_param_idx {
let mut counter = 0; let mut counter = 0;
let generics = self.ctx.generics().expect("generics in scope"); let generics = self.ctx.generics().expect("generics in scope");

View file

@ -3,7 +3,7 @@ use span::{Edition, EditionedFileId};
use syntax::{TextRange, TextSize}; use syntax::{TextRange, TextSize};
use test_fixture::WithFixture; use test_fixture::WithFixture;
use crate::{db::HirDatabase, test_db::TestDB, Interner, Substitution}; use crate::{db::HirDatabase, mir::MirLowerError, test_db::TestDB, Interner, Substitution};
use super::{interpret_mir, MirEvalError}; use super::{interpret_mir, MirEvalError};
@ -84,6 +84,16 @@ fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic:
assert_eq!(e.is_panic().unwrap_or_else(|| panic!("unexpected error: {e:?}")), expected_panic); assert_eq!(e.is_panic().unwrap_or_else(|| panic!("unexpected error: {e:?}")), expected_panic);
} }
fn check_error_with(
#[rust_analyzer::rust_fixture] ra_fixture: &str,
expect_err: impl FnOnce(MirEvalError) -> bool,
) {
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
let file_id = *file_ids.last().unwrap();
let e = eval_main(&db, file_id).unwrap_err();
assert!(expect_err(e));
}
#[test] #[test]
fn function_with_extern_c_abi() { fn function_with_extern_c_abi() {
check_pass( check_pass(
@ -945,3 +955,27 @@ fn main() {
"#, "#,
); );
} }
#[test]
fn regression_19177() {
check_error_with(
r#"
//- minicore: copy
trait Foo {}
trait Bar {}
trait Baz {}
trait Qux {
type Assoc;
}
fn main<'a, T: Foo + Bar + Baz>(
x: &T,
y: (),
z: &'a dyn Qux<Assoc = T>,
w: impl Foo + Bar,
) {
}
"#,
|e| matches!(e, MirEvalError::MirLowerError(_, MirLowerError::GenericArgNotProvided(..))),
);
}