diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-11-25 15:28:54 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-25 15:28:54 +0000 |
commit | 98fb902fb3029da33c5a8d2fd4bd7d7bcb7271ee (patch) | |
tree | 7f218adb953e271d4e9053a28d91554600df66d9 | |
parent | 295f0ae16613b44c13a15ae5ada080761b62ff54 (diff) | |
parent | a2f59f14ceace0b8e614f972beacd45acfb284c7 (diff) | |
download | gcc-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.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; |