Skip to content

Commit

Permalink
Add support for T: inline
Browse files Browse the repository at this point in the history
  • Loading branch information
yorickpeterse committed Nov 27, 2024
1 parent 2334e5d commit 3476d06
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 41 deletions.
2 changes: 2 additions & 0 deletions ast/src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,13 +638,15 @@ impl Node for ReopenClass {
pub enum Requirement {
Trait(TypeName),
Mutable(Location),
Inline(Location),
}

impl Node for Requirement {
fn location(&self) -> &Location {
match self {
Requirement::Trait(n) => &n.location,
Requirement::Mutable(loc) => loc,
Requirement::Inline(loc) => loc,
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions ast/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,7 @@ impl Parser {
let token = self.require()?;
let req = match token.kind {
TokenKind::Mut => Requirement::Mutable(token.location),
TokenKind::Inline => Requirement::Inline(token.location),
_ => Requirement::Trait(
self.type_name_with_optional_namespace(token)?,
),
Expand Down Expand Up @@ -5553,6 +5554,37 @@ mod tests {
}))
);

assert_eq!(
top(parse("impl A if T: inline {}")),
TopLevelExpression::ReopenClass(Box::new(ReopenClass {
class_name: Constant {
source: None,
name: "A".to_string(),
location: cols(6, 6)
},
body: ImplementationExpressions {
values: Vec::new(),
location: cols(21, 22)
},
bounds: Some(TypeBounds {
values: vec![TypeBound {
name: Constant {
source: None,
name: "T".to_string(),
location: cols(11, 11)
},
requirements: Requirements {
values: vec![Requirement::Inline(cols(14, 19))],
location: cols(14, 19)
},
location: cols(11, 19)
}],
location: cols(11, 19)
}),
location: cols(1, 19)
}))
);

assert_eq!(
top(parse("impl A if T: mut, {}")),
TopLevelExpression::ReopenClass(Box::new(ReopenClass {
Expand Down
25 changes: 22 additions & 3 deletions compiler/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,15 +859,34 @@ impl Diagnostics {
);
}

pub(crate) fn type_parameter_already_mutable(
pub(crate) fn duplicate_type_parameter_requirement(
&mut self,
param: &str,
req: &str,
file: PathBuf,
location: Location,
) {
self.error(
DiagnosticId::InvalidType,
format!(
"type parameter '{}' already defines the '{}' requirement",
param, req
),
file,
location,
);
}

pub(crate) fn mutable_inline_type_parameter(
&mut self,
name: &str,
file: PathBuf,
location: Location,
) {
self.error(
DiagnosticId::InvalidType,
format!("the type parameter '{}' is already mutable", name),
"type parameters can't be both 'mut' and 'inline', \
as 'inline' types are immutable"
.to_string(),
file,
location,
);
Expand Down
15 changes: 10 additions & 5 deletions compiler/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2352,18 +2352,22 @@ impl Document {
&mut self,
nodes: &nodes::Requirements,
) -> Node {
use Ordering::*;

let mut pairs = Vec::new();
let mut reqs = nodes.values.iter().collect::<Vec<_>>();

reqs.sort_by(|a, b| match (a, b) {
(Requirement::Mutable(_), Requirement::Mutable(_)) => {
Ordering::Equal
}
(Requirement::Mutable(_), _) => Ordering::Less,
(_, Requirement::Mutable(_)) => Ordering::Greater,
(Requirement::Inline(_), Requirement::Inline(_)) => Equal,
(Requirement::Mutable(_), Requirement::Mutable(_)) => Equal,
(Requirement::Trait(lhs), Requirement::Trait(rhs)) => {
lhs.name.name.cmp(&rhs.name.name)
}
(Requirement::Inline(_), _) => Less,
(Requirement::Mutable(_), Requirement::Inline(_)) => Greater,
(Requirement::Mutable(_), Requirement::Trait(_)) => Less,
(Requirement::Trait(_), Requirement::Mutable(_)) => Greater,
(Requirement::Trait(_), Requirement::Inline(_)) => Greater,
});

for (idx, node) in reqs.into_iter().enumerate() {
Expand All @@ -2377,6 +2381,7 @@ impl Document {
let val = match node {
nodes::Requirement::Trait(n) => self.type_name(n, None),
nodes::Requirement::Mutable(_) => Node::text("mut"),
nodes::Requirement::Inline(_) => Node::text("inline"),
};

pair.push(val);
Expand Down
102 changes: 70 additions & 32 deletions compiler/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ pub(crate) struct TypeBound {
pub(crate) name: Constant,
pub(crate) requirements: Vec<TypeName>,
pub(crate) mutable: bool,
pub(crate) inline: bool,
pub(crate) location: Location,
}

Expand Down Expand Up @@ -644,6 +645,7 @@ pub(crate) struct TypeParameter {
pub(crate) name: Constant,
pub(crate) requirements: Vec<TypeName>,
pub(crate) mutable: bool,
pub(crate) inline: bool,
pub(crate) location: Location,
}

Expand Down Expand Up @@ -1572,28 +1574,68 @@ impl<'a> LowerToHir<'a> {

fn type_bound(&mut self, node: ast::TypeBound) -> TypeBound {
let name = self.constant(node.name);
let (reqs, mutable, inline) = self.define_type_parameter_requirements(
&name.name,
node.requirements.values,
);

TypeBound {
name,
requirements: reqs,
mutable,
inline,
location: node.location,
}
}

fn define_type_parameter_requirements(
&mut self,
name: &str,
nodes: Vec<ast::Requirement>,
) -> (Vec<TypeName>, bool, bool) {
let mut mutable = false;
let mut inline = false;
let mut requirements = Vec::new();

for req in node.requirements.values {
for req in nodes {
match req {
ast::Requirement::Trait(n) => {
requirements.push(self.type_name(n))
}
ast::Requirement::Mutable(loc) if mutable => {
self.state.diagnostics.type_parameter_already_mutable(
&name.name,
self.file(),
loc,
);
let file = self.file();

self.state
.diagnostics
.duplicate_type_parameter_requirement(
name, "mut", file, loc,
);
}
ast::Requirement::Mutable(_) => {
mutable = true;
ast::Requirement::Mutable(loc) if inline => {
self.state
.diagnostics
.mutable_inline_type_parameter(self.file(), loc);
}
ast::Requirement::Inline(loc) if inline => {
let file = self.file();

self.state
.diagnostics
.duplicate_type_parameter_requirement(
name, "mut", file, loc,
);
}
ast::Requirement::Inline(loc) if mutable => {
self.state
.diagnostics
.mutable_inline_type_parameter(self.file(), loc);
}
ast::Requirement::Mutable(_) => mutable = true,
ast::Requirement::Inline(_) => inline = true,
}
}

TypeBound { name, requirements, mutable, location: node.location }
(requirements, mutable, inline)
}

fn define_trait(
Expand Down Expand Up @@ -1903,35 +1945,19 @@ impl<'a> LowerToHir<'a> {
fn type_parameter(&mut self, node: ast::TypeParameter) -> TypeParameter {
let name = self.constant(node.name);
let location = node.location;
let mut mutable = false;
let mut requirements = Vec::new();

if let Some(reqs) = node.requirements {
for req in reqs.values {
match req {
ast::Requirement::Trait(n) => {
requirements.push(self.type_name(n))
}
ast::Requirement::Mutable(loc) if mutable => {
self.state.diagnostics.type_parameter_already_mutable(
&name.name,
self.file(),
loc,
);
}
ast::Requirement::Mutable(_) => {
mutable = true;
}
}
}
}
let (reqs, mutable, inline) = if let Some(reqs) = node.requirements {
self.define_type_parameter_requirements(&name.name, reqs.values)
} else {
(Vec::new(), false, false)
};

TypeParameter {
type_parameter_id: None,
name,
requirements,
requirements: reqs,
location,
mutable,
inline,
}
}

Expand Down Expand Up @@ -3760,6 +3786,7 @@ mod tests {
location: cols(11, 11)
}],
mutable: false,
inline: false,
location: cols(8, 11)
}],
arguments: vec![MethodArgument {
Expand Down Expand Up @@ -3961,6 +3988,7 @@ mod tests {
location: cols(12, 12)
}],
mutable: false,
inline: false,
location: cols(9, 12)
}],
body: vec![ClassExpression::Field(Box::new(DefineField {
Expand Down Expand Up @@ -4164,6 +4192,7 @@ mod tests {
location: cols(20, 20)
}],
mutable: false,
inline: false,
location: cols(17, 20)
}],
body: vec![ClassExpression::Field(Box::new(DefineField {
Expand Down Expand Up @@ -4246,6 +4275,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: false,
inline: false,
location: cols(23, 23)
}],
arguments: vec![MethodArgument {
Expand Down Expand Up @@ -4321,6 +4351,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: false,
inline: false,
location: cols(22, 22)
}],
arguments: vec![MethodArgument {
Expand Down Expand Up @@ -4396,6 +4427,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: false,
inline: false,
location: cols(16, 16)
}],
arguments: vec![MethodArgument {
Expand Down Expand Up @@ -4509,6 +4541,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: false,
inline: false,
location: cols(9, 9)
}],
requirements: vec![TypeName {
Expand Down Expand Up @@ -4579,6 +4612,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: false,
inline: false,
location: cols(16, 16)
}],
arguments: vec![MethodArgument {
Expand Down Expand Up @@ -4718,6 +4752,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: false,
inline: false,
location: cols(16, 16)
}],
arguments: vec![MethodArgument {
Expand Down Expand Up @@ -4828,6 +4863,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: true,
inline: false,
location: cols(11, 16),
}],
body: Vec::new(),
Expand Down Expand Up @@ -5083,6 +5119,7 @@ mod tests {
location: cols(20, 20)
},],
mutable: true,
inline: false,
location: cols(17, 26)
}],
body: Vec::new(),
Expand Down Expand Up @@ -6754,6 +6791,7 @@ mod tests {
},
requirements: Vec::new(),
mutable: false,
inline: false,
location: cols(19, 19)
}],
body: vec![
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/type_check/define_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ impl<'a> DefineTypeParameters<'a> {
pid.set_mutable(self.db_mut());
}

if is_stack {
if is_stack || param.inline {
pid.set_stack_allocated(self.db_mut());
}

Expand Down Expand Up @@ -809,6 +809,10 @@ impl<'a> DefineTypeParameters<'a> {
pid.set_mutable(self.db_mut());
}

if param.inline {
pid.set_stack_allocated(self.db_mut());
}

param.type_parameter_id = Some(pid);
}
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/type_check/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ trait MethodDefiner {
pid.set_mutable(self.db_mut());
}

if param_node.inline {
pid.set_stack_allocated(self.db_mut());
}

param_node.type_parameter_id = Some(pid);
}
}
Expand Down
Loading

0 comments on commit 3476d06

Please sign in to comment.