Skip to content

Commit

Permalink
Add const probing to delineated path type check (FuelLabs#3080)
Browse files Browse the repository at this point in the history
  • Loading branch information
kayagokalp authored Oct 22, 2022
1 parent 99df7b1 commit daa3ecc
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 20 deletions.
20 changes: 20 additions & 0 deletions sway-core/src/language/ty/declaration/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,26 @@ impl TyDeclaration {
}
}

/// Retrieves the declaration as an Constant declaration.
///
/// Returns an error if `self` is not a [TyConstantDeclaration].
pub(crate) fn expect_const(&self, access_span: &Span) -> CompileResult<TyConstantDeclaration> {
match self {
TyDeclaration::ConstantDeclaration(decl) => {
CompileResult::from(de_get_constant(decl.clone(), access_span))
}
decl => {
let errors = vec![
(CompileError::DeclIsNotAConstant {
actually: decl.friendly_name().to_string(),
span: decl.span(),
}),
];
err(vec![], errors)
}
}
}

/// friendly name string used for error reporting.
pub fn friendly_name(&self) -> &'static str {
use TyDeclaration::*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod constant_decleration;
mod enum_instantiation;
mod function_application;
mod if_expression;
Expand All @@ -7,6 +8,7 @@ mod struct_field_access;
mod tuple_index_access;
mod unsafe_downcast;

use self::constant_decleration::instantiate_constant_decl;
pub(crate) use self::{
enum_instantiation::*, function_application::*, if_expression::*, lazy_operator::*,
method_application::*, struct_field_access::*, tuple_index_access::*, unsafe_downcast::*,
Expand Down Expand Up @@ -1040,9 +1042,20 @@ impl ty::TyExpression {
.map(|enum_decl| (enum_decl, enum_name, variant_name))
};

// Check if this could be a constant
let mut const_probe_warnings = vec![];
let mut const_probe_errors = vec![];
let maybe_const = {
let mut call_path_binding = call_path_binding.clone();
TypeBinding::type_check_with_ident(&mut call_path_binding, ctx.by_ref())
.flat_map(|unknown_decl| unknown_decl.expect_const(&call_path_binding.span()))
.ok(&mut const_probe_warnings, &mut const_probe_errors)
.map(|const_decl| (const_decl, call_path_binding.span()))
};

// compare the results of the checks
let exp = match (is_module, maybe_function, maybe_enum) {
(false, None, Some((enum_decl, enum_name, variant_name))) => {
let exp = match (is_module, maybe_function, maybe_enum, maybe_const) {
(false, None, Some((enum_decl, enum_name, variant_name)), None) => {
warnings.append(&mut enum_probe_warnings);
errors.append(&mut enum_probe_errors);
check!(
Expand All @@ -1052,7 +1065,7 @@ impl ty::TyExpression {
errors
)
}
(false, Some(func_decl), None) => {
(false, Some(func_decl), None, None) => {
warnings.append(&mut function_probe_warnings);
errors.append(&mut function_probe_errors);
check!(
Expand All @@ -1062,35 +1075,33 @@ impl ty::TyExpression {
errors
)
}
(true, None, None) => {
(true, None, None, None) => {
module_probe_errors.push(CompileError::Unimplemented(
"this case is not yet implemented",
span,
));
return err(module_probe_warnings, module_probe_errors);
}
(true, None, Some(_)) => {
errors.push(CompileError::AmbiguousPath { span });
return err(warnings, errors);
}
(true, Some(_), None) => {
errors.push(CompileError::AmbiguousPath { span });
return err(warnings, errors);
}
(true, Some(_), Some(_)) => {
errors.push(CompileError::AmbiguousPath { span });
return err(warnings, errors);
}
(false, Some(_), Some(_)) => {
errors.push(CompileError::AmbiguousPath { span });
return err(warnings, errors);
(false, None, None, Some((const_decl, span))) => {
warnings.append(&mut const_probe_warnings);
errors.append(&mut const_probe_errors);
check!(
instantiate_constant_decl(const_decl, span),
return err(warnings, errors),
warnings,
errors
)
}
(false, None, None) => {
(false, None, None, None) => {
errors.push(CompileError::SymbolNotFound {
name: call_path_binding.inner.suffix,
});
return err(warnings, errors);
}
_ => {
errors.push(CompileError::AmbiguousPath { span });
return err(warnings, errors);
}
};

ok(exp, warnings, errors)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use sway_types::{Span, Spanned};

use crate::{
error::*,
language::ty::{self, TyConstantDeclaration},
CompileResult,
};

pub(crate) fn instantiate_constant_decl(
const_decl: TyConstantDeclaration,
span: Span,
) -> CompileResult<ty::TyExpression> {
ok(
ty::TyExpression {
expression: ty::TyExpressionVariant::VariableExpression {
name: const_decl.name.clone(),
span: const_decl.name.span(),
mutability: ty::VariableMutability::Immutable,
},
return_type: const_decl.value.return_type,
span,
},
vec![],
vec![],
)
}
3 changes: 3 additions & 0 deletions sway-error/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ pub enum CompileError {
DeclIsNotATraitFn { actually: String, span: Span },
#[error("This is a {actually}, not storage.")]
DeclIsNotStorage { actually: String, span: Span },
#[error("This is a {actually}, not a constant")]
DeclIsNotAConstant { actually: String, span: Span },
#[error(
"Field \"{field_name}\" not found on struct \"{struct_name}\". Available fields are:\n \
{available_fields}"
Expand Down Expand Up @@ -791,6 +793,7 @@ impl Spanned for CompileError {
DeclIsNotAnImplTrait { span, .. } => span.clone(),
DeclIsNotATraitFn { span, .. } => span.clone(),
DeclIsNotStorage { span, .. } => span.clone(),
DeclIsNotAConstant { span, .. } => span.clone(),
ImpureInNonContract { span, .. } => span.clone(),
ImpureInPureContext { span, .. } => span.clone(),
ParameterMutabilityMismatch { span, .. } => span.clone(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[[package]]
name = 'const_decl_with_call_path'
source = 'root'
dependencies = ['std']

[[package]]
name = 'core'
source = 'path+from-root-8403A6B918C3B0C1'
dependencies = []

[[package]]
name = 'std'
source = 'path+from-root-8403A6B918C3B0C1'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "const_decl_with_call_path"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"functions": [
{
"inputs": [],
"name": "main",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
}
],
"loggedTypes": [],
"types": [
{
"components": null,
"type": "u64",
"typeId": 0,
"typeParameters": null
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
script;

dep test_lib;

use std::{assert::assert, contract_id::ContractId};

fn main() -> u64 {
let x = test_lib::NUMBER;
let zero = std::constants::ZERO_B256;
let base_asset_id = std::constants::BASE_ASSET_ID;
assert(zero == 0x0000000000000000000000000000000000000000000000000000000000000000);
assert(base_asset_id == ~ContractId::from(zero));
x
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
library test_lib;

pub const NUMBER: u64 = 10;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
category = "run"
expected_result = { action = "return", value = 10 }
validate_abi = true

0 comments on commit daa3ecc

Please sign in to comment.