Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/elaborator/path_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
/// A function call on a type that resolves to a trait method, for example `SomeType::from(...)`
/// or `SomeType::<A, B>::from(..).`. The main difference from `TraitFunction` is that this
/// holds the self type, in this case `SomeType`.
TypeTraitFunction(Type, TraitId, Option<Turbofish>, FuncId),
TypeTraitFunction(Type, TraitId, FuncId),
/// A function call on a primitive type, for example `u64::from(...)` or `u64::<A, B>::from(..)`.
PrimitiveFunction(PrimitiveType, Option<Turbofish>, FuncId),
}
Expand All @@ -62,7 +62,7 @@
| PathResolutionItem::SelfMethod(func_id)
| PathResolutionItem::TypeAliasFunction(_, _, func_id)
| PathResolutionItem::TraitFunction(_, _, func_id)
| PathResolutionItem::TypeTraitFunction(_, _, _, func_id)
| PathResolutionItem::TypeTraitFunction(_, _, func_id)
| PathResolutionItem::PrimitiveFunction(_, _, func_id) => Some(*func_id),
PathResolutionItem::Module(..)
| PathResolutionItem::Type(..)
Expand Down Expand Up @@ -125,7 +125,7 @@
FoundMultipleTraitMethods(Vec<(TraitId, Ident)>),
}

/// Determines whether datatypes found along a path are to be marked as referenced

Check warning on line 128 in compiler/noirc_frontend/src/elaborator/path_resolution.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (datatypes)
/// or used (see [`crate::usage_tracker::UsageTracker::mark_as_referenced`]
/// and [`crate::usage_tracker::UsageTracker::mark_as_used`])
///
Expand Down Expand Up @@ -157,7 +157,7 @@
MarkAsUsed,
}

/// Depenending on where a path appears in the source code it should either resolve to a type

Check warning on line 160 in compiler/noirc_frontend/src/elaborator/path_resolution.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (Depenending)
/// or a value. For example, in `let x: Foo::Bar = Foo::Bar {}` both `Foo::Bar` should resolve to
/// types, never values. On the other hand, in `Foo::Bar()` `Foo::Bar` should resolve to a value,
/// typically a function.
Expand Down
210 changes: 81 additions & 129 deletions compiler/noirc_frontend/src/elaborator/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,28 @@ use crate::{
ERROR_IDENT, Expression, ExpressionKind, GenericTypeArgs, Ident, ItemVisibility, Path,
PathSegment, Pattern, TypePath,
},
elaborator::types::SELF_TYPE_NAME,
elaborator::{
Turbofish,
types::{SELF_TYPE_NAME, TraitPathResolutionMethod},
},
hir::{
def_collector::dc_crate::CompilationError,
resolution::{errors::ResolverError, import::PathResolutionError},
type_check::{
Source, TypeCheckError,
generics::{FmtstrPrimitiveType, Generic, StrPrimitiveType},
},
type_check::{Source, TypeCheckError},
},
hir_def::{
expr::{HirExpression, HirIdent, HirLiteral, HirMethodReference, ImplKind, TraitMethod},
stmt::HirPattern,
},
node_interner::{
DefinitionId, DefinitionInfo, DefinitionKind, ExprId, FuncId, GlobalId, TraitImplKind,
TypeAliasId, TypeId,
},
signed_field::SignedField,
};

use super::{
Elaborator, PrimitiveType, ResolverMeta,
Elaborator, ResolverMeta,
path_resolution::{PathResolutionItem, TypedPath, TypedPathSegment},
};

Expand Down Expand Up @@ -768,15 +769,7 @@ impl Elaborator<'_> {
) -> (Vec<Type>, Option<Type>) {
match item {
PathResolutionItem::Method(struct_id, Some(generics), _func_id) => {
let struct_type = self.interner.get_type(struct_id);
let struct_type = struct_type.borrow();
let struct_generics = struct_type.instantiate(self.interner);
let generics = self.resolve_struct_turbofish_generics(
&struct_type,
struct_generics,
Some(generics.generics),
generics.location,
);
let generics = self.resolve_struct_id_turbofish_generics(struct_id, Some(generics));
(generics, None)
}
PathResolutionItem::SelfMethod(_) => {
Expand All @@ -790,21 +783,8 @@ impl Elaborator<'_> {
PathResolutionItem::TypeAliasFunction(type_alias_id, generics, _func_id) => {
let type_alias = self.interner.get_type_alias(type_alias_id);
let type_alias = type_alias.borrow();
let alias_generics = vecmap(&type_alias.generics, |generic| {
self.interner.next_type_variable_with_kind(generic.kind())
});

// First solve the generics on the alias, if any
let generics = if let Some(generics) = generics {
self.resolve_alias_turbofish_generics(
&type_alias,
alias_generics,
Some(generics.generics),
generics.location,
)
} else {
alias_generics
};
let generics =
self.resolve_type_alias_id_turbofish_generics(type_alias_id, generics);

// Now instantiate the underlying struct or alias with those generics, the struct might
// have more generics than those in the alias, like in this example:
Expand All @@ -828,101 +808,19 @@ impl Elaborator<'_> {
);
(generics, None)
}
PathResolutionItem::TypeTraitFunction(self_type, trait_id, generics, _func_id) => {
let generics = if let Some(generics) = generics {
let trait_ = self.interner.get_trait(trait_id);
let kinds = vecmap(&trait_.generics, |generic| generic.kind());
let trait_generics = vecmap(&kinds, |kind| {
self.interner.next_type_variable_with_kind(kind.clone())
});

self.resolve_trait_turbofish_generics(
&trait_.name.to_string(),
kinds,
trait_generics,
Some(generics.generics),
generics.location,
)
} else {
Vec::new()
};
(generics, Some(self_type))
PathResolutionItem::TypeTraitFunction(self_type, _trait_id, _func_id) => {
(Vec::new(), Some(self_type))
}
PathResolutionItem::PrimitiveFunction(primitive_type, turbofish, _func_id) => {
let generics = match primitive_type {
PrimitiveType::Bool
| PrimitiveType::CtString
| PrimitiveType::Expr
| PrimitiveType::Field
| PrimitiveType::FunctionDefinition
| PrimitiveType::I8
| PrimitiveType::I16
| PrimitiveType::I32
| PrimitiveType::I64
| PrimitiveType::U1
| PrimitiveType::U8
| PrimitiveType::U16
| PrimitiveType::U32
| PrimitiveType::U64
| PrimitiveType::U128
| PrimitiveType::Module
| PrimitiveType::Quoted
| PrimitiveType::StructDefinition
| PrimitiveType::TraitConstraint
| PrimitiveType::TraitDefinition
| PrimitiveType::TraitImpl
| PrimitiveType::TypeDefinition
| PrimitiveType::TypedExpr
| PrimitiveType::Type
| PrimitiveType::UnresolvedType => {
if let Some(turbofish) = turbofish {
self.push_err(CompilationError::TypeError(
TypeCheckError::GenericCountMismatch {
item: primitive_type.name().to_string(),
expected: 0,
found: turbofish.generics.len(),
location: turbofish.location,
},
));
}
Vec::new()
let typ = self.instantiate_primitive_type_with_turbofish(primitive_type, turbofish);
let generics = match typ {
Type::String(length) => {
vec![*length]
}
PrimitiveType::Str => {
if let Some(turbofish) = turbofish {
let item = StrPrimitiveType;
let item_generic_kinds = item.generic_kinds(self.interner);
let kind = item_generic_kinds[0].clone();
let generics = vec![self.interner.next_type_variable_with_kind(kind)];
self.resolve_item_turbofish_generics(
item.item_kind(),
&item.item_name(self.interner),
item_generic_kinds,
generics,
Some(turbofish.generics),
turbofish.location,
)
} else {
Vec::new()
}
}
PrimitiveType::Fmtstr => {
if let Some(turbofish) = turbofish {
let item_generic_kinds =
FmtstrPrimitiveType {}.generic_kinds(self.interner);
let kind = item_generic_kinds[0].clone();
let generics = vec![self.interner.next_type_variable_with_kind(kind)];
self.resolve_item_turbofish_generics(
"primitive type",
"fmtstr",
item_generic_kinds,
generics,
Some(turbofish.generics),
turbofish.location,
)
} else {
Vec::new()
}
Type::FmtString(length, element) => {
vec![*length, *element]
}
_ => Vec::new(),
};
(generics, None)
}
Expand All @@ -938,20 +836,74 @@ impl Elaborator<'_> {
}
}

pub(super) fn resolve_struct_id_turbofish_generics(
&mut self,
struct_id: TypeId,
mut turbofish: Option<Turbofish>,
) -> Vec<Type> {
let struct_type = self.interner.get_type(struct_id);
let struct_type = struct_type.borrow();
let struct_generics = struct_type.instantiate(self.interner);
if let Some(turbofish) = turbofish.take() {
self.resolve_struct_turbofish_generics(
&struct_type,
struct_generics,
Some(turbofish.generics),
turbofish.location,
)
} else {
struct_generics
}
}

pub(super) fn resolve_type_alias_id_turbofish_generics(
&mut self,
type_alias_id: TypeAliasId,
generics: Option<Turbofish>,
) -> Vec<Type> {
let type_alias = self.interner.get_type_alias(type_alias_id);
let type_alias = type_alias.borrow();
let alias_generics = vecmap(&type_alias.generics, |generic| {
self.interner.next_type_variable_with_kind(generic.kind())
});

if let Some(generics) = generics {
self.resolve_alias_turbofish_generics(
&type_alias,
alias_generics,
Some(generics.generics),
generics.location,
)
} else {
alias_generics
}
}

fn resolve_variable(&mut self, path: TypedPath) -> (HirIdent, Option<PathResolutionItem>) {
if let Some(trait_path_resolution) = self.resolve_trait_generic_path(&path) {
for error in trait_path_resolution.errors {
self.push_err(error);
}

return (
HirIdent {
location: path.location,
id: self.interner.trait_method_id(trait_path_resolution.method.method_id),
impl_kind: ImplKind::TraitMethod(trait_path_resolution.method),
},
trait_path_resolution.item,
);
return match trait_path_resolution.method {
TraitPathResolutionMethod::NotATraitMethod(func_id) => (
HirIdent {
location: path.location,
id: self.interner.function_definition_id(func_id),
impl_kind: ImplKind::NotATraitMethod,
},
trait_path_resolution.item,
),

TraitPathResolutionMethod::TraitMethod(trait_method) => (
HirIdent {
location: path.location,
id: self.interner.trait_method_id(trait_method.method_id),
impl_kind: ImplKind::TraitMethod(trait_method),
},
trait_path_resolution.item,
),
};
}

// If the Path is being used as an Expression, then it is referring to a global from a separate module
Expand Down
Loading
Loading