Skip to content

Commit

Permalink
Remove the obsolete unify_adt method. (FuelLabs#4332)
Browse files Browse the repository at this point in the history
## Description

This method was obsolete and was adding unnecessary complexity, so this
PR removes it 😄

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.
  • Loading branch information
emilyaherbert authored Mar 23, 2023
1 parent ff6f8af commit 5fd3cc3
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub(crate) fn instantiate_enum(

// unify the value of the argument with the variant
check!(
CompileResult::from(type_engine.unify_adt(
CompileResult::from(type_engine.unify(
decl_engine,
typed_expr.return_type,
enum_variant.type_argument.type_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ fn unify_field_arguments_and_struct_fields(
for struct_field in struct_fields.iter() {
if let Some(typed_field) = typed_fields.iter().find(|x| x.name == struct_field.name) {
check!(
CompileResult::from(type_engine.unify_adt(
CompileResult::from(type_engine.unify(
decl_engine,
typed_field.value.return_type,
struct_field.type_argument.type_id,
Expand Down
98 changes: 3 additions & 95 deletions sway-core/src/type_system/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,103 +265,11 @@ impl TypeEngine {
}
}

/// Helper function for making the type of `expected` equivalent to
/// `received` for instantiating algebraic data types.
///
/// This method simply switches the arguments of `received` and `expected`
/// and calls the `unify` method---the main purpose of this method is reduce
/// developer overhead during implementation, as it is a little non-intuitive
/// why `received` and `expected` should be switched.
///
/// Let me explain, take this Sway code:
///
/// ```ignore
/// enum Option<T> {
/// Some(T),
/// None
/// }
///
/// struct Wrapper {
/// option: Option<bool>,
/// }
///
/// fn create_it<T>() -> Wrapper {
/// Wrapper {
/// option: Option::None
/// }
/// }
/// ```
///
/// This is valid Sway code and we should expect it to compile. Here is the
/// pseudo-code of roughly what we can expect from type inference:
/// 1. `Option::None` is originally found to be of type `Option<T>` (because
/// it is not possible to know what `T` is just from the `None` case)
/// 2. we call `unify_adt` with arguments `received` of type `Option<T>` and
/// `expected` of type `Option<bool>`
/// 3. we switch `received` and `expected` and call the `unify` method
/// 4. we perform type inference with a `received` type of `Option<bool>`
/// and an `expected` type of `Option<T>`
/// 5. we perform type inference with a `received` type of `bool` and an
/// `expected` type of `T`
/// 6. because we have called the `unify` method (and not the `unify_right`
/// method), we can replace `T` with `bool`
///
/// What's important about this is flipping the arguments prioritizes
/// unifying `expected`, meaning if both `received` and `expected` are
/// generic types, then `expected` will be replaced with `received`.
pub(crate) fn unify_adt(
&self,
decl_engine: &DeclEngine,
received: TypeId,
expected: TypeId,
span: &Span,
help_text: &str,
err_override: Option<CompileError>,
) -> (Vec<CompileWarning>, Vec<CompileError>) {
let engines = Engines::new(self, decl_engine);
if !UnifyCheck::new(engines).check(received, expected) {
// create a "mismatched type" error unless the `err_override`
// argument has been provided
let mut errors = vec![];
match err_override {
Some(err_override) => {
errors.push(err_override);
}
None => {
errors.push(CompileError::TypeError(TypeError::MismatchedType {
expected: engines.help_out(expected).to_string(),
received: engines.help_out(received).to_string(),
help_text: help_text.to_string(),
span: span.clone(),
}));
}
}
return (vec![], errors);
}
let (warnings, errors) = normalize_err(
Unifier::new(engines, help_text)
.flip_arguments()
.unify(expected, received, span),
);
if errors.is_empty() {
(warnings, errors)
} else if err_override.is_some() {
// return the errors from unification unless the `err_override`
// argument has been provided
(warnings, vec![err_override.unwrap()])
} else {
(warnings, errors)
}
}

pub(crate) fn to_typeinfo(&self, id: TypeId, error_span: &Span) -> Result<TypeInfo, TypeError> {
match self.get(id) {
TypeInfo::Unknown => {
//panic!();
Err(TypeError::UnknownType {
span: error_span.clone(),
})
}
TypeInfo::Unknown => Err(TypeError::UnknownType {
span: error_span.clone(),
}),
ty => Ok(ty),
}
}
Expand Down
65 changes: 8 additions & 57 deletions sway-core/src/type_system/unify/unifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use super::occurs_check::OccursCheck;
/// Helper struct to aid in type unification.
pub(crate) struct Unifier<'a> {
engines: Engines<'a>,
arguments_are_flipped: bool,
help_text: String,
}

Expand All @@ -22,20 +21,10 @@ impl<'a> Unifier<'a> {
pub(crate) fn new(engines: Engines<'a>, help_text: &str) -> Unifier<'a> {
Unifier {
engines,
arguments_are_flipped: false,
help_text: help_text.to_string(),
}
}

/// Takes `self` and returns a new [Unifier] with the contents of self and
/// `flip_arguments` set to `true`.
pub(crate) fn flip_arguments(self) -> Unifier<'a> {
Unifier {
arguments_are_flipped: true,
..self
}
}

/// Helper method for replacing the values in the [TypeEngine].
fn replace_received_with_expected(
&self,
Expand Down Expand Up @@ -305,13 +294,8 @@ impl<'a> Unifier<'a> {
let mut warnings = vec![];
let mut errors = vec![];
for (rf, ef) in rfs.iter().zip(efs.iter()) {
let new_span = if self.arguments_are_flipped {
&ef.span
} else {
&rf.span
};
append!(
self.unify(rf.type_id, ef.type_id, new_span),
self.unify(rf.type_id, ef.type_id, &rf.span),
warnings,
errors
);
Expand All @@ -328,7 +312,7 @@ impl<'a> Unifier<'a> {
// E.g., in a variable declaration `let a: u32 = 10u64` the 'expected' type will be
// the annotation `u32`, and the 'received' type is 'self' of the initialiser, or
// `u64`. So we're casting received TO expected.
let warnings = match numeric_cast_compat(e, r, self.arguments_are_flipped) {
let warnings = match numeric_cast_compat(e, r) {
NumericCastCompatResult::CastableWithWarning(warn) => {
vec![CompileWarning {
span: span.clone(),
Expand Down Expand Up @@ -363,25 +347,15 @@ impl<'a> Unifier<'a> {
let (en, etps, efs) = e;
if rn == en && rfs.len() == efs.len() && rtps.len() == etps.len() {
rfs.iter().zip(efs.iter()).for_each(|(rf, ef)| {
let new_span = if self.arguments_are_flipped {
&ef.span
} else {
&rf.span
};
append!(
self.unify(rf.type_argument.type_id, ef.type_argument.type_id, new_span),
self.unify(rf.type_argument.type_id, ef.type_argument.type_id, &rf.span),
warnings,
errors
);
});
rtps.iter().zip(etps.iter()).for_each(|(rtp, etp)| {
let new_span = if self.arguments_are_flipped {
etp.name_ident.span()
} else {
rtp.name_ident.span()
};
append!(
self.unify(rtp.type_id, etp.type_id, &new_span),
self.unify(rtp.type_id, etp.type_id, &rtp.name_ident.span()),
warnings,
errors
);
Expand Down Expand Up @@ -412,25 +386,15 @@ impl<'a> Unifier<'a> {
let (en, etps, evs) = e;
if rn == en && rvs.len() == evs.len() && rtps.len() == etps.len() {
rvs.iter().zip(evs.iter()).for_each(|(rv, ev)| {
let new_span = if self.arguments_are_flipped {
&ev.span
} else {
&rv.span
};
append!(
self.unify(rv.type_argument.type_id, ev.type_argument.type_id, new_span),
self.unify(rv.type_argument.type_id, ev.type_argument.type_id, &rv.span),
warnings,
errors
);
});
rtps.iter().zip(etps.iter()).for_each(|(rtp, etp)| {
let new_span = if self.arguments_are_flipped {
etp.name_ident.span()
} else {
rtp.name_ident.span()
};
append!(
self.unify(rtp.type_id, etp.type_id, &new_span),
self.unify(rtp.type_id, etp.type_id, &rtp.name_ident.span()),
warnings,
errors
);
Expand Down Expand Up @@ -478,24 +442,11 @@ impl<'a> Unifier<'a> {
{
let r = self.engines.with_thing(r).to_string();
let e = self.engines.with_thing(e).to_string();
if self.arguments_are_flipped {
(e, r)
} else {
(r, e)
}
(r, e)
}
}

fn numeric_cast_compat(
new_size: IntegerBits,
old_size: IntegerBits,
arguments_are_flipped: bool,
) -> NumericCastCompatResult {
let (new_size, old_size) = if !arguments_are_flipped {
(new_size, old_size)
} else {
(old_size, new_size)
};
fn numeric_cast_compat(new_size: IntegerBits, old_size: IntegerBits) -> NumericCastCompatResult {
// If this is a downcast, warn for loss of precision. If upcast, then no warning.
use IntegerBits::*;
match (new_size, old_size) {
Expand Down

0 comments on commit 5fd3cc3

Please sign in to comment.