Skip to content

Commit

Permalink
Add missing tokens inside turbofish (FuelLabs#3847)
Browse files Browse the repository at this point in the history
  • Loading branch information
IGI-111 authored Jan 24, 2023
1 parent d1a3f07 commit 5c4e3b4
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 69 deletions.
1 change: 1 addition & 0 deletions sway-core/src/ir_generation/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ impl<'eng> FnCompiler<'eng> {
function_decl_id,
self_state_idx,
selector,
type_binding: _,
} => {
if let Some(metadata) = selector {
self.compile_contract_call(
Expand Down
3 changes: 3 additions & 0 deletions sway-core/src/language/ty/expression/expression_variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub enum TyExpressionVariant {
/// there is no selector.
self_state_idx: Option<StateIndex>,
selector: Option<ContractCallParams>,
/// optional binding information for the LSP
type_binding: Option<TypeBinding<()>>,
},
LazyOperator {
op: LazyOp,
Expand Down Expand Up @@ -90,6 +92,7 @@ pub enum TyExpressionVariant {
/// They are also used in the language server.
enum_instantiation_span: Span,
variant_instantiation_span: Span,
type_binding: TypeBinding<()>,
},
AbiCast {
abi_name: CallPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl ty::TyExpression {
.to_var_name(),
is_absolute: true,
};
let method_name_binding = TypeBinding {
let mut method_name_binding = TypeBinding {
inner: MethodName::FromTrait {
call_path: call_path.clone(),
},
Expand All @@ -71,7 +71,7 @@ impl ty::TyExpression {
};
let arguments = VecDeque::from(arguments);
let decl_id = check!(
resolve_method_name(ctx, &method_name_binding, arguments.clone()),
resolve_method_name(ctx, &mut method_name_binding, arguments.clone()),
return err(warnings, errors),
warnings,
errors
Expand Down Expand Up @@ -106,6 +106,7 @@ impl ty::TyExpression {
function_decl_id: decl_id,
self_state_idx: None,
selector: None,
type_binding: None,
},
return_type,
span,
Expand Down Expand Up @@ -491,7 +492,7 @@ impl ty::TyExpression {
instantiate_function_application(
ctx,
function_decl,
call_path_binding.inner,
call_path_binding,
Some(arguments),
span,
)
Expand Down Expand Up @@ -1150,7 +1151,15 @@ impl ty::TyExpression {
warnings.append(&mut enum_probe_warnings);
errors.append(&mut enum_probe_errors);
check!(
instantiate_enum(ctx, enum_decl, enum_name, variant_name, args, &span),
instantiate_enum(
ctx,
enum_decl,
enum_name,
variant_name,
args,
call_path_binding.strip_inner(),
&span
),
return err(warnings, errors),
warnings,
errors
Expand All @@ -1160,13 +1169,7 @@ impl ty::TyExpression {
warnings.append(&mut function_probe_warnings);
errors.append(&mut function_probe_errors);
check!(
instantiate_function_application(
ctx,
func_decl,
call_path_binding.inner,
args,
span
),
instantiate_function_application(ctx, func_decl, call_path_binding, args, span),
return err(warnings, errors),
warnings,
errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub(crate) fn instantiate_enum(
enum_name: Ident,
enum_variant_name: Ident,
args_opt: Option<Vec<Expression>>,
mut type_binding: TypeBinding<()>,
span: &Span,
) -> CompileResult<ty::TyExpression> {
let mut warnings = vec![];
Expand Down Expand Up @@ -46,6 +47,17 @@ pub(crate) fn instantiate_enum(
}
let args = args_opt.unwrap_or_default();

// Update type binding with the correct type information from the enum decl
for (type_arg, type_param) in type_binding
.type_arguments
.iter_mut()
.zip(enum_decl.type_parameters.iter())
{
type_arg.type_id = type_param.type_id;
type_arg.initial_type_id = type_param.initial_type_id;
// keep the type_arg span so the LSP knows where we are
}

// If there is an instantiator, it must match up with the type. If there is not an
// instantiator, then the type of the enum is necessarily the unit type.

Expand All @@ -60,6 +72,7 @@ pub(crate) fn instantiate_enum(
variant_name: enum_variant.name,
enum_instantiation_span: enum_name.span(),
variant_instantiation_span: enum_variant_name.span(),
type_binding,
},
span: enum_variant_name.span(),
},
Expand Down Expand Up @@ -105,6 +118,7 @@ pub(crate) fn instantiate_enum(
variant_name: enum_variant.name,
enum_instantiation_span: enum_name.span(),
variant_instantiation_span: enum_variant_name.span(),
type_binding,
},
span: enum_variant_name.span(),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use sway_types::Spanned;
pub(crate) fn instantiate_function_application(
mut ctx: TypeCheckContext,
mut function_decl: ty::TyFunctionDeclaration,
call_path: CallPath,
call_path_binding: TypeBinding<CallPath>,
arguments: Option<Vec<Expression>>,
span: Span,
) -> CompileResult<ty::TyExpression> {
Expand All @@ -24,8 +24,8 @@ pub(crate) fn instantiate_function_application(

if arguments.is_none() {
errors.push(CompileError::MissingParenthesesForFunction {
method_name: call_path.suffix.clone(),
span: call_path.span(),
method_name: call_path_binding.inner.suffix.clone(),
span: call_path_binding.inner.span(),
});
return err(warnings, errors);
}
Expand All @@ -35,13 +35,18 @@ pub(crate) fn instantiate_function_application(
if !ctx.purity().can_call(function_decl.purity) {
errors.push(CompileError::StorageAccessMismatch {
attrs: promote_purity(ctx.purity(), function_decl.purity).to_attribute_syntax(),
span: call_path.span(),
span: call_path_binding.span(),
});
}

// check that the number of parameters and the number of the arguments is the same
check!(
check_function_arguments_arity(arguments.len(), &function_decl, &call_path, false),
check_function_arguments_arity(
arguments.len(),
&function_decl,
&call_path_binding.inner,
false
),
return err(warnings, errors),
warnings,
errors
Expand Down Expand Up @@ -73,7 +78,7 @@ pub(crate) fn instantiate_function_application(
TypeParameter::gather_decl_mapping_from_trait_constraints(
ctx.by_ref(),
&function_decl.type_parameters,
&call_path.span()
&call_path_binding.span()
),
return err(warnings, errors),
warnings,
Expand All @@ -85,12 +90,13 @@ pub(crate) fn instantiate_function_application(

let exp = ty::TyExpression {
expression: ty::TyExpressionVariant::FunctionApplication {
call_path,
call_path: call_path_binding.inner.clone(),
contract_call_params: HashMap::new(),
arguments: typed_arguments_with_names,
function_decl_id: new_decl_id,
self_state_idx: None,
selector: None,
type_binding: Some(call_path_binding.strip_inner()),
},
return_type,
span,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ use std::collections::{HashMap, VecDeque};
use sway_error::error::CompileError;
use sway_types::{constants, integer_bits::IntegerBits};
use sway_types::{constants::CONTRACT_CALL_COINS_PARAMETER_NAME, Spanned};
use sway_types::{state::StateIndex, Span};
use sway_types::{state::StateIndex, Ident, Span};

#[allow(clippy::too_many_arguments)]
pub(crate) fn type_check_method_application(
mut ctx: TypeCheckContext,
method_name_binding: TypeBinding<MethodName>,
mut method_name_binding: TypeBinding<MethodName>,
contract_call_params: Vec<StructExpressionField>,
arguments: Vec<Expression>,
span: Span,
Expand Down Expand Up @@ -44,7 +44,7 @@ pub(crate) fn type_check_method_application(

// resolve the method name to a typed function declaration and type_check
let decl_id = check!(
resolve_method_name(ctx.by_ref(), &method_name_binding, args_buf.clone()),
resolve_method_name(ctx.by_ref(), &mut method_name_binding, args_buf.clone()),
return err(warnings, errors),
warnings,
errors
Expand Down Expand Up @@ -261,7 +261,7 @@ pub(crate) fn type_check_method_application(
}

// retrieve the function call path
let call_path = match method_name_binding.inner {
let call_path = match method_name_binding.inner.clone() {
MethodName::FromType {
call_path_binding,
method_name,
Expand Down Expand Up @@ -335,21 +335,13 @@ pub(crate) fn type_check_method_application(
);

// unify the types of the arguments with the types of the parameters from the function declaration
check!(
unify_arguments_and_parameters(ctx.by_ref(), &args_buf, &method.parameters),
let typed_arguments_with_names = check!(
unify_arguments_and_parameters(ctx.by_ref(), args_buf, &method.parameters),
return err(warnings, errors),
warnings,
errors
);

// Map the names of the parameters to the typed arguments.
let args_and_names = method
.parameters
.iter()
.zip(args_buf.into_iter())
.map(|(param, arg)| (param.name.clone(), arg))
.collect::<Vec<(_, _)>>();

// Retrieve the implemented traits for the type of the return type and
// insert them in the broader namespace.
ctx.namespace
Expand All @@ -359,10 +351,11 @@ pub(crate) fn type_check_method_application(
expression: ty::TyExpressionVariant::FunctionApplication {
call_path,
contract_call_params: contract_call_params_map,
arguments: args_and_names,
arguments: typed_arguments_with_names,
function_decl_id: decl_id,
self_state_idx,
selector,
type_binding: Some(method_name_binding.strip_inner()),
},
return_type: method.return_type,
span,
Expand All @@ -371,21 +364,22 @@ pub(crate) fn type_check_method_application(
ok(exp, warnings, errors)
}

/// Unifies the types of the arguments with the types of the parameters from the
/// function declaration.
/// Unifies the types of the arguments with the types of the parameters. Returns
/// a list of the arguments with the names of the corresponding parameters.
fn unify_arguments_and_parameters(
ctx: TypeCheckContext,
arguments: &VecDeque<ty::TyExpression>,
arguments: VecDeque<ty::TyExpression>,
parameters: &[ty::TyFunctionParameter],
) -> CompileResult<()> {
) -> CompileResult<Vec<(Ident, ty::TyExpression)>> {
let mut warnings = vec![];
let mut errors = vec![];

let type_engine = ctx.type_engine;
let decl_engine = ctx.decl_engine;
let engines = ctx.engines();
let mut typed_arguments_and_names = vec![];

for (arg, param) in arguments.iter().zip(parameters.iter()) {
for (arg, param) in arguments.into_iter().zip(parameters.iter()) {
// unify the type of the argument with the type of the param
check!(
CompileResult::from(type_engine.unify_with_self(
Expand All @@ -405,18 +399,20 @@ fn unify_arguments_and_parameters(
warnings,
errors
);

typed_arguments_and_names.push((param.name.clone(), arg));
}

if errors.is_empty() {
ok((), warnings, errors)
ok(typed_arguments_and_names, warnings, errors)
} else {
err(warnings, errors)
}
}

pub(crate) fn resolve_method_name(
mut ctx: TypeCheckContext,
method_name: &TypeBinding<MethodName>,
method_name: &mut TypeBinding<MethodName>,
arguments: VecDeque<ty::TyExpression>,
) -> CompileResult<DeclId> {
let mut warnings = vec![];
Expand Down Expand Up @@ -526,12 +522,13 @@ pub(crate) fn resolve_method_name(
);

// monomorphize the function declaration
let method_name_span = method_name.span();
check!(
ctx.monomorphize(
&mut func_decl,
&mut method_name.type_arguments.clone(),
&mut method_name.type_arguments,
EnforceTypeArguments::No,
&method_name.span()
&method_name_span,
),
return err(warnings, errors),
warnings,
Expand Down
10 changes: 10 additions & 0 deletions sway-core/src/type_system/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ impl<T> Spanned for TypeBinding<T> {
}
}

impl<T> TypeBinding<T> {
pub fn strip_inner(self) -> TypeBinding<()> {
TypeBinding {
inner: (),
type_arguments: self.type_arguments,
span: self.span,
}
}
}

impl TypeBinding<CallPath<(TypeInfo, Span)>> {
pub(crate) fn type_check_with_type_info(
&self,
Expand Down
Loading

0 comments on commit 5c4e3b4

Please sign in to comment.