|
1 | 1 | use iter_extended::vecmap; |
2 | 2 | use noirc_errors::Location; |
3 | 3 | use rustc_hash::FxHashMap as HashMap; |
4 | | -use std::collections::HashSet; |
| 4 | +use std::{collections::HashSet, rc::Rc}; |
5 | 5 |
|
6 | 6 | use crate::{ |
7 | 7 | GenericTypeVars, Shared, Type, TypeBindings, |
@@ -316,17 +316,31 @@ impl NodeInterner { |
316 | 316 | // Match associated types by name, not position |
317 | 317 | let associated_types_unify = trait_associated_types.iter().all(|trait_generic| { |
318 | 318 | // Find the matching impl generic by name |
319 | | - let Some(impl_generic) = impl_trait_generics |
| 319 | + let Some(named_impl_generic) = impl_trait_generics |
320 | 320 | .named |
321 | 321 | .iter() |
322 | 322 | .find(|impl_g| impl_g.name.as_str() == trait_generic.name.as_str()) |
323 | 323 | else { |
324 | 324 | // If the impl doesn't have this associated type, it doesn't match |
325 | 325 | return false; |
326 | 326 | }; |
327 | | - let impl_generic2 = impl_generic.typ.force_substitute(&instantiation_bindings); |
328 | | - trait_generic.typ.try_unify(&impl_generic2, &mut fresh_bindings).is_ok() |
| 327 | + |
| 328 | + let mut impl_generic = |
| 329 | + named_impl_generic.typ.force_substitute(&instantiation_bindings); |
| 330 | + |
| 331 | + // If the implementation is just a free type variable, it will bind to anything. |
| 332 | + // By turning it we can make sure it won't bind to other associated types. |
| 333 | + if let Type::TypeVariable(v) = &impl_generic { |
| 334 | + if v.borrow().is_unbound() { |
| 335 | + impl_generic = v |
| 336 | + .clone() |
| 337 | + .into_named_generic(&Rc::new(named_impl_generic.name.to_string()), None) |
| 338 | + } |
| 339 | + } |
| 340 | + |
| 341 | + trait_generic.typ.try_unify(&impl_generic, &mut fresh_bindings).is_ok() |
329 | 342 | }); |
| 343 | + |
330 | 344 | if !associated_types_unify { |
331 | 345 | continue; |
332 | 346 | } |
|
0 commit comments