Skip to content

Commit 9739ec7

Browse files
tritaoJoshuaBatty
andauthored
Update trait map to track fully resolved impl type parameters. (#6963)
## Description Updates trait map to track fully resolved impl type parameters. To be used for trait coherence checking. ## 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] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [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: Joshua Batty <joshpbatty@gmail.com>
1 parent 27be22c commit 9739ec7

File tree

14 files changed

+128
-52
lines changed

14 files changed

+128
-52
lines changed

sway-core/src/abi_generation/abi_str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl TypeInfo {
9393
Never => "never".into(),
9494
UnknownGeneric { name, .. } => name.to_string(),
9595
Placeholder(_) => "_".to_string(),
96-
TypeParam(n) => format!("typeparam({n})"),
96+
TypeParam(param) => format!("typeparam({})", param.name),
9797
StringSlice => "str".into(),
9898
StringArray(length) => format!("str[{}]", length.val()),
9999
UnsignedInteger(x) => match x {

sway-core/src/abi_generation/evm_abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub fn abi_str(type_info: &TypeInfo, engines: &Engines) -> String {
6969
Never => "never".into(),
7070
UnknownGeneric { name, .. } => name.to_string(),
7171
Placeholder(_) => "_".to_string(),
72-
TypeParam(n) => format!("typeparam({n})"),
72+
TypeParam(param) => format!("typeparam({})", param.name),
7373
StringSlice => "str".into(),
7474
StringArray(x) => format!("str[{}]", x.val()),
7575
UnsignedInteger(x) => match x {

sway-core/src/engine_threading.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,19 @@ impl<T: PartialEqWithEngines> PartialEqWithEngines for [T] {
388388
}
389389
impl<T: OrdWithEngines> OrdWithEngines for [T] {
390390
fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
391-
self.iter()
392-
.zip(other.iter())
393-
.map(|(x, y)| x.cmp(y, ctx))
394-
.find(|o| o.is_ne())
395-
.unwrap_or_else(|| self.len().cmp(&other.len()))
391+
let len_cmp = self.len().cmp(&other.len());
392+
if len_cmp != Ordering::Equal {
393+
return len_cmp;
394+
}
395+
396+
for (a, b) in self.iter().zip(other.iter()) {
397+
let cmp = a.cmp(b, ctx);
398+
if cmp != Ordering::Equal {
399+
return cmp;
400+
}
401+
}
402+
403+
Ordering::Equal
396404
}
397405
}
398406

sway-core/src/semantic_analysis/ast_node/declaration/abi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ impl ty::TyAbiDecl {
427427
CallPath::ident_to_fullpath(self.name.clone(), ctx.namespace()),
428428
vec![],
429429
type_id,
430+
vec![],
430431
&all_items,
431432
&self.span,
432433
Some(self.span()),

sway-core/src/semantic_analysis/ast_node/declaration/auto_impl/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ where
267267
impl_trait.trait_name.clone(),
268268
impl_trait.trait_type_arguments.clone(),
269269
impl_trait.implementing_for.type_id,
270+
impl_trait.impl_type_parameters.clone(),
270271
&impl_trait.items,
271272
&impl_trait.span,
272273
impl_trait

sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs

+2
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ impl TyDecl {
246246
impl_trait.trait_name.clone(),
247247
impl_trait.trait_type_arguments.clone(),
248248
impl_trait.implementing_for.type_id,
249+
impl_trait.impl_type_parameters.clone(),
249250
&impl_trait.items,
250251
&impl_trait.span,
251252
impl_trait
@@ -313,6 +314,7 @@ impl TyDecl {
313314
impl_trait.trait_name.clone(),
314315
impl_trait.trait_type_arguments.clone(),
315316
impl_trait.implementing_for.type_id,
317+
impl_trait.impl_type_parameters.clone(),
316318
impl_trait_items,
317319
&impl_trait.span,
318320
impl_trait

sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs

+2
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,7 @@ impl TyImplSelfOrTrait {
590590
impl_trait.trait_name.clone(),
591591
impl_trait.trait_type_arguments.clone(),
592592
impl_trait.implementing_for.type_id,
593+
impl_trait.impl_type_parameters.clone(),
593594
&impl_trait.items,
594595
&impl_trait.span,
595596
impl_trait
@@ -847,6 +848,7 @@ fn type_check_trait_implementation(
847848
trait_name.clone(),
848849
trait_type_arguments.to_vec(),
849850
implementing_for,
851+
impl_type_parameters.to_vec(),
850852
&this_supertrait_impld_method_refs
851853
.values()
852854
.cloned()

sway-core/src/semantic_analysis/ast_node/declaration/trait.rs

+3
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ impl TyTraitDecl {
167167
CallPath::ident_to_fullpath(name.clone(), ctx.namespace),
168168
new_type_parameters.iter().map(|x| x.into()).collect(),
169169
self_type,
170+
vec![],
170171
&dummy_interface_surface,
171172
&span,
172173
None,
@@ -235,6 +236,7 @@ impl TyTraitDecl {
235236
CallPath::ident_to_fullpath(name.clone(), ctx.namespace()),
236237
new_type_parameters.iter().map(|x| x.into()).collect(),
237238
self_type,
239+
vec![],
238240
&dummy_interface_surface,
239241
&span,
240242
None,
@@ -614,6 +616,7 @@ impl TyTraitDecl {
614616
trait_name.clone(),
615617
type_arguments.to_vec(),
616618
type_id,
619+
vec![],
617620
&all_items,
618621
&trait_name.span(),
619622
Some(self.span()),

sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,7 @@ impl ty::TyExpression {
20012001
abi_name.clone(),
20022002
vec![],
20032003
return_type,
2004+
vec![],
20042005
&abi_items,
20052006
span,
20062007
Some(span.clone()),

sway-core/src/semantic_analysis/namespace/trait_map.rs

+32-21
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ impl From<bool> for CodeBlockFirstPass {
5454
}
5555

5656
#[derive(Clone, Debug)]
57-
struct TraitSuffix {
58-
name: Ident,
59-
args: Vec<TypeArgument>,
57+
pub(crate) struct TraitSuffix {
58+
pub(crate) name: Ident,
59+
pub(crate) args: Vec<TypeArgument>,
6060
}
6161
impl PartialEqWithEngines for TraitSuffix {
6262
fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
@@ -99,17 +99,20 @@ impl DebugWithEngines for TraitSuffix {
9999
type TraitName = Arc<CallPath<TraitSuffix>>;
100100

101101
#[derive(Clone, Debug)]
102-
struct TraitKey {
103-
name: TraitName,
104-
type_id: TypeId,
105-
trait_decl_span: Option<Span>,
102+
pub(crate) struct TraitKey {
103+
pub(crate) name: TraitName,
104+
pub(crate) type_id: TypeId,
105+
pub(crate) impl_type_parameters: Vec<TypeId>,
106+
pub(crate) trait_decl_span: Option<Span>,
106107
}
107108

108109
impl OrdWithEngines for TraitKey {
109110
fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> std::cmp::Ordering {
110-
self.name
111-
.cmp(&other.name, ctx)
112-
.then_with(|| self.type_id.cmp(&other.type_id))
111+
self.name.cmp(&other.name, ctx).then_with(|| {
112+
self.type_id
113+
.cmp(&other.type_id)
114+
.then_with(|| self.impl_type_parameters.cmp(&other.impl_type_parameters))
115+
})
113116
}
114117
}
115118

@@ -148,29 +151,28 @@ impl ResolvedTraitImplItem {
148151
type TraitItems = HashMap<String, ResolvedTraitImplItem>;
149152

150153
#[derive(Clone, Debug)]
151-
struct TraitValue {
152-
trait_items: TraitItems,
154+
pub(crate) struct TraitValue {
155+
pub(crate) trait_items: TraitItems,
153156
/// The span of the entire impl block.
154-
impl_span: Span,
157+
pub(crate) impl_span: Span,
155158
}
156159

157160
#[derive(Clone, Debug)]
158-
struct TraitEntry {
159-
key: TraitKey,
160-
value: TraitValue,
161+
pub(crate) struct TraitEntry {
162+
pub(crate) key: TraitKey,
163+
pub(crate) value: TraitValue,
161164
}
162165

163166
/// Map of string of type entry id and vec of [TraitEntry].
164167
/// We are using the HashMap as a wrapper to the vec so the TraitMap algorithms
165168
/// don't need to traverse every TraitEntry.
166-
type TraitImpls = HashMap<TypeRootFilter, Vec<TraitEntry>>;
169+
pub(crate) type TraitImpls = HashMap<TypeRootFilter, Vec<TraitEntry>>;
167170

168171
#[derive(Clone, Hash, Eq, PartialOrd, Ord, PartialEq, Debug)]
169-
enum TypeRootFilter {
172+
pub(crate) enum TypeRootFilter {
170173
Unknown,
171174
Never,
172175
Placeholder,
173-
TypeParam(usize),
174176
StringSlice,
175177
StringArray(usize),
176178
U8,
@@ -201,7 +203,7 @@ enum TypeRootFilter {
201203
/// [TraitMap].
202204
#[derive(Clone, Debug, Default)]
203205
pub struct TraitMap {
204-
trait_impls: TraitImpls,
206+
pub(crate) trait_impls: TraitImpls,
205207
satisfied_cache: HashSet<u64>,
206208
}
207209

@@ -230,6 +232,7 @@ impl TraitMap {
230232
trait_name: CallPath,
231233
trait_type_args: Vec<TypeArgument>,
232234
type_id: TypeId,
235+
impl_type_parameters: Vec<TypeId>,
233236
items: &[ResolvedTraitImplItem],
234237
impl_span: &Span,
235238
trait_decl_span: Option<Span>,
@@ -276,6 +279,7 @@ impl TraitMap {
276279
name: map_trait_name,
277280
type_id: map_type_id,
278281
trait_decl_span: _,
282+
impl_type_parameters: _,
279283
},
280284
value:
281285
TraitValue {
@@ -464,6 +468,7 @@ impl TraitMap {
464468
impl_span.clone(),
465469
trait_decl_span,
466470
unaliased_type_id,
471+
impl_type_parameters,
467472
trait_items,
468473
engines,
469474
);
@@ -472,19 +477,22 @@ impl TraitMap {
472477
})
473478
}
474479

480+
#[allow(clippy::too_many_arguments)]
475481
fn insert_inner(
476482
&mut self,
477483
trait_name: TraitName,
478484
impl_span: Span,
479485
trait_decl_span: Option<Span>,
480486
type_id: TypeId,
487+
impl_type_parameters: Vec<TypeId>,
481488
trait_methods: TraitItems,
482489
engines: &Engines,
483490
) {
484491
let key = TraitKey {
485492
name: trait_name,
486493
type_id,
487494
trait_decl_span,
495+
impl_type_parameters,
488496
};
489497
let value = TraitValue {
490498
trait_items: trait_methods,
@@ -664,6 +672,7 @@ impl TraitMap {
664672
name: map_trait_name,
665673
type_id: map_type_id,
666674
trait_decl_span: map_trait_decl_span,
675+
impl_type_parameters: map_impl_type_parameters,
667676
},
668677
value:
669678
TraitValue {
@@ -679,6 +688,7 @@ impl TraitMap {
679688
impl_span.clone(),
680689
map_trait_decl_span.clone(),
681690
*type_id,
691+
map_impl_type_parameters.clone(),
682692
map_trait_items.clone(),
683693
engines,
684694
);
@@ -688,6 +698,7 @@ impl TraitMap {
688698
impl_span.clone(),
689699
map_trait_decl_span.clone(),
690700
*map_type_id,
701+
map_impl_type_parameters.clone(),
691702
Self::filter_dummy_methods(
692703
map_trait_items.clone(),
693704
*type_id,
@@ -1496,7 +1507,7 @@ impl TraitMap {
14961507
Unknown => TypeRootFilter::Unknown,
14971508
Never => TypeRootFilter::Never,
14981509
UnknownGeneric { .. } | Placeholder(_) => TypeRootFilter::Placeholder,
1499-
TypeParam(n) => TypeRootFilter::TypeParam(*n),
1510+
TypeParam(_param) => unreachable!(),
15001511
StringSlice => TypeRootFilter::StringSlice,
15011512
StringArray(x) => TypeRootFilter::StringArray(x.val()),
15021513
UnsignedInteger(x) => match x {

sway-core/src/semantic_analysis/type_check_context.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use crate::{
1919
Namespace,
2020
},
2121
type_system::{SubstTypes, TypeArgument, TypeId, TypeInfo},
22-
EnforceTypeArguments, SubstTypesContext, TraitConstraint, TypeSubstMap, UnifyCheck,
22+
EnforceTypeArguments, SubstTypesContext, TraitConstraint, TypeParameter, TypeSubstMap,
23+
UnifyCheck,
2324
};
2425
use sway_error::{
2526
error::CompileError,
@@ -1291,13 +1292,28 @@ impl<'a> TypeCheckContext<'a> {
12911292
trait_name: CallPath,
12921293
trait_type_args: Vec<TypeArgument>,
12931294
type_id: TypeId,
1295+
mut impl_type_parameters: Vec<TypeParameter>,
12941296
items: &[ty::TyImplItem],
12951297
impl_span: &Span,
12961298
trait_decl_span: Option<Span>,
12971299
is_impl_self: IsImplSelf,
12981300
is_extending_existing_impl: IsExtendingExistingImpl,
12991301
) -> Result<(), ErrorEmitted> {
13001302
let engines = self.engines;
1303+
1304+
// Use trait name with full path, improves consistency between
1305+
// this inserting and getting in `get_methods_for_type_and_trait_name`.
1306+
impl_type_parameters.iter_mut().for_each(|tp| {
1307+
tp.trait_constraints.iter_mut().for_each(|tc| {
1308+
tc.trait_name = tc.trait_name.to_fullpath(self.engines(), self.namespace())
1309+
})
1310+
});
1311+
1312+
let impl_type_parameters_ids = impl_type_parameters
1313+
.iter()
1314+
.map(|type_parameter| engines.te().new_type_param(type_parameter.clone()))
1315+
.collect::<Vec<_>>();
1316+
13011317
// CallPath::to_fullpath gives a resolvable path, but is not guaranteed to provide the path
13021318
// to the actual trait declaration. Since the path of the trait declaration is used as a key
13031319
// in the trait map, we need to find the actual declaration path.
@@ -1316,6 +1332,7 @@ impl<'a> TypeCheckContext<'a> {
13161332
canonical_trait_path,
13171333
trait_type_args,
13181334
type_id,
1335+
impl_type_parameters_ids,
13191336
&items,
13201337
impl_span,
13211338
trait_decl_span,

sway-core/src/type_system/ast_elements/type_parameter.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,14 @@ impl OrdWithEngines for TypeParameter {
9191
fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
9292
let TypeParameter {
9393
type_id: lti,
94-
name: ln,
94+
name: lname,
9595
trait_constraints: ltc,
9696
// these fields are not compared because they aren't relevant/a
9797
// reliable source of obj v. obj distinction
9898
trait_constraints_span: _,
9999
initial_type_id: _,
100100
is_from_parent: _,
101-
} = self;
101+
} = &self;
102102
let TypeParameter {
103103
type_id: rti,
104104
name: rn,
@@ -108,15 +108,13 @@ impl OrdWithEngines for TypeParameter {
108108
trait_constraints_span: _,
109109
initial_type_id: _,
110110
is_from_parent: _,
111-
} = other;
112-
ln.cmp(rn)
113-
.then_with(|| {
114-
ctx.engines()
115-
.te()
116-
.get(*lti)
117-
.cmp(&ctx.engines().te().get(*rti), ctx)
118-
})
119-
.then_with(|| ltc.cmp(rtc, ctx))
111+
} = &other;
112+
let type_engine = ctx.engines().te();
113+
let ltype = type_engine.get(*lti);
114+
let rtype = type_engine.get(*rti);
115+
ltype
116+
.cmp(&rtype, ctx)
117+
.then_with(|| lname.cmp(rn).then_with(|| ltc.cmp(rtc, ctx)))
120118
}
121119
}
122120

0 commit comments

Comments
 (0)