aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-11-25 15:28:54 +0000
committerGitHub <noreply@github.com>2021-11-25 15:28:54 +0000
commit98fb902fb3029da33c5a8d2fd4bd7d7bcb7271ee (patch)
tree7f218adb953e271d4e9053a28d91554600df66d9
parent295f0ae16613b44c13a15ae5ada080761b62ff54 (diff)
parenta2f59f14ceace0b8e614f972beacd45acfb284c7 (diff)
downloadgcc-98fb902fb3029da33c5a8d2fd4bd7d7bcb7271ee.zip
gcc-98fb902fb3029da33c5a8d2fd4bd7d7bcb7271ee.tar.gz
gcc-98fb902fb3029da33c5a8d2fd4bd7d7bcb7271ee.tar.bz2
Merge #820
820: Bug fix mutability checks in can_eq for autoderef r=philberty a=philberty Rust is permissive about mutablity in type checking for example, if we have a function: fn foo(a:&bar) { ... } fn caller() { let a:&mut bar = ...; foo(a); } This is valid since the mutable reference to bar is valid to be turned into an immutable reference without any conversion. Like in C a non-const pointer is valid to be passed to a const pointer inferface. Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.h6
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h42
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h10
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc2
4 files changed, 48 insertions, 12 deletions
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index f88db7e..067ae2c 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -115,7 +115,7 @@ private:
if (fn->is_method ())
{
TyTy::BaseType *fn_self = fn->get_self_type ();
- if (receiver->can_eq (fn_self, false, true))
+ if (fn_self->can_eq (receiver, false, true))
{
return &c;
}
@@ -143,7 +143,7 @@ private:
if (fn->is_method ())
{
TyTy::BaseType *fn_self = fn->get_self_type ();
- if (receiver->can_eq (fn_self, false, true))
+ if (fn_self->can_eq (receiver, false, true))
{
return &c;
}
@@ -165,7 +165,7 @@ private:
if (fn->is_method ())
{
TyTy::BaseType *fn_self = fn->get_self_type ();
- if (receiver->can_eq (fn_self, false, true))
+ if (fn_self->can_eq (receiver, false, true))
{
return &c;
}
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 4ab3df2..a23855e 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -1169,9 +1169,23 @@ public:
auto base_type = base->get_base ();
auto other_base_type = type.get_base ();
- ok = base_type->can_eq (other_base_type, emit_error_flag,
- autoderef_mode_flag)
- && (base->is_mutable () == type.is_mutable ());
+ // rust is permissive about mutablity here you can always go from mutable to
+ // immutable but not the otherway round
+ bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ if (!base_type->can_eq (other_base_type, emit_error_flag,
+ autoderef_mode_flag))
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
}
private:
@@ -1193,9 +1207,23 @@ public:
auto base_type = base->get_base ();
auto other_base_type = type.get_base ();
- ok = base_type->can_eq (other_base_type, emit_error_flag,
- autoderef_mode_flag)
- && (base->is_mutable () == type.is_mutable ());
+ // rust is permissive about mutablity here you can always go from mutable to
+ // immutable but not the otherway round
+ bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ if (!base_type->can_eq (other_base_type, emit_error_flag,
+ autoderef_mode_flag))
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
}
private:
@@ -1276,6 +1304,8 @@ public:
void visit (const NeverType &) override { ok = true; }
+ void visit (const DynamicObjectType &) override { ok = true; }
+
void visit (const PlaceholderType &type) override
{
ok = base->get_symbol ().compare (type.get_symbol ()) == 0;
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index db86de9..f044d0e 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -1209,7 +1209,10 @@ public:
return;
}
- if (base->is_mutable () != type.is_mutable ())
+ // rust is permissive about mutablity here you can always go from mutable to
+ // immutable but not the otherway round
+ bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
{
BaseRules::visit (type);
return;
@@ -1246,7 +1249,10 @@ public:
return;
}
- if (base->is_mutable () != type.is_mutable ())
+ // rust is permissive about mutablity here you can always go from mutable to
+ // immutable but not the otherway round
+ bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
+ if (!mutability_ok)
{
BaseRules::visit (type);
return;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index add4dbe..25fdfa9 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -2786,7 +2786,7 @@ TypeCheckCallExpr::visit (FnPtr &type)
void
TypeCheckMethodCallExpr::visit (FnType &type)
{
- adjusted_self->unify (type.get_self_type ());
+ type.get_self_type ()->unify (adjusted_self);
// +1 for the receiver self
size_t num_args_to_call = call.num_params () + 1;