Repository: apple/swift
File: lib/Sema/TypeCheckType.cpp (C++)

Code before:
    // be an unbound generic.
    if (options.is(TypeResolverContext::TypeAliasDecl)) {
      if (parentTy->is<UnboundGenericType>()) {
        if (!options.contains(TypeResolutionFlags::SilenceErrors))
          diagnoseUnboundGenericType(parentTy, parentRange.End);

        return ErrorType::get(ctx);
      }
    }

    // Diagnose a bad conformance reference if we need to.
    if (!options.contains(TypeResolutionFlags::SilenceErrors) &&
        inferredAssocType && memberType->hasError()) {
      maybeDiagnoseBadConformanceRef(DC, parentTy, repr->getLoc(),
                                     inferredAssocType);
    }

    // If there are generic arguments, apply them now.
    return applyGenericArguments(memberType, resolution, silContext, repr);
  };

  // Short-circuiting.
  if (repr->isInvalid()) return ErrorType::get(ctx);
  // Reject explicit syntax like `(some P).T`, but allow member type lookup on
  // opaque archetypes introduced by generic requirements.
  if (repr->getBase()->hasOpaque()) {
    if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
      diags.diagnose(repr->getNameLoc(),
                     diag::opaque_type_member_type,
                     repr->getNameRef(), parentTy)
          .highlight(parentRange);
    }
    return ErrorType::get(ctx);
  }

  // If the parent is a type parameter, the member is a dependent member,
  // and we skip much of the work below.
  if (parentTy->isTypeParameter()) {
    if (auto memberType = resolution.resolveDependentMemberType(
            parentTy, DC, parentRange, repr)) {
      // Hack -- if we haven't resolved this to a declaration yet, don't
      // attempt to apply generic arguments, since this will emit a
      // diagnostic, and its possible that this type will become a concrete
      // type later on.
      if (!memberType->is<DependentMemberType>() ||
          memberType->castTo<DependentMemberType>()->getAssocType()) {
        return applyGenericArguments(memberType, resolution, silContext, repr);
      }

      return memberType;
    }

Review comment (suggestion):
Should this be `isa<NamedOpaqueReturnTypeRepr>` instead? I'm assuming that at some point `S<some P>` is going to be allowed and this check shouldn't diagnose the problem here.

Code after:
    // be an unbound generic.
    if (options.is(TypeResolverContext::TypeAliasDecl)) {
      if (parentTy->is<UnboundGenericType>()) {
        if (!options.contains(TypeResolutionFlags::SilenceErrors))
          diagnoseUnboundGenericType(parentTy, parentRange.End);

        return ErrorType::get(ctx);
      }
    }

    // Diagnose a bad conformance reference if we need to.
    if (!options.contains(TypeResolutionFlags::SilenceErrors) &&
        inferredAssocType && memberType->hasError()) {
      maybeDiagnoseBadConformanceRef(DC, parentTy, repr->getLoc(),
                                     inferredAssocType);
    }

    // If there are generic arguments, apply them now.
    return applyGenericArguments(memberType, resolution, silContext, repr);
  };

  // Short-circuiting.
  if (repr->isInvalid()) return ErrorType::get(ctx);
  // Reject member type access only when the base is explicitly written as an
  // opaque type, e.g. `(some P).T`.
  auto *baseRepr = repr->getBase()->getWithoutParens();
  if (isa<OpaqueReturnTypeRepr>(baseRepr) ||
      isa<NamedOpaqueReturnTypeRepr>(baseRepr)) {
    if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
      diags.diagnose(repr->getNameLoc(),
                     diag::opaque_type_member_type,
                     repr->getNameRef(), parentTy)
          .highlight(parentRange);
    }
    return ErrorType::get(ctx);
  }

  // If the parent is a type parameter, the member is a dependent member,
  // and we skip much of the work below.
  if (parentTy->isTypeParameter()) {
    if (auto memberType = resolution.resolveDependentMemberType(
            parentTy, DC, parentRange, repr)) {
      // Hack -- if we haven't resolved this to a declaration yet, don't
      // attempt to apply generic arguments, since this will emit a
      // diagnostic, and its possible that this type will become a concrete
      // type later on.
      if (!memberType->is<DependentMemberType>() ||
          memberType->castTo<DependentMemberType>()->getAssocType()) {
        return applyGenericArguments(memberType, resolution, silContext, repr);
      }