Skip to content

Commit

Permalink
Collect full call paths in generic types (FuelLabs#4075)
Browse files Browse the repository at this point in the history
## Description
Replace simple ident based `SpanTree` with a `CallPathTree` to handle
call path based field definitions for all `TypeArgument`s.

Fix FuelLabs#4056


## 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.

Co-authored-by: Mohammad Fawaz <[email protected]>
Co-authored-by: João Matos <[email protected]>
  • Loading branch information
3 people authored Feb 14, 2023
1 parent f5e2065 commit f7cbf83
Show file tree
Hide file tree
Showing 17 changed files with 225 additions and 137 deletions.
6 changes: 6 additions & 0 deletions sway-core/src/language/call_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use crate::{Ident, Namespace};

use sway_types::{span::Span, Spanned};

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct CallPathTree {
pub call_path: CallPath,
pub children: Vec<CallPathTree>,
}

/// in the expression `a::b::c()`, `a` and `b` are the prefixes and `c` is the suffix.
/// `c` can be any type `T`, but in practice `c` is either an `Ident` or a `TypeInfo`.
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
Expand Down
12 changes: 6 additions & 6 deletions sway-core/src/semantic_analysis/ast_node/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ fn test_function_selector_behavior() {
parameters: vec![],
span: Span::dummy(),
attributes: Default::default(),
return_type: TypeArgument::no_spans(0.into()),
return_type: TypeId::from(0).into(),
type_parameters: vec![],
visibility: Visibility::Public,
is_contract_call: false,
Expand All @@ -245,9 +245,9 @@ fn test_function_selector_behavior() {
is_reference: false,
is_mutable: false,
mutability_span: Span::dummy(),
type_argument: TypeArgument::no_spans(
type_engine.insert(&decl_engine, TypeInfo::Str(Length::new(5, Span::dummy()))),
),
type_argument: type_engine
.insert(&decl_engine, TypeInfo::Str(Length::new(5, Span::dummy())))
.into(),
},
ty::TyFunctionParameter {
name: Ident::new_no_span("baz"),
Expand All @@ -262,13 +262,13 @@ fn test_function_selector_behavior() {
initial_type_id: type_engine
.insert(&decl_engine, TypeInfo::Str(Length::new(5, Span::dummy()))),
span: Span::dummy(),
name_spans: None,
call_path_tree: None,
},
},
],
span: Span::dummy(),
attributes: Default::default(),
return_type: TypeArgument::no_spans(0.into()),
return_type: TypeId::from(0).into(),
type_parameters: vec![],
visibility: Visibility::Public,
is_contract_call: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl ty::TyTraitFn {
type_id: self.return_type,
initial_type_id: self.return_type,
span: self.return_type_span.clone(),
name_spans: None,
call_path_tree: None,
},
visibility: Visibility::Public,
type_parameters: vec![],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn type_check_size_of_type(
type_id,
initial_type_id,
span: targ.span,
name_spans: targ.name_spans,
call_path_tree: targ.call_path_tree,
}],
span,
};
Expand Down Expand Up @@ -225,7 +225,7 @@ fn type_check_is_reference_type(
type_id,
initial_type_id,
span: targ.span,
name_spans: targ.name_spans,
call_path_tree: targ.call_path_tree,
}],
span,
};
Expand Down Expand Up @@ -483,7 +483,7 @@ fn type_check_gtf(
type_id,
initial_type_id,
span: targ.span,
name_spans: targ.name_spans,
call_path_tree: targ.call_path_tree,
}],
span,
},
Expand Down Expand Up @@ -792,7 +792,7 @@ fn type_check_state_store_word(
type_id,
initial_type_id,
span: span.clone(),
name_spans: targ.name_spans.clone(),
call_path_tree: targ.call_path_tree.clone(),
}
});
let intrinsic_function = ty::TyIntrinsicFunctionKind {
Expand Down Expand Up @@ -917,7 +917,7 @@ fn type_check_state_quad(
type_id,
initial_type_id,
span: span.clone(),
name_spans: targ.name_spans.clone(),
call_path_tree: targ.call_path_tree.clone(),
}
});
let intrinsic_function = ty::TyIntrinsicFunctionKind {
Expand Down Expand Up @@ -1263,7 +1263,7 @@ fn type_check_ptr_ops(
type_id,
initial_type_id,
span: targ.span,
name_spans: targ.name_spans,
call_path_tree: targ.call_path_tree,
}],
span,
},
Expand Down Expand Up @@ -1342,7 +1342,7 @@ fn type_check_smo(
type_id,
initial_type_id,
span: span.clone(),
name_spans: targ.name_spans.clone(),
call_path_tree: targ.call_path_tree.clone(),
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
language::{parsed::MatchBranch, ty},
semantic_analysis::*,
types::DeterministicallyAborts,
CompileResult, TypeArgument, TypeInfo,
CompileResult, TypeInfo,
};

use super::matcher::matcher;
Expand Down Expand Up @@ -52,7 +52,7 @@ impl ty::TyMatchBranch {
// insert it into the branch namespace, and add it to a block of code statements
let mut code_block_contents: Vec<ty::TyAstNode> = vec![];
for (left_decl, right_decl) in match_decl_map.into_iter() {
let type_ascription = TypeArgument::no_spans(right_decl.return_type);
let type_ascription = right_decl.return_type.into();
let return_type = right_decl.return_type;
let span = left_decl.span().clone();
let var_decl =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fn type_check_tuple(
type_id: x.type_id,
initial_type_id: x.type_id,
span: span.clone(),
name_spans: None,
call_path_tree: None,
})
.collect(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ impl ty::TyExpression {
type_id: initial_type_id,
initial_type_id,
span: Span::dummy(),
name_spans: None,
call_path_tree: None,
}
});
let field_span = field.span();
Expand All @@ -883,7 +883,7 @@ impl ty::TyExpression {
type_id: typed_field.return_type,
initial_type_id: field_type.type_id,
span: typed_field.span.clone(),
name_spans: None,
call_path_tree: None,
});
typed_fields.push(typed_field);
}
Expand Down Expand Up @@ -1415,7 +1415,7 @@ impl ty::TyExpression {
TypeArgument {
type_id: unknown_type,
span: Span::dummy(),
name_spans: None,
call_path_tree: None,
initial_type_id: unknown_type,
},
Length::new(0, Span::dummy()),
Expand Down Expand Up @@ -1476,7 +1476,7 @@ impl ty::TyExpression {
TypeArgument {
type_id: elem_type,
span: Span::dummy(),
name_spans: None,
call_path_tree: None,
initial_type_id: elem_type,
},
Length::new(array_count, Span::dummy()),
Expand Down Expand Up @@ -1902,7 +1902,7 @@ mod tests {
TypeArgument {
type_id: type_engine.insert(&decl_engine, TypeInfo::Boolean),
span: Span::dummy(),
name_spans: None,
call_path_tree: None,
initial_type_id: type_engine.insert(&decl_engine, TypeInfo::Boolean),
},
Length::new(2, Span::dummy()),
Expand Down Expand Up @@ -2036,7 +2036,7 @@ mod tests {
TypeArgument {
type_id: type_engine.insert(&decl_engine, TypeInfo::Boolean),
span: Span::dummy(),
name_spans: None,
call_path_tree: None,
initial_type_id: type_engine.insert(&decl_engine, TypeInfo::Boolean),
},
Length::new(0, Span::dummy()),
Expand Down
100 changes: 61 additions & 39 deletions sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use sway_types::{
},
integer_bits::IntegerBits,
};
use sway_types::{Ident, Span, SpanTree, Spanned};
use sway_types::{Ident, Span, Spanned};

use std::{
collections::{HashMap, HashSet},
Expand Down Expand Up @@ -435,7 +435,7 @@ fn item_fn_to_function_declaration(
type_id,
initial_type_id: type_id,
span: item_fn.fn_signature.span(),
name_spans: None,
call_path_tree: None,
}
}
};
Expand Down Expand Up @@ -620,24 +620,10 @@ fn path_type_to_call_path_and_type_arguments(
context: &mut Context,
handler: &Handler,
engines: Engines<'_>,
PathType {
root_opt,
prefix,
mut suffix,
}: PathType,
path_type: PathType,
) -> Result<(CallPath, Vec<TypeArgument>), ErrorEmitted> {
let (prefixes, suffix) = match suffix.pop() {
None => (Vec::new(), prefix),
Some((_, last)) => {
// Gather the idents of the prefix, i.e. all segments but the last one.
let mut before = Vec::with_capacity(suffix.len() + 1);
before.push(path_type_segment_to_ident(context, handler, prefix)?);
for (_, seg) in suffix {
before.push(path_type_segment_to_ident(context, handler, seg)?);
}
(before, last)
}
};
let root_opt = path_type.root_opt.clone();
let (prefixes, suffix) = path_type_to_prefixes_and_suffix(context, handler, path_type)?;

let call_path = CallPath {
prefixes,
Expand Down Expand Up @@ -731,7 +717,7 @@ pub(crate) fn item_const_to_constant_declaration(
let span = item_const.span();
let type_ascription = match item_const.ty_opt {
Some((_colon_token, ty)) => ty_to_type_argument(context, handler, engines, ty)?,
None => TypeArgument::no_spans(engines.te().insert(engines.de(), TypeInfo::Unknown)),
None => engines.te().insert(engines.de(), TypeInfo::Unknown).into(),
};

Ok(ConstantDeclaration {
Expand Down Expand Up @@ -1026,7 +1012,7 @@ fn fn_args_to_function_parameters(
type_id,
initial_type_id: type_id,
span: self_token.span(),
name_spans: None,
call_path_tree: None,
},
}];
if let Some((_comma_token, args)) = args_opt {
Expand Down Expand Up @@ -1103,22 +1089,59 @@ fn ty_to_type_info(
Ok(type_info)
}

fn ty_to_span_tree(ty: &Ty) -> Result<Option<SpanTree>, ErrorEmitted> {
if let Some(span) = ty.name_span() {
let children = if let Ty::Path(path_type) = &ty {
if let Some((_, generic_args)) = &path_type.last_segment().generics_opt {
(&generic_args.parameters.inner)
.into_iter()
.filter_map(|ty| ty_to_span_tree(ty).transpose())
.collect::<Result<Vec<_>, _>>()?
} else {
vec![]
fn path_type_to_prefixes_and_suffix(
context: &mut Context,
handler: &Handler,
PathType {
root_opt: _,
prefix,
mut suffix,
}: PathType,
) -> Result<(Vec<Ident>, PathTypeSegment), ErrorEmitted> {
Ok(match suffix.pop() {
None => (Vec::new(), prefix),
Some((_, last)) => {
// Gather the idents of the prefix, i.e. all segments but the last one.
let mut before = Vec::with_capacity(suffix.len() + 1);
before.push(path_type_segment_to_ident(context, handler, prefix)?);
for (_, seg) in suffix {
before.push(path_type_segment_to_ident(context, handler, seg)?);
}
(before, last)
}
})
}

fn ty_to_call_path_tree(
context: &mut Context,
handler: &Handler,
ty: Ty,
) -> Result<Option<CallPathTree>, ErrorEmitted> {
if let Ty::Path(path_type) = ty {
let root_opt = path_type.root_opt.clone();
let (prefixes, suffix) = path_type_to_prefixes_and_suffix(context, handler, path_type)?;

let children = if let Some((_, generic_args)) = suffix.generics_opt {
generic_args
.parameters
.inner
.into_iter()
.filter_map(|ty| ty_to_call_path_tree(context, handler, ty).transpose())
.collect::<Result<Vec<_>, _>>()?
} else {
vec![]
};

Ok(Some(SpanTree { span, children }))
let call_path = CallPath {
prefixes,
suffix: suffix.name,
is_absolute: path_root_opt_to_bool(context, handler, root_opt)?,
};

Ok(Some(CallPathTree {
call_path,
children,
}))
} else {
Ok(None)
}
Expand All @@ -1133,14 +1156,14 @@ fn ty_to_type_argument(
let type_engine = engines.te();
let decl_engine = engines.de();
let span = ty.span();
let name_spans = ty_to_span_tree(&ty)?;
let call_path_tree = ty_to_call_path_tree(context, handler, ty.clone())?;
let initial_type_id =
type_engine.insert(decl_engine, ty_to_type_info(context, handler, engines, ty)?);

let type_argument = TypeArgument {
type_id: initial_type_id,
initial_type_id,
name_spans,
call_path_tree,
span,
};
Ok(type_argument)
Expand Down Expand Up @@ -1652,7 +1675,7 @@ fn expr_to_expression(
type_id,
initial_type_id: type_id,
span: var_decl_name.span(),
name_spans: None,
call_path_tree: None,
}
},
name: var_decl_name,
Expand Down Expand Up @@ -2864,7 +2887,7 @@ fn statement_let_to_ast_nodes(
type_id,
initial_type_id: type_id,
span: name.span(),
name_spans: None,
call_path_tree: None,
}
}
};
Expand Down Expand Up @@ -2918,7 +2941,7 @@ fn statement_let_to_ast_nodes(
type_id,
initial_type_id: type_id,
span: destructure_name.span(),
name_spans: None,
call_path_tree: None,
}
}
};
Expand Down Expand Up @@ -3009,7 +3032,7 @@ fn statement_let_to_ast_nodes(
type_id,
initial_type_id: type_id,
span: tuple_name.span(),
name_spans: None,
call_path_tree: None,
}
}
};
Expand Down Expand Up @@ -3277,7 +3300,6 @@ fn ty_to_type_parameter(
})
}

#[allow(dead_code)]
fn path_type_to_ident(
context: &mut Context,
handler: &Handler,
Expand Down
Loading

0 comments on commit f7cbf83

Please sign in to comment.