diff --git a/src/codegen.cpp b/src/codegen.cpp index be9aaf075858f..1fc71a923f1a2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2500,8 +2500,16 @@ static Value *emit_bits_compare(jl_codectx_t &ctx, jl_cgval_t arg1, jl_cgval_t a Value *nullcheck2 = nullptr; auto fld1 = emit_getfield_knownidx(ctx, arg1, i, sty, &nullcheck1); auto fld2 = emit_getfield_knownidx(ctx, arg2, i, sty, &nullcheck2); - answer = ctx.builder.CreateAnd(answer, emit_f_is(ctx, fld1, fld2, - nullcheck1, nullcheck2)); + Value *fld_answer; + if (jl_field_isptr(sty, i) && jl_is_concrete_immutable(fldty)) { + // concrete immutables that are !isinlinealloc might be reference cycles + // issue #37872 + fld_answer = emit_box_compare(ctx, fld1, fld2, nullcheck1, nullcheck2); + } + else { + fld_answer = emit_f_is(ctx, fld1, fld2, nullcheck1, nullcheck2); + } + answer = ctx.builder.CreateAnd(answer, fld_answer); } return answer; } diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 5f131f3e80e48..2ccffc40b2f16 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -495,3 +495,8 @@ let x = reinterpret(Has256Bits, [0xfcdac822cac89d82de4f9b3326da8294, 0x6ebac4d59 @test reinterpret(UInt128, [h(x)]) == lshifted @test reinterpret(UInt128, [Base.shl_int(x, 0x8)]) == lshifted end + +# issue #37872 +let f(@nospecialize(x)) = x===Base.ImmutableDict(Int128=>:big) + @test !f(Dict(Int=>Int)) +end