Skip to content

Commit

Permalink
Improved trait coherence checking
Browse files Browse the repository at this point in the history
  • Loading branch information
tritao committed Feb 24, 2025
1 parent af25915 commit 2f559fa
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 188 deletions.
39 changes: 37 additions & 2 deletions sway-core/src/language/call_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ impl<T: Spanned> Spanned for CallPath<T> {
}
}

/// This controls the type of display type for call path display string conversions.
pub enum CallPathDisplayType {
/// Prints the regular call path as exists internally.
Regular,
/// Strips the current root package if it exists as prefix.
StripPackagePrefix,
}

impl CallPath {
pub fn fullpath(path: &[&str]) -> Self {
assert!(!path.is_empty());
Expand Down Expand Up @@ -398,6 +406,27 @@ impl CallPath {
converted
}

pub fn to_display_path(
&self,
display_type: CallPathDisplayType,
namespace: &Namespace,
) -> CallPath {
let mut display_path = self.clone();

match display_type {
CallPathDisplayType::Regular => {}
CallPathDisplayType::StripPackagePrefix => {
if let Some(first) = self.prefixes.first() {
if namespace.root_ref().current_package_root_module().name() == first {
display_path = display_path.lshift();
}
}
}
};

display_path
}

/// Create a string form of the given [CallPath] and zero or more [TypeArgument]s.
/// The returned string is convenient for displaying full names, including generic arguments, in help messages.
/// E.g.:
Expand Down Expand Up @@ -553,11 +582,17 @@ impl CallPath {
Some(module) => {
// Resolve the path suffix in the found module
match module.resolve_symbol(&Handler::default(), engines, &full_path.suffix) {
Ok((_, decl_path)) => {
Ok((decl, decl_path)) => {
let name = decl.expect_typed().get_name(engines);
let suffix = if name.as_str() != full_path.suffix.as_str() {
name
} else {
full_path.suffix
};
// Replace the resolvable path with the declaration's path
CallPath {
prefixes: decl_path,
suffix: full_path.suffix.clone(),
suffix,
callpath_type: full_path.callpath_type,
}
}
Expand Down
62 changes: 61 additions & 1 deletion sway-core/src/language/ty/declaration/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use sway_error::{
error::CompileError,
handler::{ErrorEmitted, Handler},
};
use sway_types::{Ident, Named, Span, Spanned};
use sway_types::{BaseIdent, Ident, Named, Span, Spanned};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum TyDecl {
Expand Down Expand Up @@ -667,6 +667,66 @@ impl TyDecl {
}
}

pub fn get_name(&self, engines: &Engines) -> BaseIdent {
match self {
TyDecl::VariableDecl(ty_variable_decl) => ty_variable_decl.name.clone(),
TyDecl::ConstantDecl(constant_decl) => engines
.de()
.get_constant(&constant_decl.decl_id)
.call_path
.suffix
.clone(),
TyDecl::ConfigurableDecl(configurable_decl) => engines
.de()
.get_configurable(&configurable_decl.decl_id)
.call_path
.suffix
.clone(),
TyDecl::TraitTypeDecl(trait_type_decl) => {
engines.de().get_type(&trait_type_decl.decl_id).name.clone()
}
TyDecl::FunctionDecl(function_decl) => engines
.de()
.get_function(&function_decl.decl_id)
.name
.clone(),
TyDecl::TraitDecl(trait_decl) => {
engines.de().get_trait(&trait_decl.decl_id).name.clone()
}
TyDecl::StructDecl(struct_decl) => engines
.de()
.get_struct(&struct_decl.decl_id)
.call_path
.suffix
.clone(),
TyDecl::EnumDecl(enum_decl) => engines
.de()
.get_enum(&enum_decl.decl_id)
.call_path
.suffix
.clone(),
TyDecl::EnumVariantDecl(_enum_variant_decl) => {
unreachable!()
}
TyDecl::ImplSelfOrTrait(impl_self_or_trait) => engines
.de()
.get_impl_self_or_trait(&impl_self_or_trait.decl_id)
.trait_name
.suffix
.clone(),
TyDecl::AbiDecl(abi_decl) => engines.de().get_abi(&abi_decl.decl_id).name.clone(),
TyDecl::GenericTypeForFunctionScope(_generic_type_for_function_scope) => unreachable!(),
TyDecl::ErrorRecovery(_span, _error_emitted) => unreachable!(),
TyDecl::StorageDecl(_storage_decl) => unreachable!(),
TyDecl::TypeAliasDecl(type_alias_decl) => engines
.de()
.get_type_alias(&type_alias_decl.decl_id)
.call_path
.suffix
.clone(),
}
}

/// Friendly name string used for error reporting,
/// which consists of the identifier for the declaration.
pub fn friendly_name(&self, engines: &Engines) -> String {
Expand Down
10 changes: 2 additions & 8 deletions sway-core/src/semantic_analysis/namespace/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -909,16 +909,10 @@ impl Root {
ignored_prefixes += 1;
}

println!("{:?}", ignored_prefixes);
println!("prefixes {:?}", iter_prefixes(src).collect::<Vec<_>>());
// Check visibility of remaining submodules in the source path
for prefix in iter_prefixes(src) {
let prefix = prefix.iter().skip(ignored_prefixes).cloned().collect::<Vec<_>>();
println!("prefix {:?}", prefix);
if let Some(module) = self.module_from_absolute_path(&prefix) {
for prefix in iter_prefixes(src).skip(ignored_prefixes) {
if let Some(module) = self.module_from_absolute_path(&prefix.to_vec()) {
if module.visibility().is_private() {
println!("src {:?}", src);
println!("dst {:?}", dst);
let prefix_last = prefix[prefix.len() - 1].clone();
handler.emit_err(CompileError::ImportPrivateModule {
span: prefix_last.span(),
Expand Down
11 changes: 9 additions & 2 deletions sway-core/src/type_system/ast_elements/trait_constraint.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::{
engine_threading::*,
language::{parsed::Supertrait, ty, CallPath},
language::{parsed::Supertrait, ty, CallPath, CallPathDisplayType},
semantic_analysis::{
declaration::{insert_supertraits_into_namespace, SupertraitOf},
TypeCheckContext,
},
type_system::priv_prelude::*,
types::{CollectTypesMetadata, CollectTypesMetadataContext, TypeMetadata},
EnforceTypeArguments,
EnforceTypeArguments, Namespace,
};
use serde::{Deserialize, Serialize};
use std::{
Expand Down Expand Up @@ -263,4 +263,11 @@ impl TraitConstraint {

Ok(())
}

pub fn to_display_name(&self, engines: &Engines, namespace: &Namespace) -> String {
let display_path = self
.trait_name
.to_display_path(CallPathDisplayType::StripPackagePrefix, namespace);
display_path.to_string_with_args(engines, &self.type_arguments)
}
}
4 changes: 2 additions & 2 deletions sway-core/src/type_system/ast_elements/type_parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
use std::{
cmp::Ordering,
collections::BTreeMap,
fmt,
fmt::{self},
hash::{Hash, Hasher},
};
use sway_error::{
Expand Down Expand Up @@ -558,7 +558,7 @@ impl TypeParameter {
return Err(handler.emit_err(CompileError::MultipleImplsSatisfyingTraitForType{
span:access_span.clone(),
type_annotation: engines.help_out(type_id).to_string(),
trait_names: trait_constraints.iter().map(|t| engines.help_out(t).to_string()).collect(),
trait_names: trait_constraints.iter().map(|t| t.to_display_name(engines, ctx.namespace())).collect(),
trait_types_and_names: concrete_trait_type_ids.iter().map(|t| (engines.help_out(t.0).to_string(), t.1.clone())).collect::<Vec<_>>()
}));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ category = "fail"
# check: $()let b = a.set(42);
# check: $()No method "set(FooBarData<u8>, numeric) -> bool" found for type "FooBarData<u8>".

# check: $()Aborting due to 22 errors.
# check: $()Aborting due to 24 errors.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit 2f559fa

Please sign in to comment.