Skip to content

Commit

Permalink
Merge fdaefda into df5d194
Browse files Browse the repository at this point in the history
  • Loading branch information
esdrubal authored Aug 26, 2024
2 parents df5d194 + fdaefda commit 943be69
Show file tree
Hide file tree
Showing 23 changed files with 413 additions and 56 deletions.
10 changes: 8 additions & 2 deletions sway-core/src/language/ty/expression/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,20 @@ impl TypeCheckAnalysis for TyExpression {
unify::unifier::UnifyKind::Default,
);
for element in contents {
let element_type = ctx.engines.te().get(*elem_type);
let element_type = ctx.engines.te().get(element.return_type);

// If the element is never, we do not need to check
if matches!(&*element_type, TypeInfo::Never) {
continue;
}

unify.unify(handler, element.return_type, *elem_type, &element.span)
unify.unify(
handler,
element.return_type,
*elem_type,
&element.span,
true,
)
}
}
}
Expand Down
38 changes: 36 additions & 2 deletions sway-core/src/semantic_analysis/ast_node/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,44 @@ impl ty::TyCodeBlock {

pub(crate) fn type_check(
handler: &Handler,
ctx: TypeCheckContext,
mut ctx: TypeCheckContext,
code_block: &CodeBlock,
is_root: bool,
) -> Result<Self, ErrorEmitted> {
ctx.scoped(|mut ctx| {
if !is_root {
let code_block_result = ctx.by_ref().scoped(|mut ctx| {
let evaluated_contents = code_block
.contents
.iter()
.filter_map(|node| ty::TyAstNode::type_check(handler, ctx.by_ref(), node).ok())
.collect::<Vec<ty::TyAstNode>>();
Ok(ty::TyCodeBlock {
contents: evaluated_contents,
whole_block_span: code_block.whole_block_span.clone(),
})
})?;

return Ok(code_block_result);
}

ctx.engines.te().clear_unifications();

// We are typechecking the code block AST nodes twice.
// The first pass does all the unifications to the variables types.
// In the second pass we use the previous_namespace on variable declaration to unify directly with the result of the first pass.
// This is required to fix the test case numeric_type_propagation and issue #6371
ctx.by_ref()
.with_collecting_unifications()
.scoped(|mut ctx| {
code_block.contents.iter().for_each(|node| {
ty::TyAstNode::type_check(&Handler::default(), ctx.by_ref(), node).ok();
});
Ok(())
})?;

ctx.engines.te().reapply_unifications(ctx.engines());

ctx.by_ref().scoped(|mut ctx| {
let evaluated_contents = code_block
.contents
.iter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
ty::{self, FunctionDecl, TyCodeBlock, TyDecl, TyStorageField},
CallPath,
},
namespace::{IsExtendingExistingImpl, IsImplSelf},
namespace::{IsExtendingExistingImpl, IsImplSelf, ResolvedDeclaration},
semantic_analysis::{
symbol_collection_context::SymbolCollectionContext,
type_check_context::EnforceTypeArguments, ConstShadowingMode, GenericShadowingMode,
Expand Down Expand Up @@ -162,6 +162,30 @@ impl TyDecl {
},
};

if !ctx.collecting_unifications() {
let previous_symbol = ctx
.namespace()
.module(engines)
.current_items()
.check_symbol_unique(&var_decl.name.clone())
.ok();

if let Some(ResolvedDeclaration::Typed(ty::TyDecl::VariableDecl(
variable_decl,
))) = previous_symbol
{
type_engine.unify(
handler,
engines,
body.return_type,
variable_decl.body.return_type,
&decl.span(engines),
"",
None,
);
}
}

let typed_var_decl = ty::TyDecl::VariableDecl(Box::new(ty::TyVariableDecl {
name: var_decl.name.clone(),
body,
Expand Down Expand Up @@ -359,6 +383,7 @@ impl TyDecl {
for i in &impl_trait.items {
if let ty::TyTraitItem::Fn(f) = i {
let decl = engines.de().get(f.id());
let collecting_unifications = ctx.collecting_unifications();
let _ = ctx.namespace.module_mut(ctx.engines()).write(engines, |m| {
m.current_items_mut().insert_typed_symbol(
handler,
Expand All @@ -370,6 +395,7 @@ impl TyDecl {
TyDecl::FunctionDecl(FunctionDecl { decl_id: *f.id() }),
ConstShadowingMode::ItemStyle,
GenericShadowingMode::Allow,
collecting_unifications,
)
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl ty::TyFunctionDecl {
.with_type_annotation(return_type.type_id)
.with_function_type_annotation(return_type.type_id);

let body = ty::TyCodeBlock::type_check(handler, ctx.by_ref(), body)
let body = ty::TyCodeBlock::type_check(handler, ctx.by_ref(), body, true)
.unwrap_or_else(|_err| ty::TyCodeBlock::default());

ty_fn_decl.body = body;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ impl ty::TyExpression {
let engines = ctx.engines();

let (typed_block, block_return_type) =
match ty::TyCodeBlock::type_check(handler, ctx.by_ref(), contents) {
match ty::TyCodeBlock::type_check(handler, ctx.by_ref(), contents, false) {
Ok(res) => {
let (block_type, _span) = TyCodeBlock::compute_return_type_and_span(&ctx, &res);
(res, block_type)
Expand Down Expand Up @@ -1840,7 +1840,12 @@ impl ty::TyExpression {
// from the elements
let initial_type = match &*ctx.engines().te().get(ctx.type_annotation()) {
TypeInfo::Array(element_type, _) => {
(*ctx.engines().te().get(element_type.type_id)).clone()
let element_type = (*ctx.engines().te().get(element_type.type_id)).clone();
if matches!(element_type, TypeInfo::Never) {
TypeInfo::Unknown //Even if array element type is Never other elements may not be of type Never.
} else {
element_type
}
}
_ => TypeInfo::Unknown,
};
Expand Down Expand Up @@ -2008,7 +2013,7 @@ impl ty::TyExpression {
assigning it to a mutable variable declared outside of the loop \
instead.",
);
let typed_body = ty::TyCodeBlock::type_check(handler, ctx.by_ref(), body)?;
let typed_body = ty::TyCodeBlock::type_check(handler, ctx.by_ref(), body, false)?;

let exp = ty::TyExpression {
expression: ty::TyExpressionVariant::WhileLoop {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ pub(crate) fn instantiate_function_application(
)
.with_parent(decl_engine, (*function_decl_ref.id()).into());

if method_sig.is_concrete(engines)
if !ctx.collecting_unifications()
&& method_sig.is_concrete(engines)
&& function_is_type_check_finalized
&& !function_is_trait_method_dummy
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,8 @@ pub(crate) fn type_check_method_application(
method_return_type_id = method.return_type.type_id;
decl_engine.replace(*fn_ref.id(), method.clone());

if method_sig.is_concrete(engines)
if !ctx.collecting_unifications()
&& method_sig.is_concrete(engines)
&& method.is_type_check_finalized
&& !method.is_trait_method_dummy
{
Expand Down
36 changes: 35 additions & 1 deletion sway-core/src/semantic_analysis/namespace/lexical_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ use crate::{

use super::{root::ResolvedDeclaration, TraitMap};

use parking_lot::RwLock;
use sway_error::{
error::{CompileError, ShadowingSource, StructFieldUsageContext},
handler::{ErrorEmitted, Handler},
};
use sway_types::{span::Span, Spanned};
use sway_types::{span::Span, IdentUnique, Spanned};

use std::sync::Arc;

Expand All @@ -36,6 +37,7 @@ impl ResolvedFunctionDecl {
}

pub(super) type SymbolMap = im::OrdMap<Ident, ResolvedDeclaration>;
pub(super) type SymbolUniqueMap = im::OrdMap<IdentUnique, ResolvedDeclaration>;

type SourceIdent = Ident;

Expand Down Expand Up @@ -76,6 +78,13 @@ pub struct LexicalScope {
pub struct Items {
/// An ordered map from `Ident`s to their associated declarations.
pub(crate) symbols: SymbolMap,

/// An ordered map from `IdentUnique`s to their associated declarations.
/// This uses an Arc<RwLock<SymbolUniqueMap>> so it is shared between all
/// Items clones. This is intended so we can keep the symbols of previous
/// lexical scopes while collecting_unifications scopes.
pub(crate) symbols_unique_while_collecting_unifications: Arc<RwLock<SymbolUniqueMap>>,

pub(crate) implemented_traits: TraitMap,
/// Contains symbols imported using star imports (`use foo::*`.).
///
Expand Down Expand Up @@ -163,9 +172,11 @@ impl Items {
ResolvedDeclaration::Parsed(item),
const_shadowing_mode,
generic_shadowing_mode,
false,
)
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn insert_typed_symbol(
&mut self,
handler: &Handler,
Expand All @@ -174,6 +185,7 @@ impl Items {
item: ty::TyDecl,
const_shadowing_mode: ConstShadowingMode,
generic_shadowing_mode: GenericShadowingMode,
collecting_unifications: bool,
) -> Result<(), ErrorEmitted> {
self.insert_symbol(
handler,
Expand All @@ -182,9 +194,11 @@ impl Items {
ResolvedDeclaration::Typed(item),
const_shadowing_mode,
generic_shadowing_mode,
collecting_unifications,
)
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn insert_symbol(
&mut self,
handler: &Handler,
Expand All @@ -193,6 +207,7 @@ impl Items {
item: ResolvedDeclaration,
const_shadowing_mode: ConstShadowingMode,
generic_shadowing_mode: GenericShadowingMode,
collecting_unifications: bool,
) -> Result<(), ErrorEmitted> {
let parsed_decl_engine = engines.pe();
let decl_engine = engines.de();
Expand Down Expand Up @@ -629,6 +644,11 @@ impl Items {
);
}

if collecting_unifications {
self.symbols_unique_while_collecting_unifications
.write()
.insert(name.clone().into(), item.clone());
}
self.symbols.insert(name, item);

Ok(())
Expand Down Expand Up @@ -684,6 +704,20 @@ impl Items {
})
}

pub(crate) fn check_symbol_unique(
&self,
name: &Ident,
) -> Result<ResolvedDeclaration, CompileError> {
self.symbols_unique_while_collecting_unifications
.read()
.get(&name.into())
.cloned()
.ok_or_else(|| CompileError::SymbolNotFound {
name: name.clone(),
span: name.span(),
})
}

pub fn get_items_for_type(
&self,
engines: &Engines,
Expand Down
Loading

0 comments on commit 943be69

Please sign in to comment.