Skip to content

Commit

Permalink
Merge ce58228 into c186d93
Browse files Browse the repository at this point in the history
  • Loading branch information
xunilrj authored Jun 22, 2024
2 parents c186d93 + ce58228 commit 63595e5
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 73 deletions.
12 changes: 9 additions & 3 deletions sway-core/src/language/ty/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,9 +602,15 @@ impl TyFunctionSig {
}

pub fn is_concrete(&self, engines: &Engines) -> bool {
self.return_type.is_concrete(engines)
&& self.parameters.iter().all(|p| p.is_concrete(engines))
&& self.type_parameters.iter().all(|p| p.is_concrete(engines))
self.return_type.is_concrete(engines, IncludeNumeric::No)
&& self
.parameters
.iter()
.all(|p| p.is_concrete(engines, IncludeNumeric::No))
&& self
.type_parameters
.iter()
.all(|p| p.is_concrete(engines, IncludeNumeric::No))
}

/// Returns a String representing the function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,25 @@ pub(crate) fn type_check_method_application(
.by_ref()
.with_help_text("")
.with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None));

// Ignore errors in method parameters
// On the second pass we will throw the errors if they persist.
let arg_handler = Handler::default();
let arg_opt = ty::TyExpression::type_check(&arg_handler, ctx, arg).ok();

// Check this type needs a second pass
let has_errors = arg_handler.has_errors();
let is_not_concrete = arg_opt
.as_ref()
.map(|x| {
x.return_type
.extract_inner_types(engines, IncludeSelf::Yes)
.iter()
.any(|x| !x.is_concrete(engines, IncludeNumeric::Yes))
})
.unwrap_or_default();
let needs_second_pass = has_errors || is_not_concrete;

if index == 0 {
// We want to emit errors in the self parameter and ignore TraitConstraintNotSatisfied with Placeholder
// which may be recoverable on the second pass.
Expand All @@ -66,7 +80,8 @@ pub(crate) fn type_check_method_application(
});
handler.append(arg_handler);
}
args_opt_buf.push_back((arg_opt, has_errors));

args_opt_buf.push_back((arg_opt, needs_second_pass));
}

// resolve the method name to a typed function declaration and type_check
Expand Down Expand Up @@ -114,21 +129,22 @@ pub(crate) fn type_check_method_application(
} else {
index
};

let tid = method
.parameters
.get(param_index)
.unwrap()
.type_argument
.type_id;

// This arg_opt is None because it failed in the first pass.
// We now try to type check it again, this time with the type annotation.
let ctx = ctx
.by_ref()
.with_help_text(
"Function application argument type must match function parameter type.",
)
.with_type_annotation(
method
.parameters
.get(param_index)
.unwrap()
.type_argument
.type_id,
);
.with_type_annotation(tid);
args_buf.push_back(
ty::TyExpression::type_check(handler, ctx, arg)
.unwrap_or_else(|err| ty::TyExpression::error(err, span.clone(), engines)),
Expand Down
22 changes: 18 additions & 4 deletions sway-core/src/type_system/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ pub enum IncludeSelf {
No,
}

pub enum IncludeNumeric {
Yes,
No,
}

/// A identifier to uniquely refer to our type terms
#[derive(PartialEq, Eq, Hash, Clone, Copy, Ord, PartialOrd, Debug)]
pub struct TypeId(usize);
Expand Down Expand Up @@ -480,17 +485,26 @@ impl TypeId {
}))
}

pub(crate) fn is_concrete(&self, engines: &Engines) -> bool {
pub(crate) fn is_concrete(&self, engines: &Engines, include_numeric: IncludeNumeric) -> bool {
let nested_types = (*self).extract_nested_types(engines);
!nested_types.into_iter().any(|x| {
matches!(
!nested_types.into_iter().any(|x| match include_numeric {
IncludeNumeric::Yes => matches!(
x,
TypeInfo::UnknownGeneric { .. }
| TypeInfo::Custom { .. }
| TypeInfo::Placeholder(..)
| TypeInfo::TraitType { .. }
| TypeInfo::TypeParam(..)
)
| TypeInfo::Numeric
),
IncludeNumeric::No => matches!(
x,
TypeInfo::UnknownGeneric { .. }
| TypeInfo::Custom { .. }
| TypeInfo::Placeholder(..)
| TypeInfo::TraitType { .. }
| TypeInfo::TypeParam(..)
),
})
}

Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/type_system/priv_prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ pub use super::{
type_parameter::TypeParameter,
},
engine::TypeEngine,
id::{IncludeSelf, TypeId},
id::{IncludeNumeric, IncludeSelf, TypeId},
info::{AbiEncodeSizeHint, AbiName, TypeInfo, TypeSourceInfo},
};
20 changes: 17 additions & 3 deletions sway-ir/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub enum IrError {
VerifyContractCallBadTypes(String),
VerifyGepElementTypeNonPointer,
VerifyGepFromNonPointer(String),
VerifyGepInconsistentTypes,
VerifyGepInconsistentTypes(String, Option<crate::Value>),
VerifyGepOnNonAggregate,
VerifyGetNonExistentPointer,
VerifyInsertElementOfIncorrectType,
Expand Down Expand Up @@ -67,11 +67,21 @@ pub enum IrError {
VerifyStoreToNonPointer(String),
VerifyUntypedValuePassedToFunction,
}
impl IrError {
pub(crate) fn get_problematic_value(&self) -> Option<&Value> {
match self {
Self::VerifyGepInconsistentTypes(_, v) => v.as_ref(),
_ => None,
}
}
}

impl std::error::Error for IrError {}

use std::fmt;

use crate::Value;

impl fmt::Display for IrError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self {
Expand Down Expand Up @@ -191,8 +201,12 @@ impl fmt::Display for IrError {
IrError::VerifyGepElementTypeNonPointer => {
write!(f, "Verification failed: GEP on a non-pointer.")
}
IrError::VerifyGepInconsistentTypes => {
write!(f, "Verification failed: Struct field type mismatch.")
IrError::VerifyGepInconsistentTypes(error, _) => {
write!(
f,
"Verification failed: Struct field type mismatch: ({}).",
error
)
}
IrError::VerifyGepFromNonPointer(ty) => {
write!(
Expand Down
47 changes: 36 additions & 11 deletions sway-ir/src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
};

#[derive(Debug)]
enum Doc {
pub(crate) enum Doc {
Empty,
Space,
Comma,
Expand All @@ -42,15 +42,15 @@ enum Doc {
}

impl Doc {
fn text<S: Into<String>>(s: S) -> Self {
pub(crate) fn text<S: Into<String>>(s: S) -> Self {
Doc::Text(s.into())
}

fn line(doc: Doc) -> Self {
Doc::Line(Box::new(doc))
}

fn text_line<S: Into<String>>(s: S) -> Self {
pub(crate) fn text_line<S: Into<String>>(s: S) -> Self {
Doc::Line(Box::new(Doc::Text(s.into())))
}

Expand All @@ -66,7 +66,7 @@ impl Doc {
Doc::Parens(Box::new(Doc::list_sep(docs, Doc::Comma)))
}

fn append(self, doc: Doc) -> Doc {
pub(crate) fn append(self, doc: Doc) -> Doc {
match (&self, &doc) {
(Doc::Empty, _) => doc,
(_, Doc::Empty) => self,
Expand All @@ -81,7 +81,7 @@ impl Doc {
}
}

fn build(self) -> String {
pub(crate) fn build(self) -> String {
build_doc(self, 0)
}
}
Expand All @@ -90,17 +90,32 @@ impl Doc {
///
/// The output from this function must always be suitable for [crate::parser::parse].
pub fn to_string(context: &Context) -> String {
context_print(context, &|_, doc| doc)
}

pub(crate) fn context_print(context: &Context, map_doc: &impl Fn(&Value, Doc) -> Doc) -> String {
let mut md_namer = MetadataNamer::default();
context
.modules
.iter()
.fold(Doc::Empty, |doc, (_, module)| {
doc.append(module_to_doc(context, &mut md_namer, module))
doc.append(module_to_doc(context, &mut md_namer, module, map_doc))
})
.append(md_namer.to_doc(context))
.build()
}

pub(crate) fn block_print(
context: &Context,
function: Function,
block: Block,
map_doc: &impl Fn(&Value, Doc) -> Doc,
) -> String {
let mut md_namer = MetadataNamer::default();
let mut namer = Namer::new(function);
block_to_doc(context, &mut md_namer, &mut namer, &block, map_doc).build()
}

pub struct ModulePrinterResult;
impl AnalysisResultT for ModulePrinterResult {}

Expand All @@ -116,7 +131,8 @@ pub fn module_printer_pass(
module_to_doc(
context,
&mut md_namer,
context.modules.get(module.0).unwrap()
context.modules.get(module.0).unwrap(),
&|_, doc| doc
)
.append(md_namer.to_doc(context))
.build()
Expand All @@ -132,7 +148,8 @@ pub fn module_print(context: &Context, _analyses: &AnalysisResults, module: Modu
module_to_doc(
context,
&mut md_namer,
context.modules.get(module.0).unwrap()
context.modules.get(module.0).unwrap(),
&|_, doc| doc
)
.append(md_namer.to_doc(context))
.build()
Expand All @@ -148,7 +165,8 @@ pub fn function_print(context: &Context, function: Function) {
context,
&mut md_namer,
&mut Namer::new(function),
context.functions.get(function.0).unwrap()
context.functions.get(function.0).unwrap(),
&|_, doc| doc
)
.append(md_namer.to_doc(context))
.build()
Expand All @@ -170,6 +188,7 @@ fn module_to_doc<'a>(
context: &'a Context,
md_namer: &mut MetadataNamer,
module: &'a ModuleContent,
map_doc: &impl Fn(&Value, Doc) -> Doc,
) -> Doc {
Doc::line(Doc::Text(format!(
"{} {{",
Expand Down Expand Up @@ -207,6 +226,7 @@ fn module_to_doc<'a>(
md_namer,
&mut Namer::new(*function),
&context.functions[function.0],
map_doc,
)
})
.collect(),
Expand Down Expand Up @@ -268,6 +288,7 @@ fn function_to_doc<'a>(
md_namer: &mut MetadataNamer,
namer: &mut Namer,
function: &'a FunctionContent,
map_doc: &impl Fn(&Value, Doc) -> Doc,
) -> Doc {
let public = if function.is_public { "pub " } else { "" };
let entry = if function.is_entry { "entry " } else { "" };
Expand Down Expand Up @@ -354,7 +375,7 @@ fn function_to_doc<'a>(
function
.blocks
.iter()
.map(|block| block_to_doc(context, md_namer, namer, block))
.map(|block| block_to_doc(context, md_namer, namer, block, map_doc))
.collect(),
Doc::line(Doc::Empty),
),
Expand All @@ -370,6 +391,7 @@ fn block_to_doc(
md_namer: &mut MetadataNamer,
namer: &mut Namer,
block: &Block,
mut map_doc: &impl Fn(&Value, Doc) -> Doc,
) -> Doc {
let block_content = &context.blocks[block.0];
Doc::line(
Expand All @@ -391,7 +413,10 @@ fn block_to_doc(
.append(Doc::List(
block
.instruction_iter(context)
.map(|ins| instruction_to_doc(context, md_namer, namer, block, &ins))
.map(|current_value| {
let mut doc = instruction_to_doc(context, md_namer, namer, block, &current_value);
(map_doc)(&current_value, doc)
})
.collect(),
))
}
Expand Down
Loading

0 comments on commit 63595e5

Please sign in to comment.