diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-05-06 13:12:41 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-05-06 16:57:11 +0100 |
commit | cb4d935508def8b250345ba5205a90ad9e177ab4 (patch) | |
tree | 12019e3e3380e793d0d435e59e00ca35d311ff1e | |
parent | 9ea940e4dcabbf99fbb44c125a0af7cf82e48146 (diff) | |
download | gcc-cb4d935508def8b250345ba5205a90ad9e177ab4.zip gcc-cb4d935508def8b250345ba5205a90ad9e177ab4.tar.gz gcc-cb4d935508def8b250345ba5205a90ad9e177ab4.tar.bz2 |
Add new monomorphize_clone interface
This interface is required when we monomorphize since types might be
placeholder -> projection -> param -> actual-type
This gives us a clean clone interface to destructure this into its actual
type. This is important so for example if we have a generic trait function
and resolve the function for a specific set of generics we update the
associated types. This works, then when we go to subsitute the same
generic trait again the placeholders are again updated throwing off the
typing for the first type.
Fixes #1133
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.cc | 3 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 235 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 43 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/issue-1133.rs | 146 |
4 files changed, 417 insertions, 10 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index a3d911e..c499204 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -469,7 +469,8 @@ TypeCheckExpr::resolve_operator_overload ( fn->monomorphize (); // get the return type - TyTy::BaseType *function_ret_tyty = type->get_return_type ()->clone (); + TyTy::BaseType *function_ret_tyty + = type->get_return_type ()->monomorphized_clone (); // store the expected fntype context->insert_operator_overload (expr.get_mappings ().get_hirid (), type); diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index fcbf998..e2dacc9 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -284,6 +284,32 @@ TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst) return TyVar (subst->get_ref ()); } +TyVar +TyVar::clone () const +{ + TyTy::BaseType *c = get_tyty ()->clone (); + return TyVar (c->get_ref ()); +} + +TyVar +TyVar::monomorphized_clone () const +{ + auto mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); + + // this needs a new hirid + TyTy::BaseType *c = get_tyty ()->monomorphized_clone (); + c->set_ref (mappings->get_next_hir_id ()); + + // insert it + context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (), + UNKNOWN_NODEID, c->get_ref (), + UNKNOWN_LOCAL_DEFID), + c); + + return TyVar (c->get_ref ()); +} + void InferType::accept_vis (TyVisitor &vis) { @@ -372,6 +398,12 @@ InferType::clone () const return clone; } +BaseType * +InferType::monomorphized_clone () const +{ + return clone (); +} + bool InferType::default_type (BaseType **type) const { @@ -445,6 +477,12 @@ ErrorType::clone () const return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ()); } +BaseType * +ErrorType::monomorphized_clone () const +{ + return clone (); +} + std::string StructFieldType::as_string () const { @@ -475,6 +513,13 @@ StructFieldType::clone () const get_field_type ()->clone ()); } +StructFieldType * +StructFieldType::monomorphized_clone () const +{ + return new StructFieldType (get_ref (), get_name (), + get_field_type ()->monomorphized_clone ()); +} + bool SubstitutionParamMapping::need_substitution () const { @@ -965,6 +1010,19 @@ ADTType::clone () const get_combined_refs ()); } +BaseType * +ADTType::monomorphized_clone () const +{ + std::vector<VariantDef *> cloned_variants; + for (auto &variant : variants) + cloned_variants.push_back (variant->monomorphized_clone ()); + + return new ADTType (get_ref (), get_ty_ref (), identifier, ident, + get_adt_kind (), cloned_variants, clone_substs (), + get_repr_options (), used_arguments, + get_combined_refs ()); +} + static bool handle_substitions (SubstitutionArgumentMappings &subst_mappings, StructFieldType *field) @@ -1127,8 +1185,23 @@ TupleType::is_equal (const BaseType &other) const BaseType * TupleType::clone () const { - return new TupleType (get_ref (), get_ty_ref (), get_ident ().locus, fields, - get_combined_refs ()); + std::vector<TyVar> cloned_fields; + for (const auto &f : fields) + cloned_fields.push_back (f.clone ()); + + return new TupleType (get_ref (), get_ty_ref (), get_ident ().locus, + cloned_fields, get_combined_refs ()); +} + +BaseType * +TupleType::monomorphized_clone () const +{ + std::vector<TyVar> cloned_fields; + for (const auto &f : fields) + cloned_fields.push_back (f.monomorphized_clone ()); + + return new TupleType (get_ref (), get_ty_ref (), get_ident ().locus, + cloned_fields, get_combined_refs ()); } TupleType * @@ -1265,8 +1338,20 @@ FnType::clone () const { std::vector<std::pair<HIR::Pattern *, BaseType *>> cloned_params; for (auto &p : params) - cloned_params.push_back ( - std::pair<HIR::Pattern *, BaseType *> (p.first, p.second->clone ())); + cloned_params.push_back ({p.first, p.second->clone ()}); + + return new FnType (get_ref (), get_ty_ref (), get_id (), get_identifier (), + ident, flags, abi, std::move (cloned_params), + get_return_type ()->clone (), clone_substs (), + get_combined_refs ()); +} + +BaseType * +FnType::monomorphized_clone () const +{ + std::vector<std::pair<HIR::Pattern *, BaseType *>> cloned_params; + for (auto &p : params) + cloned_params.push_back ({p.first, p.second->monomorphized_clone ()}); return new FnType (get_ref (), get_ty_ref (), get_id (), get_identifier (), ident, flags, abi, std::move (cloned_params), @@ -1480,6 +1565,18 @@ FnPtr::clone () const get_combined_refs ()); } +BaseType * +FnPtr::monomorphized_clone () const +{ + std::vector<TyVar> cloned_params; + for (auto &p : params) + cloned_params.push_back (p.monomorphized_clone ()); + + return new FnPtr (get_ref (), get_ty_ref (), ident.locus, + std::move (cloned_params), result_type, + get_combined_refs ()); +} + void ClosureType::accept_vis (TyVisitor &vis) { @@ -1540,6 +1637,12 @@ ClosureType::clone () const result_type, clone_substs (), get_combined_refs ()); } +BaseType * +ClosureType::monomorphized_clone () const +{ + return clone (); +} + ClosureType * ClosureType::handle_substitions (SubstitutionArgumentMappings mappings) { @@ -1620,6 +1723,14 @@ ArrayType::clone () const element_type, get_combined_refs ()); } +BaseType * +ArrayType::monomorphized_clone () const +{ + return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity_expr, + element_type.monomorphized_clone (), + get_combined_refs ()); +} + ArrayType * ArrayType::handle_substitions (SubstitutionArgumentMappings mappings) { @@ -1705,7 +1816,15 @@ SliceType::get_element_type () const BaseType * SliceType::clone () const { - return new SliceType (get_ref (), get_ty_ref (), ident.locus, element_type, + return new SliceType (get_ref (), get_ty_ref (), ident.locus, + element_type.clone (), get_combined_refs ()); +} + +BaseType * +SliceType::monomorphized_clone () const +{ + return new SliceType (get_ref (), get_ty_ref (), ident.locus, + element_type.monomorphized_clone (), get_combined_refs ()); } @@ -1777,6 +1896,12 @@ BoolType::clone () const return new BoolType (get_ref (), get_ty_ref (), get_combined_refs ()); } +BaseType * +BoolType::monomorphized_clone () const +{ + return clone (); +} + void IntType::accept_vis (TyVisitor &vis) { @@ -1844,6 +1969,12 @@ IntType::clone () const get_combined_refs ()); } +BaseType * +IntType::monomorphized_clone () const +{ + return clone (); +} + bool IntType::is_equal (const BaseType &other) const { @@ -1921,6 +2052,12 @@ UintType::clone () const get_combined_refs ()); } +BaseType * +UintType::monomorphized_clone () const +{ + return clone (); +} + bool UintType::is_equal (const BaseType &other) const { @@ -1992,6 +2129,12 @@ FloatType::clone () const get_combined_refs ()); } +BaseType * +FloatType::monomorphized_clone () const +{ + return clone (); +} + bool FloatType::is_equal (const BaseType &other) const { @@ -2054,6 +2197,12 @@ USizeType::clone () const return new USizeType (get_ref (), get_ty_ref (), get_combined_refs ()); } +BaseType * +USizeType::monomorphized_clone () const +{ + return clone (); +} + void ISizeType::accept_vis (TyVisitor &vis) { @@ -2106,6 +2255,12 @@ ISizeType::clone () const return new ISizeType (get_ref (), get_ty_ref (), get_combined_refs ()); } +BaseType * +ISizeType::monomorphized_clone () const +{ + return clone (); +} + void CharType::accept_vis (TyVisitor &vis) { @@ -2158,6 +2313,12 @@ CharType::clone () const return new CharType (get_ref (), get_ty_ref (), get_combined_refs ()); } +BaseType * +CharType::monomorphized_clone () const +{ + return clone (); +} + void ReferenceType::accept_vis (TyVisitor &vis) { @@ -2228,6 +2389,14 @@ ReferenceType::clone () const get_combined_refs ()); } +BaseType * +ReferenceType::monomorphized_clone () const +{ + return new ReferenceType (get_ref (), get_ty_ref (), + base.monomorphized_clone (), mutability (), + get_combined_refs ()); +} + ReferenceType * ReferenceType::handle_substitions (SubstitutionArgumentMappings mappings) { @@ -2314,6 +2483,14 @@ PointerType::clone () const get_combined_refs ()); } +BaseType * +PointerType::monomorphized_clone () const +{ + return new PointerType (get_ref (), get_ty_ref (), + base.monomorphized_clone (), mutability (), + get_combined_refs ()); +} + PointerType * PointerType::handle_substitions (SubstitutionArgumentMappings mappings) { @@ -2398,6 +2575,12 @@ ParamType::clone () const param, get_specified_bounds (), get_combined_refs ()); } +BaseType * +ParamType::monomorphized_clone () const +{ + return resolve ()->clone (); +} + std::string ParamType::get_symbol () const { @@ -2479,6 +2662,12 @@ StrType::clone () const return new StrType (get_ref (), get_ty_ref (), get_combined_refs ()); } +BaseType * +StrType::monomorphized_clone () const +{ + return clone (); +} + void StrType::accept_vis (TyVisitor &vis) { @@ -2583,6 +2772,12 @@ NeverType::clone () const return new NeverType (get_ref (), get_ty_ref (), get_combined_refs ()); } +BaseType * +NeverType::monomorphized_clone () const +{ + return clone (); +} + // placeholder type void @@ -2639,6 +2834,15 @@ PlaceholderType::clone () const get_combined_refs ()); } +BaseType * +PlaceholderType::monomorphized_clone () const +{ + if (can_resolve ()) + return resolve ()->monomorphized_clone (); + + return clone (); +} + void PlaceholderType::set_associated_type (HirId ref) { @@ -2734,11 +2938,17 @@ ProjectionType::can_eq (const BaseType *other, bool emit_errors) const BaseType * ProjectionType::clone () const { - return new ProjectionType (get_ref (), get_ty_ref (), base, trait, item, - clone_substs (), used_arguments, + return new ProjectionType (get_ref (), get_ty_ref (), base->clone (), trait, + item, clone_substs (), used_arguments, get_combined_refs ()); } +BaseType * +ProjectionType::monomorphized_clone () const +{ + return get ()->monomorphized_clone (); +} + ProjectionType * ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings) { @@ -2864,6 +3074,12 @@ DynamicObjectType::clone () const specified_bounds, get_combined_refs ()); } +BaseType * +DynamicObjectType::monomorphized_clone () const +{ + return clone (); +} + std::string DynamicObjectType::get_name () const { @@ -3087,7 +3303,7 @@ TypeCheckCallExpr::visit (FnPtr &type) return; } - resolved = type.get_return_type ()->clone (); + resolved = type.get_return_type ()->monomorphized_clone (); } // method call checker @@ -3143,7 +3359,8 @@ TypeCheckMethodCallExpr::visit (FnType &type) } type.monomorphize (); - resolved = type.get_return_type ()->clone (); + + resolved = type.get_return_type ()->monomorphized_clone (); } } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index b00237c..c0e4324 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -212,6 +212,9 @@ public: * releasing the memory of the returned ty. */ virtual BaseType *clone () const = 0; + // TODO + virtual BaseType *monomorphized_clone () const = 0; + // get_combined_refs returns the chain of node refs involved in unification std::set<HirId> get_combined_refs () const { return combined; } @@ -293,6 +296,10 @@ public: BaseType *get_tyty () const; + TyVar clone () const; + + TyVar monomorphized_clone () const; + static TyVar get_implicit_infer_var (Location locus); static TyVar subst_covariant_var (TyTy::BaseType *orig, @@ -339,6 +346,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; InferTypeKind get_infer_kind () const { return infer_kind; } @@ -378,6 +386,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; std::string get_name () const override final { return as_string (); } @@ -421,6 +430,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; std::string get_symbol () const; @@ -471,6 +481,8 @@ public: StructFieldType *clone () const; + StructFieldType *monomorphized_clone () const; + bool is_concrete () const { return ty->is_concrete (); } void debug () const { rust_debug ("%s", as_string ().c_str ()); } @@ -524,6 +536,7 @@ public: BaseType *get_field (size_t index) const; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { @@ -1235,6 +1248,16 @@ public: cloned_fields); } + VariantDef *monomorphized_clone () const + { + std::vector<StructFieldType *> cloned_fields; + for (auto &f : fields) + cloned_fields.push_back ((StructFieldType *) f->monomorphized_clone ()); + + return new VariantDef (id, identifier, ident, type, discriminant, + cloned_fields); + } + const RustIdent &get_ident () const { return ident; } private: @@ -1358,6 +1381,7 @@ public: } BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool needs_generic_substitutions () const override final { @@ -1530,6 +1554,7 @@ public: BaseType *get_return_type () const { return type; } BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool needs_generic_substitutions () const override final { @@ -1595,6 +1620,7 @@ public: bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; void iterate_params (std::function<bool (BaseType *)> cb) const { @@ -1668,6 +1694,7 @@ public: bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { @@ -1735,6 +1762,7 @@ public: BaseType *get_element_type () const; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const final override { @@ -1784,6 +1812,7 @@ public: BaseType *get_element_type () const; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const final override { @@ -1826,6 +1855,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { return true; } }; @@ -1873,6 +1903,7 @@ public: IntKind get_int_kind () const { return int_kind; } BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_equal (const BaseType &other) const override; bool is_concrete () const override final { return true; } @@ -1925,6 +1956,7 @@ public: UintKind get_uint_kind () const { return uint_kind; } BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_equal (const BaseType &other) const override; bool is_concrete () const override final { return true; } @@ -1975,6 +2007,7 @@ public: FloatKind get_float_kind () const { return float_kind; } BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_equal (const BaseType &other) const override; bool is_concrete () const override final { return true; } @@ -2013,6 +2046,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { return true; } }; @@ -2046,6 +2080,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { return true; } }; @@ -2079,6 +2114,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { return true; } }; @@ -2123,6 +2159,7 @@ public: bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { @@ -2181,6 +2218,7 @@ public: bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { @@ -2232,6 +2270,7 @@ public: bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; bool is_concrete () const override final { return true; } }; @@ -2273,6 +2312,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; std::string get_name () const override final { return as_string (); } @@ -2314,6 +2354,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; std::string get_name () const override final { return as_string (); } @@ -2389,6 +2430,7 @@ public: BaseType *cast (BaseType *other) override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; std::string get_name () const override final { return as_string (); } @@ -2447,6 +2489,7 @@ public: bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; + BaseType *monomorphized_clone () const final override; std::string get_name () const override final; diff --git a/gcc/testsuite/rust/execute/torture/issue-1133.rs b/gcc/testsuite/rust/execute/torture/issue-1133.rs new file mode 100644 index 0000000..19d6690 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1133.rs @@ -0,0 +1,146 @@ +// { dg-additional-options "-w" } +extern "rust-intrinsic" { + pub fn offset<T>(dst: *const T, offset: isize) -> *const T; +} + +struct FatPtr<T> { + data: *const T, + len: usize, +} + +pub union Repr<T> { + rust: *const [T], + rust_mut: *mut [T], + raw: FatPtr<T>, +} + +pub enum Option<T> { + None, + Some(T), +} + +#[lang = "Range"] +pub struct Range<Idx> { + pub start: Idx, + pub end: Idx, +} + +#[lang = "const_slice_ptr"] +impl<T> *const [T] { + pub const fn len(self) -> usize { + let a = unsafe { Repr { rust: self }.raw }; + a.len + } + + pub const fn as_ptr(self) -> *const T { + self as *const T + } +} + +#[lang = "const_ptr"] +impl<T> *const T { + pub const unsafe fn offset(self, count: isize) -> *const T { + unsafe { offset(self, count) } + } + + pub const unsafe fn add(self, count: usize) -> Self { + unsafe { self.offset(count as isize) } + } + + pub const fn as_ptr(self) -> *const T { + self as *const T + } +} + +const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] { + unsafe { + Repr { + raw: FatPtr { data, len }, + } + .rust + } +} + +#[lang = "index"] +trait Index<Idx> { + type Output; + + fn index(&self, index: Idx) -> &Self::Output; +} + +pub unsafe trait SliceIndex<T> { + type Output; + + fn get(self, slice: &T) -> Option<&Self::Output>; + + unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output; + + fn index(self, slice: &T) -> &Self::Output; +} + +unsafe impl<T> SliceIndex<[T]> for usize { + type Output = T; + + fn get(self, slice: &[T]) -> Option<&T> { + unsafe { Option::Some(&*self.get_unchecked(slice)) } + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const T { + // SAFETY: the caller guarantees that `slice` is not dangling, so it + // cannot be longer than `isize::MAX`. They also guarantee that + // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, + // so the call to `add` is safe. + unsafe { slice.as_ptr().add(self) } + } + + fn index(self, slice: &[T]) -> &T { + // N.B., use intrinsic indexing + // &(*slice)[self] + unsafe { &*self.get_unchecked(slice) } + } +} + +unsafe impl<T> SliceIndex<[T]> for Range<usize> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&[T]> { + if self.start > self.end + /* || self.end > slice.len() */ + { + Option::None + } else { + unsafe { Option::Some(&*self.get_unchecked(slice)) } + } + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { + unsafe { + let a: *const T = slice.as_ptr(); + let b: *const T = a.add(self.start); + slice_from_raw_parts(b, self.end - self.start) + } + } + + fn index(self, slice: &[T]) -> &[T] { + unsafe { &*self.get_unchecked(slice) } + } +} + +impl<T, I> Index<I> for [T] +where + I: SliceIndex<[T]>, +{ + type Output = I::Output; + + fn index(&self, index: I) -> &I::Output { + index.index(self) + } +} + +fn main() -> i32 { + let a = [1, 2, 3, 4, 5]; + let b = &a[1..3]; + let c = b[1]; + + 0 +} |