Index: flang/include/flang/Semantics/type.h =================================================================== --- flang/include/flang/Semantics/type.h +++ flang/include/flang/Semantics/type.h @@ -288,6 +288,9 @@ bool operator==(const DerivedTypeSpec &that) const { return RawEquals(that) && parameters_ == that.parameters_; } + bool operator!=(const DerivedTypeSpec &that) const { + return !(*this == that); + } std::string AsFortran() const; private: Index: flang/lib/Semantics/runtime-type-info.cpp =================================================================== --- flang/lib/Semantics/runtime-type-info.cpp +++ flang/lib/Semantics/runtime-type-info.cpp @@ -955,9 +955,27 @@ std::uint8_t isArgDescriptorSet{0}; int argThatMightBeDescriptor{0}; MaybeExpr which; - if (isAssignment) { // only type-bound asst's are germane to runtime - CHECK(binding != nullptr); + if (isAssignment) { + // Only type-bound asst's with the same type on both dummy arguments + // are germane to the runtime, which needs only these to implement + // component assignment as part of intrinsic assignment. + // Non-type-bound generic INTERFACEs and assignments from distinct + // types must not be used for component intrinsic assignment. CHECK(proc->dummyArguments.size() == 2); + const auto t1{ + DEREF(std::get_if( + &proc->dummyArguments[0].u)) + .type.type()}; + const auto t2{ + DEREF(std::get_if( + &proc->dummyArguments[1].u)) + .type.type()}; + if (!binding || t1.category() != TypeCategory::Derived || + t2.category() != TypeCategory::Derived || + t1.IsUnlimitedPolymorphic() || t2.IsUnlimitedPolymorphic() || + t1.GetDerivedTypeSpec() != t2.GetDerivedTypeSpec()) { + return; + } which = proc->IsElemental() ? elementalAssignmentEnum_ : scalarAssignmentEnum_; if (binding && binding->passName() && Index: flang/test/Semantics/typeinfo01.f90 =================================================================== --- flang/test/Semantics/typeinfo01.f90 +++ flang/test/Semantics/typeinfo01.f90 @@ -253,3 +253,22 @@ ! CHECK: .n.n_3, SAVE, TARGET: ObjectEntity type: CHARACTER(3_8,1) init:"n_3" end type end module + +module m13 + type :: t1 + integer :: n + contains + procedure :: assign1, assign2 + generic :: assignment(=) => assign1, assign2 + ! CHECK: .s.t1, SAVE, TARGET: ObjectEntity type: TYPE(specialbinding) shape: 0_8:0_8 init:[specialbinding::specialbinding(which=2_1,isargdescriptorset=3_1,proc=assign1)] + end type + contains + impure elemental subroutine assign1(to, from) + class(t1), intent(out) :: to + class(t1), intent(in) :: from + end subroutine + impure elemental subroutine assign2(to, from) + class(t1), intent(out) :: to + integer, intent(in) :: from + end subroutine +end module