Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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