diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-11-24 22:52:28 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-11-25 13:32:49 +0000 |
commit | a2f59f14ceace0b8e614f972beacd45acfb284c7 (patch) | |
tree | cef0f5c313734f997a2a60539c1824ee0bd26c24 | |
parent | 717b6da459b26ace9a3c303cfa5e485ff8935709 (diff) | |
download | gcc-a2f59f14ceace0b8e614f972beacd45acfb284c7.zip gcc-a2f59f14ceace0b8e614f972beacd45acfb284c7.tar.gz gcc-a2f59f14ceace0b8e614f972beacd45acfb284c7.tar.bz2 |
Bug fix mutability checks in can_eq for autoderef
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.
-rw-r--r-- | gcc/rust/typecheck/rust-hir-dot-operator.h | 6 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-cmp.h | 42 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-rules.h | 10 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 2 |
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; |