Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treat trait exclusively as Item not Type #744

Merged
merged 1 commit into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions crates/analyzer/src/db/queries/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,14 +330,6 @@ pub fn contract_field_type(

let node = &field.data(db).ast;

if let Ok(Type::Trait(ref val)) = typ {
scope.error(
"traits can not be used as contract fields",
node.span,
&format!("trait `{}` can not appear here", val.name),
);
}

if node.kind.is_pub {
scope.not_yet_implemented("contract `pub` fields", node.span);
}
Expand Down
22 changes: 5 additions & 17 deletions crates/analyzer/src/db/queries/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::namespace::items::{
use crate::namespace::scopes::{BlockScope, BlockScopeType, FunctionScope, ItemScope};
use crate::namespace::types::{self, Contract, CtxDecl, Generic, SelfDecl, Struct, Type};
use crate::traversal::functions::traverse_statements;
use crate::traversal::types::type_desc;
use crate::traversal::types::{type_desc, type_desc_to_trait};
use fe_common::diagnostics::Label;
use fe_parser::ast::{self, GenericParameter};
use fe_parser::node::Node;
Expand Down Expand Up @@ -255,17 +255,9 @@ pub fn resolve_function_param_type(
if let Some(val) = function.generic_param(db, base) {
let bounds = match val {
ast::GenericParameter::Unbounded(_) => vec![],
ast::GenericParameter::Bounded { bound, .. } => match type_desc(context, &bound)? {
Type::Trait(trait_ty) => vec![trait_ty.id],
other => {
context.error(
&format!("expected trait, found type `{}`", other),
bound.span,
"not a trait",
);
vec![]
}
},
ast::GenericParameter::Bounded { bound, .. } => {
vec![type_desc_to_trait(context, &bound)?]
}
};

return Ok(Type::Generic(Generic {
Expand Down Expand Up @@ -401,11 +393,7 @@ pub fn function_dependency_graph(db: &dyn AnalyzerDb, function: FunctionId) -> D
directs.push((root, Item::Function(*method), DepLocality::Local));
}
CallType::TraitValueMethod { trait_id, .. } => {
directs.push((
root,
Item::Type(TypeDef::Trait(*trait_id)),
DepLocality::Local,
));
directs.push((root, Item::Trait(*trait_id), DepLocality::Local));
}
CallType::External { contract, function } => {
directs.push((root, Item::Function(*function), DepLocality::External));
Expand Down
12 changes: 5 additions & 7 deletions crates/analyzer/src/db/queries/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,10 @@ pub fn module_all_items(db: &dyn AnalyzerDb, module: ModuleId) -> Rc<[Item]> {
ast::ModuleStmt::Function(node) => Some(Item::Function(
db.intern_function(Rc::new(Function::new(db, node, None, module))),
)),
ast::ModuleStmt::Trait(node) => Some(Item::Type(TypeDef::Trait(db.intern_trait(
Rc::new(Trait {
ast: node.clone(),
module,
}),
)))),
ast::ModuleStmt::Trait(node) => Some(Item::Trait(db.intern_trait(Rc::new(Trait {
ast: node.clone(),
module,
})))),
ast::ModuleStmt::Pragma(_) | ast::ModuleStmt::Use(_) | ast::ModuleStmt::Impl(_) => None,
ast::ModuleStmt::Event(node) => Some(Item::Event(db.intern_event(Rc::new(Event {
ast: node.clone(),
Expand All @@ -119,7 +117,7 @@ pub fn module_all_impls(db: &dyn AnalyzerDb, module: ModuleId) -> Rc<[ImplId]> {
let mut scope = ItemScope::new(db, module);
let receiver_type = type_desc(&mut scope, &impl_node.kind.receiver).unwrap();

if let Some(Item::Type(TypeDef::Trait(val))) = treit {
if let Some(Item::Trait(val)) = treit {
Some(db.intern_impl(Rc::new(Impl {
trait_id: val,
receiver: receiver_type,
Expand Down
24 changes: 11 additions & 13 deletions crates/analyzer/src/namespace/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub enum Item {
// Events aren't normal types; they *could* be moved into
// TypeDef, but it would have consequences.
Event(EventId),
Trait(TraitId),
Function(FunctionId),
Constant(ModuleConstantId),
// Needed until we can represent keccak256 as a FunctionId.
Expand All @@ -48,6 +49,7 @@ impl Item {
pub fn name(&self, db: &dyn AnalyzerDb) -> SmolStr {
match self {
Item::Type(id) => id.name(db),
Item::Trait(id) => id.name(db),
Item::GenericType(id) => id.name(),
Item::Event(id) => id.name(db),
Item::Function(id) => id.name(db),
Expand All @@ -62,6 +64,7 @@ impl Item {
pub fn name_span(&self, db: &dyn AnalyzerDb) -> Option<Span> {
match self {
Item::Type(id) => id.name_span(db),
Item::Trait(id) => Some(id.name_span(db)),
Item::GenericType(_) => None,
Item::Event(id) => Some(id.name_span(db)),
Item::Function(id) => Some(id.name_span(db)),
Expand All @@ -81,6 +84,7 @@ impl Item {
| Self::Intrinsic(_)
| Self::GenericType(_) => true,
Self::Type(id) => id.is_public(db),
Self::Trait(id) => id.is_public(db),
Self::Event(id) => id.is_public(db),
Self::Function(id) => id.is_public(db),
Self::Constant(id) => id.is_public(db),
Expand All @@ -94,6 +98,7 @@ impl Item {
| Item::BuiltinFunction(_)
| Item::Intrinsic(_) => true,
Item::Type(_)
| Item::Trait(_)
| Item::Event(_)
| Item::Function(_)
| Item::Constant(_)
Expand All @@ -113,6 +118,7 @@ impl Item {
pub fn item_kind_display_name(&self) -> &'static str {
match self {
Item::Type(_) | Item::GenericType(_) => "type",
Item::Trait(_) => "trait",
Item::Event(_) => "event",
Item::Function(_) | Item::BuiltinFunction(_) => "function",
Item::Intrinsic(_) => "intrinsic function",
Expand All @@ -129,6 +135,7 @@ impl Item {
Item::Type(val) => val.items(db),
Item::GenericType(_)
| Item::Event(_)
| Item::Trait(_)
| Item::Function(_)
| Item::Constant(_)
| Item::BuiltinFunction(_)
Expand All @@ -139,6 +146,7 @@ impl Item {
pub fn parent(&self, db: &dyn AnalyzerDb) -> Option<Item> {
match self {
Item::Type(id) => id.parent(db),
Item::Trait(id) => Some(id.parent(db)),
Item::GenericType(_) => None,
Item::Event(id) => Some(id.parent(db)),
Item::Function(id) => Some(id.parent(db)),
Expand Down Expand Up @@ -222,6 +230,7 @@ impl Item {
pub fn sink_diagnostics(&self, db: &dyn AnalyzerDb, sink: &mut impl DiagnosticSink) {
match self {
Item::Type(id) => id.sink_diagnostics(db, sink),
Item::Trait(id) => id.sink_diagnostics(db, sink),
Item::Event(id) => id.sink_diagnostics(db, sink),
Item::Function(id) => id.sink_diagnostics(db, sink),
Item::GenericType(_) | Item::BuiltinFunction(_) | Item::Intrinsic(_) => {}
Expand Down Expand Up @@ -772,7 +781,6 @@ impl ModuleConstantId {
pub enum TypeDef {
Alias(TypeAliasId),
Struct(StructId),
Trait(TraitId),
Contract(ContractId),
Primitive(types::Base),
}
Expand Down Expand Up @@ -804,7 +812,6 @@ impl TypeDef {
match self {
TypeDef::Alias(id) => id.name(db),
TypeDef::Struct(id) => id.name(db),
TypeDef::Trait(id) => id.name(db),
TypeDef::Contract(id) => id.name(db),
TypeDef::Primitive(typ) => typ.name(),
}
Expand All @@ -814,7 +821,6 @@ impl TypeDef {
match self {
TypeDef::Alias(id) => Some(id.name_span(db)),
TypeDef::Struct(id) => Some(id.name_span(db)),
TypeDef::Trait(id) => Some(id.name_span(db)),
TypeDef::Contract(id) => Some(id.name_span(db)),
TypeDef::Primitive(_) => None,
}
Expand All @@ -828,10 +834,6 @@ impl TypeDef {
name: id.name(db),
field_count: id.fields(db).len(), // for the EvmSized trait
})),
TypeDef::Trait(id) => Ok(types::Type::Trait(types::Trait {
id: *id,
name: id.name(db),
})),
TypeDef::Contract(id) => Ok(types::Type::Contract(types::Contract {
id: *id,
name: id.name(db),
Expand All @@ -844,7 +846,6 @@ impl TypeDef {
match self {
Self::Alias(id) => id.is_public(db),
Self::Struct(id) => id.is_public(db),
Self::Trait(id) => id.is_public(db),
Self::Contract(id) => id.is_public(db),
Self::Primitive(_) => true,
}
Expand All @@ -854,7 +855,6 @@ impl TypeDef {
match self {
TypeDef::Alias(id) => Some(id.parent(db)),
TypeDef::Struct(id) => Some(id.parent(db)),
TypeDef::Trait(id) => Some(id.parent(db)),
TypeDef::Contract(id) => Some(id.parent(db)),
TypeDef::Primitive(_) => None,
}
Expand All @@ -864,7 +864,6 @@ impl TypeDef {
match self {
TypeDef::Alias(id) => id.sink_diagnostics(db, sink),
TypeDef::Struct(id) => id.sink_diagnostics(db, sink),
TypeDef::Trait(id) => id.sink_diagnostics(db, sink),
TypeDef::Contract(id) => id.sink_diagnostics(db, sink),
TypeDef::Primitive(_) => {}
}
Expand Down Expand Up @@ -1158,7 +1157,7 @@ impl FunctionSigId {
}

pub fn is_trait_fn(&self, db: &dyn AnalyzerDb) -> bool {
matches!(self.parent(db), Item::Type(TypeDef::Trait(_)))
matches!(self.parent(db), Item::Trait(_))
}

pub fn is_impl_fn(&self, db: &dyn AnalyzerDb) -> bool {
Expand Down Expand Up @@ -1344,7 +1343,7 @@ impl Class {
match self {
Class::Contract(id) => Item::Type(TypeDef::Contract(*id)),
Class::Struct(id) => Item::Type(TypeDef::Struct(*id)),
Class::Trait(id) => Item::Type(TypeDef::Trait(*id)),
Class::Trait(id) => Item::Trait(*id),
// Coercing into an Item of the basis of the receiver doesn't seem ideal but can hopefully
// be addressed when we get rid of `Class`.
Class::Impl(id) => id
Expand Down Expand Up @@ -1595,7 +1594,6 @@ impl ImplId {
Type::Contract(_)
| Type::Map(_)
| Type::SelfContract(_)
| Type::Trait(_)
| Type::Generic(_)
// TODO: We should find a way to support these types. We only support implementing traits for structs
// so far because it simplifies things regarding the assign location of the underlying type.
Expand Down
5 changes: 1 addition & 4 deletions crates/analyzer/src/namespace/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ pub enum Type {
/// of `self` within a contract function.
SelfContract(Contract),
Struct(Struct),
Trait(Trait),
Generic(Generic),
}

Expand Down Expand Up @@ -410,7 +409,6 @@ impl Type {
Type::Tuple(inner) => inner.to_string().into(),
Type::String(inner) => inner.to_string().into(),
Type::Struct(inner) => inner.name.clone(),
Type::Trait(inner) => inner.name.clone(),
Type::Generic(inner) => inner.name.clone(),
Type::Contract(inner) | Type::SelfContract(inner) => inner.name.clone(),
}
Expand Down Expand Up @@ -482,7 +480,7 @@ impl Type {
| Type::Struct(_)
| Type::Generic(_)
| Type::Contract(_) => true,
Type::Map(_) | Type::SelfContract(_) | Type::Trait(_) => false,
Type::Map(_) | Type::SelfContract(_) => false,
}
}
}
Expand Down Expand Up @@ -686,7 +684,6 @@ impl fmt::Display for Type {
Type::Contract(inner) => inner.fmt(f),
Type::SelfContract(inner) => inner.fmt(f),
Type::Struct(inner) => inner.fmt(f),
Type::Trait(inner) => inner.fmt(f),
Type::Generic(inner) => inner.fmt(f),
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/analyzer/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub fn index(value: Type, index: Type) -> Result<Type, IndexingError> {
| Type::String(_)
| Type::Contract(_)
| Type::SelfContract(_)
| Type::Trait(_)
| Type::Generic(_)
| Type::Struct(_) => Err(IndexingError::NotSubscriptable),
}
Expand Down
40 changes: 28 additions & 12 deletions crates/analyzer/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::context::{AnalyzerContext, CallType, ExpressionAttributes, Location,
use crate::errors::{FatalError, IndexingError};
use crate::namespace::items::{Class, FunctionId, Item, TypeDef};
use crate::namespace::scopes::BlockScopeType;
use crate::namespace::types::Trait;
use crate::namespace::types::{
Array, Base, Contract, FeString, Integer, Struct, Tuple, Type, TypeDowncast, U256,
};
Expand Down Expand Up @@ -179,7 +178,7 @@ pub fn assignable_expr(
attributes.move_location = Some(Location::Value);
}
}
Array(_) | Tuple(_) | String(_) | Struct(_) | Trait(_) | Generic(_) => {
Array(_) | Tuple(_) | String(_) | Struct(_) | Generic(_) => {
if attributes.final_location() != Location::Memory {
context.fancy_error(
"value must be copied to memory",
Expand Down Expand Up @@ -318,10 +317,24 @@ fn expr_named_thing(
id.receiver(context.db()),
Location::Memory,
)),
Class::Trait(id) => Ok(ExpressionAttributes::new(
Type::Trait(Trait::from_id(id, context.db())),
Location::Memory,
)),
// This can only happen when trait methods can implement a default body
Class::Trait(id) => Err(FatalError::new(context.fancy_error(
&format!(
"`{}` is a trait, and can't be used as an expression",
exp.kind
),
vec![
Label::primary(
id.name_span(context.db()),
&format!("`{}` is defined here as a trait", exp.kind),
),
Label::primary(
exp.span,
&format!("`{}` is used here as a value", exp.kind),
),
],
vec![],
))),
Class::Contract(id) => Ok(ExpressionAttributes::new(
Type::SelfContract(Contract::from_id(id, context.db())),
Location::Value,
Expand Down Expand Up @@ -974,6 +987,14 @@ fn expr_call_named_thing<T: std::fmt::Display>(
func.kind
)],
))),
NamedThing::Item(Item::Trait(_)) => Err(FatalError::new(context.error(
&format!("`{}` is not callable", func.kind),
func.span,
&format!(
"`{}` is a trait, and can't be used as a function",
func.kind
),
))),
NamedThing::Item(Item::Ingot(_)) => Err(FatalError::new(context.error(
&format!("`{}` is not callable", func.kind),
func.span,
Expand Down Expand Up @@ -1129,11 +1150,7 @@ fn expr_call_type_constructor(
Type::Struct(struct_type) => {
return expr_call_struct_constructor(context, name_span, struct_type, args)
}
Type::Base(Base::Bool)
| Type::Array(_)
| Type::Map(_)
| Type::Generic(_)
| Type::Trait(_) => {
Type::Base(Base::Bool) | Type::Array(_) | Type::Map(_) | Type::Generic(_) => {
return Err(FatalError::new(context.error(
&format!("`{}` type is not callable", typ.name()),
name_span,
Expand Down Expand Up @@ -1220,7 +1237,6 @@ fn expr_call_type_constructor(
Type::Struct(_) => unreachable!(), // handled above
Type::Map(_) => unreachable!(), // handled above
Type::Array(_) => unreachable!(), // handled above
Type::Trait(_) => unreachable!(), // handled above
Type::Generic(_) => unreachable!(), // handled above
Type::SelfContract(_) => unreachable!(), /* unnameable; contract names all become
* Type::Contract */
Expand Down
Loading