Skip to content

Commit

Permalink
fix: Allow implicit associated types on integer type kinds (#7078)
Browse files Browse the repository at this point in the history
Co-authored-by: Ary Borenszweig <[email protected]>
  • Loading branch information
jfecher and asterite authored Jan 15, 2025
1 parent 1273ea4 commit f2a6d10
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 17 deletions.
30 changes: 22 additions & 8 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ use std::{
rc::Rc,
};

use crate::{
ast::ItemVisibility, graph::CrateGraph, hir_def::traits::ResolvedTraitBound,
node_interner::GlobalValue, usage_tracker::UsageTracker, StructField, StructType, TypeBindings,
};
use crate::{
ast::{
BlockExpression, FunctionKind, GenericTypeArgs, Ident, NoirFunction, NoirStruct, Param,
Expand Down Expand Up @@ -41,6 +37,14 @@ use crate::{
token::SecondaryAttribute,
Shared, Type, TypeVariable,
};
use crate::{
ast::{ItemVisibility, UnresolvedType},
graph::CrateGraph,
hir_def::traits::ResolvedTraitBound,
node_interner::GlobalValue,
usage_tracker::UsageTracker,
StructField, StructType, TypeBindings,
};

mod comptime;
mod expressions;
Expand Down Expand Up @@ -766,7 +770,9 @@ impl<'context> Elaborator<'context> {
) -> Vec<ResolvedGeneric> {
where_clause
.iter_mut()
.flat_map(|constraint| self.add_missing_named_generics(&mut constraint.trait_bound))
.flat_map(|constraint| {
self.add_missing_named_generics(&constraint.typ, &mut constraint.trait_bound)
})
.collect()
}

Expand All @@ -782,7 +788,11 @@ impl<'context> Elaborator<'context> {
///
/// with a vector of `<A, B>` returned so that the caller can then modify the function to:
/// `fn foo<T, A, B>() where T: Foo<Bar = A, Baz = B> { ... }`
fn add_missing_named_generics(&mut self, bound: &mut TraitBound) -> Vec<ResolvedGeneric> {
fn add_missing_named_generics(
&mut self,
object: &UnresolvedType,
bound: &mut TraitBound,
) -> Vec<ResolvedGeneric> {
let mut added_generics = Vec::new();

let Ok(item) = self.resolve_path_or_error(bound.trait_path.clone()) else {
Expand All @@ -796,6 +806,8 @@ impl<'context> Elaborator<'context> {
let the_trait = self.get_trait_mut(trait_id);

if the_trait.associated_types.len() > bound.trait_generics.named_args.len() {
let trait_name = the_trait.name.to_string();

for associated_type in &the_trait.associated_types.clone() {
if !bound
.trait_generics
Expand All @@ -806,10 +818,12 @@ impl<'context> Elaborator<'context> {
// This generic isn't contained in the bound's named arguments,
// so add it by creating a fresh type variable.
let new_generic_id = self.interner.next_type_variable_id();
let type_var = TypeVariable::unbound(new_generic_id, Kind::Normal);
let kind = associated_type.type_var.kind();
let type_var = TypeVariable::unbound(new_generic_id, kind);

let span = bound.trait_path.span;
let name = associated_type.name.clone();
let name = format!("<{object} as {trait_name}>::{}", associated_type.name);
let name = Rc::new(name);
let typ = Type::NamedGeneric(type_var.clone(), name.clone());
let typ = self.interner.push_quoted_type(typ);
let typ = UnresolvedTypeData::Resolved(typ).with_span(span);
Expand Down
16 changes: 7 additions & 9 deletions test_programs/compile_success_empty/serialize/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ trait Serialize {
fn serialize(self) -> [Field; Self::Size];
}

impl<A, B, let AS: u32, let BS: u32> Serialize for (A, B)
impl<A, B> Serialize for (A, B)
where
A: Serialize<Size = AS>,
B: Serialize<Size = BS>,
A: Serialize,
B: Serialize,
{
// let Size = <A as Serialize>::Size + <B as Serialize>::Size;
let Size: u32 = AS + BS;
let Size = <A as Serialize>::Size + <B as Serialize>::Size;

fn serialize(self: Self) -> [Field; Self::Size] {
let mut array: [Field; Self::Size] = std::mem::zeroed();
Expand All @@ -28,12 +27,11 @@ where
}
}

impl<T, let N: u32, let TS: u32> Serialize for [T; N]
impl<T, let N: u32> Serialize for [T; N]
where
T: Serialize<Size = TS>,
T: Serialize,
{
// let Size = <T as Serialize>::Size * N;
let Size: u32 = TS * N;
let Size = <T as Serialize>::Size * N;

fn serialize(self: Self) -> [Field; Self::Size] {
let mut array: [Field; Self::Size] = std::mem::zeroed();
Expand Down

0 comments on commit f2a6d10

Please sign in to comment.