Code review comment: > If the type is `string | never`, we will create a union type by including only the `string` type as a member. If the type is `never | never`, we will add the never type as a member. Why do we treat these two scenarios differently?  As per the spec, we can consider `string|never` as `string`, but it is incorrect to consider  `never|never` as no type.

Code under review:
public static BUnionType create(BTypeSymbol tsymbol, LinkedHashSet<BType> types) {
        LinkedHashSet<BType> memberTypes = new LinkedHashSet<>(types.size());

        boolean isImmutable = true;
        boolean hasNilableType = false;

        if (types.isEmpty()) {
            return new BUnionType(tsymbol, memberTypes, hasNilableType, isImmutable);
        }

        boolean foundNotNeverType = false;
        for (BType memBType : toFlatTypeSet(types)) {
            if (getReferredType(memBType).tag != TypeTags.NEVER) {
                foundNotNeverType = true;
                memberTypes.add(memBType);
            }

            if (isImmutable && !Symbols.isFlagOn(memBType.flags, Flags.READONLY)) {
                isImmutable = false;
            }
        }

        if (!foundNotNeverType) {
            memberTypes.addAll(types);
        }

        for (BType memberType : memberTypes) {
            if (memberType.isNullable() && memberType.tag != TypeTags.NIL) {
                hasNilableType = true;
                break;
            }
        }

        if (hasNilableType) {
            LinkedHashSet<BType> bTypes = new LinkedHashSet<>(memberTypes.size());
            for (BType t : memberTypes) {
                if (t.tag != TypeTags.NIL) {
                    bTypes.add(t);
                }
            }
            memberTypes = bTypes;
        }

        for (BType memberType : memberTypes) {
            if (memberType.isNullable()) {
                return new BUnionType(tsymbol, types, memberTypes, true, isImmutable);
            }
        }

        return new BUnionType(tsymbol, types, memberTypes, false, isImmutable);
    }

Line commented on: if (!foundNotNeverType) {

Revised code:
public static BUnionType create(BTypeSymbol tsymbol, LinkedHashSet<BType> types) {
        LinkedHashSet<BType> memberTypes = new LinkedHashSet<>(types.size());

        if (types.isEmpty()) {
            return new BUnionType(tsymbol, memberTypes, false, true);
        }

        boolean isImmutable = true;
        for (BType memBType : toFlatTypeSet(types)) {
            if (!isNeverType(memBType)) {
                memberTypes.add(memBType);
            }

            if (isImmutable && !Symbols.isFlagOn(memBType.flags, Flags.READONLY)) {
                isImmutable = false;
            }
        }
        if (memberTypes.isEmpty()) {
            memberTypes.add(new BNeverType());
            return new BUnionType(tsymbol, memberTypes, false, isImmutable);
        }

        boolean hasNilableType = false;
        for (BType memberType : memberTypes) {
            if (memberType.isNullable() && memberType.tag != TypeTags.NIL) {
                hasNilableType = true;
                break;
            }
        }

        if (hasNilableType) {
            LinkedHashSet<BType> bTypes = new LinkedHashSet<>(memberTypes.size());
            for (BType t : memberTypes) {
                if (t.tag != TypeTags.NIL) {
                    bTypes.add(t);
                }
            }
            memberTypes = bTypes;
        }

        for (BType memberType : memberTypes) {
            if (memberType.isNullable()) {
                return new BUnionType(tsymbol, types, memberTypes, true, isImmutable);
            }
        }

        return new BUnionType(tsymbol, types, memberTypes, false, isImmutable);
    }