Skip to content

Commit

Permalink
Fix type-checking and inferring against traits
Browse files Browse the repository at this point in the history
When comparing a class instance against a trait instance, the
implementation of the trait may contain type parameters that are
assigned values in the class instance. If we don't expose these as part
of the type-check, types might not be inferred properly.

This commit fixes this by using a sub TypeContext when comparing against
a trait instance. The TypeArguments of this context are populated
according to the type arguments of the class instance compared against
the trait instance.

Changelog: fixed
  • Loading branch information
yorickpeterse committed Oct 3, 2022
1 parent a620693 commit 7d0c79a
Show file tree
Hide file tree
Showing 7 changed files with 647 additions and 409 deletions.
6 changes: 5 additions & 1 deletion compiler/src/diagnostics.rs
Expand Up @@ -794,12 +794,16 @@ impl Diagnostics {

pub(crate) fn cant_infer_type(
&mut self,
name: String,
file: PathBuf,
location: SourceLocation,
) {
self.error(
DiagnosticId::InvalidType,
"The type of this expression can't be inferred",
format!(
"The type of this expression ('{}') can't be fully inferred",
name,
),
file,
location,
);
Expand Down
19 changes: 12 additions & 7 deletions compiler/src/mir/passes.rs
Expand Up @@ -1564,9 +1564,11 @@ impl<'a> LowerMethod<'a> {

fn array_literal(&mut self, node: hir::ArrayLiteral) -> RegisterId {
if !node.resolved_type.is_inferred(self.db()) {
self.state
.diagnostics
.cant_infer_type(self.file(), node.location.clone());
self.state.diagnostics.cant_infer_type(
types::format_type(self.db(), node.resolved_type),
self.file(),
node.location.clone(),
);
}

let vals: Vec<RegisterId> = node
Expand Down Expand Up @@ -1819,13 +1821,16 @@ impl<'a> LowerMethod<'a> {
&mut self,
typ: types::TypeRef,
location: &SourceLocation,
) -> bool {
) {
if typ.is_inferred(self.db()) {
return true;
return;
}

self.state.diagnostics.cant_infer_type(self.file(), location.clone());
false
self.state.diagnostics.cant_infer_type(
types::format_type(self.db(), typ),
self.file(),
location.clone(),
);
}

fn expected_argument_type(
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/type_check/define_types.rs
Expand Up @@ -471,7 +471,7 @@ impl<'a> CheckTraitImplementations<'a> {

for req in trait_ins.instance_of().required_traits(self.db()) {
if !class_ins.type_check_with_trait_instance(
self.db(),
self.db_mut(),
req,
&mut context,
true,
Expand All @@ -497,6 +497,10 @@ impl<'a> CheckTraitImplementations<'a> {
fn db(&self) -> &Database {
&self.state.db
}

fn db_mut(&mut self) -> &mut Database {
&mut self.state.db
}
}

/// A compiler pass that defines the fields in a class.
Expand Down

0 comments on commit 7d0c79a

Please sign in to comment.