1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
use std::collections::BTreeMap;
use sway_error::error::CompileError;
use sway_error::handler::{ErrorEmitted, Handler};
use sway_types::{Span, Spanned};
use crate::EnforceTypeArguments;
use crate::{
language::{parsed, ty},
semantic_analysis::TypeCheckContext,
TypeId,
};
#[derive(Clone, PartialEq, Eq)]
pub enum SupertraitOf {
Abi(Span), // Span is needed for error reporting
Trait,
}
/// Recursively insert the interface surfaces and methods from supertraits to
/// the given namespace.
pub(crate) fn insert_supertraits_into_namespace(
handler: &Handler,
mut ctx: TypeCheckContext,
type_id: TypeId,
supertraits: &[parsed::Supertrait],
supertraits_of: &SupertraitOf,
) -> Result<(), ErrorEmitted> {
let engines = ctx.engines;
let decl_engine = engines.de();
handler.scope(|handler| {
for supertrait in supertraits.iter() {
// Right now we don't have the ability to support defining a supertrait
// using a callpath directly, so we check to see if the user has done
// this and we disallow it.
if !supertrait.name.prefixes.is_empty() {
handler.emit_err(CompileError::Unimplemented {
feature: "Using module paths to define supertraits".to_string(),
help: vec![
// Note that eventual leading `::` will not be shown. It'a fine for now, we anyhow want to implement using module paths.
format!(
"Import the supertrait by using: `use {};`.",
supertrait.name
),
format!(
"Then, in the list of supertraits, just use the trait name \"{}\".",
supertrait.name.suffix
),
],
span: supertrait.span(),
});
continue;
}
let decl = ctx
// Use the default Handler to avoid emitting the redundant SymbolNotFound error.
.resolve_call_path(&Handler::default(), &supertrait.name)
.ok();
match (decl.clone(), supertraits_of) {
// a trait can be a supertrait of either a trait or a an ABI
(Some(ty::TyDecl::TraitDecl(ty::TraitDecl { decl_id, .. })), _) => {
let mut trait_decl = (*decl_engine.get_trait(&decl_id)).clone();
// Right now we don't parse type arguments for supertraits, so
// we should give this error message to users.
if !trait_decl.type_parameters.is_empty() {
handler.emit_err(CompileError::Unimplemented {
feature: "Using generic traits as supertraits".to_string(),
help: vec![],
span: supertrait.span(),
});
continue;
}
// TODO: right now supertraits can't take type arguments
let mut type_arguments = vec![];
// Monomorphize the trait declaration.
if ctx
.monomorphize(
handler,
&mut trait_decl,
&mut type_arguments,
BTreeMap::new(),
EnforceTypeArguments::Yes,
&supertrait.name.span(),
)
.is_err()
{
continue;
}
// Insert the interface surface and methods from this trait into
// the namespace.
trait_decl.insert_interface_surface_and_items_into_namespace(
handler,
ctx.by_ref(),
&supertrait.name,
&type_arguments,
type_id,
);
// Recurse to insert versions of interfaces and methods of the
// *super* supertraits.
if insert_supertraits_into_namespace(
handler,
ctx.by_ref(),
type_id,
&trait_decl.supertraits,
&SupertraitOf::Trait,
)
.is_err()
{
continue;
}
}
// an ABI can only be a superABI of an ABI
(
Some(ty::TyDecl::AbiDecl(ty::AbiDecl { decl_id, .. })),
SupertraitOf::Abi(subabi_span),
) => {
let abi_decl = decl_engine.get_abi(&decl_id);
// Insert the interface surface and methods from this ABI into
// the namespace.
if abi_decl
.insert_interface_surface_and_items_into_namespace(
handler,
decl_id,
ctx.by_ref(),
type_id,
Some(subabi_span.clone()),
)
.is_err()
{
continue;
}
// Recurse to insert versions of interfaces and methods of the
// *super* superABIs.
if insert_supertraits_into_namespace(
handler,
ctx.by_ref(),
type_id,
&abi_decl.supertraits,
&SupertraitOf::Abi(subabi_span.clone()),
)
.is_err()
{
continue;
}
}
// an ABI cannot be a supertrait of a trait
(Some(ty::TyDecl::AbiDecl { .. }), SupertraitOf::Trait) => {
handler.emit_err(CompileError::AbiAsSupertrait {
span: supertrait.name.span().clone(),
});
}
_ => {
handler.emit_err(CompileError::TraitNotFound {
name: supertrait.name.to_string(),
span: supertrait.name.span(),
});
}
}
}
Ok(())
})
}