当前位置: 首页>>代码示例>>C++>>正文


C++ TypeChecker类代码示例

本文整理汇总了C++中TypeChecker的典型用法代码示例。如果您正苦于以下问题:C++ TypeChecker类的具体用法?C++ TypeChecker怎么用?C++ TypeChecker使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。


在下文中一共展示了TypeChecker类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: computeSelfTypeRelationship

/// Determine the relationship between the self types of the given declaration
/// contexts..
static SelfTypeRelationship computeSelfTypeRelationship(TypeChecker &tc,
                                                        DeclContext *dc,
                                                        DeclContext *dc1,
                                                        DeclContext *dc2){
  // If at least one of the contexts is a non-type context, the two are
  // unrelated.
  if (!dc1->isTypeContext() || !dc2->isTypeContext())
    return SelfTypeRelationship::Unrelated;

  Type type1 = dc1->getDeclaredInterfaceType();
  Type type2 = dc2->getDeclaredInterfaceType();

  // If the types are equal, the answer is simple.
  if (type1->isEqual(type2))
    return SelfTypeRelationship::Equivalent;

  // If both types can have superclasses, which whether one is a superclass
  // of the other. The subclass is the common base type.
  if (type1->mayHaveSuperclass() && type2->mayHaveSuperclass()) {
    if (isNominallySuperclassOf(tc, type1, type2))
      return SelfTypeRelationship::Superclass;

    if (isNominallySuperclassOf(tc, type2, type1))
      return SelfTypeRelationship::Subclass;

    return SelfTypeRelationship::Unrelated;
  }

  // If neither or both are protocol types, consider the bases unrelated.
  bool isProtocol1 = isa<ProtocolDecl>(dc1);
  bool isProtocol2 = isa<ProtocolDecl>(dc2);
  if (isProtocol1 == isProtocol2)
    return SelfTypeRelationship::Unrelated;

  // Just one of the two is a protocol. Check whether the other conforms to
  // that protocol.
  Type protoTy = isProtocol1? type1 : type2;
  Type modelTy = isProtocol1? type2 : type1;
  auto proto = protoTy->castTo<ProtocolType>()->getDecl();

  // If the model type does not conform to the protocol, the bases are
  // unrelated.
  if (!tc.conformsToProtocol(modelTy, proto, dc,
                             ConformanceCheckFlags::InExpression))
    return SelfTypeRelationship::Unrelated;

  return isProtocol1? SelfTypeRelationship::ConformedToBy
                    : SelfTypeRelationship::ConformsTo;
}
开发者ID:pk-codebox-evo,项目名称:swift,代码行数:51,代码来源:CSRanking.cpp

示例2: typeCheck

void ArraySetElementAST::typeCheck(TypeChecker& checker) {
	mArrayRefExpression->typeCheck(checker);
	mAccessExpression->typeCheck(checker);
	mRightHandSide->typeCheck(checker);

	//Check if array
	auto arrayRefType = std::dynamic_pointer_cast<ArrayType>(mArrayRefExpression->expressionType(checker));

	if (arrayRefType == nullptr) {
		checker.typeError("The expression '" + mArrayRefExpression->asString() + "' is not of array type.");
	}

	//Access access
	checker.assertSameType(
		*checker.makeType("Int"),
		*mAccessExpression->expressionType(checker),
		"Expected the array indexing to be of type 'Int'.");

	//Check rhs
	checker.assertSameType(
		*arrayRefType->elementType(), 
		*mRightHandSide->expressionType(checker),
		asString());
}
开发者ID:svenslaggare,项目名称:StackLang,代码行数:24,代码来源:arrayast.cpp

示例3: getTypeOfCompletionContextExpr

static Optional<Type> getTypeOfCompletionContextExpr(
                        TypeChecker &TC,
                        DeclContext *DC,
                        CompletionTypeCheckKind kind,
                        Expr *&parsedExpr,
                        ConcreteDeclRef &referencedDecl) {
  switch (kind) {
  case CompletionTypeCheckKind::Normal:
    // Handle below.
    break;

  case CompletionTypeCheckKind::ObjCKeyPath:
    referencedDecl = nullptr;
    if (auto keyPath = dyn_cast<ObjCKeyPathExpr>(parsedExpr))
      return TC.checkObjCKeyPathExpr(DC, keyPath, /*requireResultType=*/true);

    return None;
  }

  Type originalType = parsedExpr->getType();
  if (auto T = TC.getTypeOfExpressionWithoutApplying(parsedExpr, DC,
                 referencedDecl, FreeTypeVariableBinding::GenericParameters))
    return T;

  // Try to recover if we've made any progress.
  if (parsedExpr &&
      !isa<ErrorExpr>(parsedExpr) &&
      parsedExpr->getType() &&
      !parsedExpr->getType()->hasError() &&
      (originalType.isNull() ||
       !parsedExpr->getType()->isEqual(originalType))) {
    return parsedExpr->getType();
  }

  return None;
}
开发者ID:KoKumagai,项目名称:swift,代码行数:36,代码来源:TypeChecker.cpp

示例4: Infer

ValuePtr BSequence::Infer(TypeChecker& checker, const vector<ExprPtr>& args)
{
  for(auto& e : args)
  {
    TypeSubst lastSubst;
    checker.subst.swap(lastSubst);

    checker.Visit(e.get());
    if(!e->value)
      return {};

    Compose(lastSubst, checker.subst);
  }

  return args.back()->value;
}
开发者ID:boardwalk,项目名称:xra,代码行数:16,代码来源:builtins.cpp

示例5: getInfixData

/// getInfixData - If the specified expression is an infix binary
/// operator, return its infix operator attributes.
static InfixData getInfixData(TypeChecker &TC, DeclContext *DC, Expr *E) {
  if (auto *ifExpr = dyn_cast<IfExpr>(E)) {
    // Ternary has fixed precedence.
    assert(!ifExpr->isFolded() && "already folded if expr in sequence?!");
    (void)ifExpr;
    return InfixData(IntrinsicPrecedences::IfExpr,
                     Associativity::Right,
                     /*assignment*/ false);

  } else if (auto *assign = dyn_cast<AssignExpr>(E)) {
    // Assignment has fixed precedence.
    assert(!assign->isFolded() && "already folded assign expr in sequence?!");
    (void)assign;
    return InfixData(IntrinsicPrecedences::AssignExpr,
                     Associativity::Right,
                     /*assignment*/ true);

  } else if (auto *as = dyn_cast<ExplicitCastExpr>(E)) {
    // 'as' and 'is' casts have fixed precedence.
    assert(!as->isFolded() && "already folded 'as' expr in sequence?!");
    (void)as;
    return InfixData(IntrinsicPrecedences::ExplicitCastExpr,
                     Associativity::None,
                     /*assignment*/ false);

  } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
    SourceFile *SF = DC->getParentSourceFile();
    Identifier name = DRE->getDecl()->getName();
    bool isCascading = DC->isCascadingContextForLookup(true);
    if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
                                                        E->getLoc()))
      return op->getInfixData();

  } else if (OverloadedDeclRefExpr *OO = dyn_cast<OverloadedDeclRefExpr>(E)) {
    SourceFile *SF = DC->getParentSourceFile();
    Identifier name = OO->getDecls()[0]->getName();
    bool isCascading = DC->isCascadingContextForLookup(true);
    if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
                                                        E->getLoc()))
      return op->getInfixData();
  }
  
  TC.diagnose(E->getLoc(), diag::unknown_binop);
  // Recover with an infinite-precedence left-associative operator.
  return InfixData((unsigned char)~0U, Associativity::Left,
                   /*assignment*/ false);
}
开发者ID:AaronPelzer,项目名称:swift,代码行数:49,代码来源:TypeCheckExpr.cpp

示例6: checkGenericParamList

/// Check the generic parameters in the given generic parameter list (and its
/// parent generic parameter lists) according to the given resolver.
void checkGenericParamList(TypeChecker &tc,
                           GenericSignatureBuilder *builder,
                           GenericParamList *genericParams,
                           GenericSignature *parentSig,
                           TypeResolution resolution) {
  // If there is a parent context, add the generic parameters and requirements
  // from that context.
  if (builder)
    builder->addGenericSignature(parentSig);

  // If there aren't any generic parameters at this level, we're done.
  if (!genericParams)
    return;

  assert(genericParams->size() > 0 &&
         "Parsed an empty generic parameter list?");

  // Determine where and how to perform name lookup.
  TypeResolutionOptions options = None;
  DeclContext *lookupDC = genericParams->begin()[0]->getDeclContext();
  assert(lookupDC == resolution.getDeclContext());

  // First, add the generic parameters to the generic signature builder.
  // Do this before checking the inheritance clause, since it may
  // itself be dependent on one of these parameters.
  if (builder) {
    for (auto param : *genericParams)
      builder->addGenericParameter(param);
  }

  // Add the requirements for each of the generic parameters to the builder.
  // Now, check the inheritance clauses of each parameter.
  if (builder) {
    for (auto param : *genericParams)
      builder->addGenericParameterRequirements(param);
  }


  // Add the requirements clause to the builder, validating the types in
  // the requirements clause along the way.
  tc.validateRequirements(genericParams->getWhereLoc(),
                          genericParams->getRequirements(), resolution,
                          options, builder);
}
开发者ID:frsoares,项目名称:swift,代码行数:46,代码来源:TypeCheckGeneric.cpp

示例7: getResultType

static Type getResultType(TypeChecker &TC, FuncDecl *fn, Type resultType) {
  // Look through optional types.
  OptionalTypeKind optKind;
  if (auto origValueType = resultType->getAnyOptionalObjectType(optKind)) {
    // Get the interface type of the result.
    Type ifaceValueType = getResultType(TC, fn, origValueType);

    // Preserve the optional type's original spelling if the interface
    // type is the same as the original.
    if (origValueType.getPointer() == ifaceValueType.getPointer()) {
      return resultType;
    }

    // Wrap the interface type in the right kind of optional.
    switch (optKind) {
    case OTK_None: llvm_unreachable("impossible");
    case OTK_Optional:
      return OptionalType::get(ifaceValueType);
    case OTK_ImplicitlyUnwrappedOptional:
      return ImplicitlyUnwrappedOptionalType::get(ifaceValueType);
    }
    llvm_unreachable("bad optional kind");
  }

  // Rewrite dynamic self to the appropriate interface type.
  if (resultType->is<DynamicSelfType>()) {
    return fn->getDynamicSelfInterface();
  }

  // Weird hacky special case.
  if (!fn->getBodyResultTypeLoc().hasLocation() &&
      fn->isGenericContext()) {
    // FIXME: This should not be rewritten.  This is only needed in cases where
    // we synthesize a function which returns a generic value.  In that case,
    // the return type is specified in terms of archetypes, but has no TypeLoc
    // in the TypeRepr.  Because of this, Sema isn't able to rebuild it in
    // terms of interface types.  When interface types prevail, this should be
    // removed.  Until then, we hack the mapping here.
    return TC.getInterfaceTypeFromInternalType(fn, resultType);
  }

  return resultType;
}
开发者ID:peteriou18,项目名称:swift,代码行数:43,代码来源:TypeCheckGeneric.cpp

示例8: typeConformsToCodable

/// Returns whether the given type conforms to the given {En,De}codable
/// protocol.
///
/// \param tc The typechecker to use in validating {En,De}codable conformance.
///
/// \param context The \c DeclContext the var declarations belong to.
///
/// \param target The \c Type to validate.
///
/// \param proto The \c ProtocolDecl to check conformance to.
static CodableConformanceType typeConformsToCodable(TypeChecker &tc,
                                                    DeclContext *context,
                                                    Type target,
                                                    ProtocolDecl *proto) {
  // Some generic types need to be introspected to get at their "true" Codable
  // conformance.
  auto canType = target->getCanonicalType();
  if (auto genericType = dyn_cast<BoundGenericType>(canType)) {
    auto *nominalTypeDecl = genericType->getAnyNominal();

    // Implicitly unwrapped optionals need to be unwrapped;
    // ImplicitlyUnwrappedOptional does not need to conform to Codable directly
    // -- only its inner type does.
    if (nominalTypeDecl == tc.Context.getImplicitlyUnwrappedOptionalDecl() ||
         // FIXME: Remove the following when conditional conformance lands.
         // Some generic types in the stdlib currently conform to Codable even
         // when the type they are generic on does not [Optional, Array, Set,
         // Dictionary].  For synthesizing conformance, we don't want to
         // consider these types as Codable if the nested type is not Codable.
         // Look through the generic type parameters of these types recursively
         // to avoid synthesizing code that will crash at runtime.
         //
         // We only want to look through generic params for these types; other
         // types may validly conform to Codable even if their generic param
         // types do not.
         nominalTypeDecl == tc.Context.getOptionalDecl() ||
         nominalTypeDecl == tc.Context.getArrayDecl() ||
         nominalTypeDecl == tc.Context.getSetDecl() ||
         nominalTypeDecl == tc.Context.getDictionaryDecl()) {
      for (auto paramType : genericType->getGenericArgs()) {
        if (typeConformsToCodable(tc, context, paramType, proto) != Conforms)
          return DoesNotConform;
      }

      return Conforms;
    }
  }

  return tc.conformsToProtocol(target, proto, context,
                               ConformanceCheckFlags::Used) ? Conforms
                                                            : DoesNotConform;
}
开发者ID:Jnosh,项目名称:swift,代码行数:52,代码来源:DerivedConformanceCodable.cpp

示例9: typeCheck

void SetFieldValueAST::typeCheck(TypeChecker& checker) {
	mObjectRefExpression->typeCheck(checker);

	std::shared_ptr<Type> objRefType;

	if (auto varRef = std::dynamic_pointer_cast<VariableReferenceExpressionAST>(mObjectRefExpression)) {
		auto varSymbol = std::dynamic_pointer_cast<VariableSymbol>(mSymbolTable->find(varRef->name()));
		objRefType = checker.findType(varSymbol->variableType());
	} else if (auto arrayRef = std::dynamic_pointer_cast<ArrayAccessAST>(mObjectRefExpression)) {
		objRefType = arrayRef->expressionType(checker);
	} else {
		checker.typeError("Not implemented");
	}

	auto memberName = getMemberName();
	std::string objName = objRefType->name();

	if (!checker.objectExists(objName)) {
		checker.typeError(objRefType->name() + " is not an object type.");
	}

	auto& object = checker.getObject(objName);

	if (!object.fieldExists(memberName)) {
		checker.typeError("There exists no field '" + memberName + "' in the type '" + objRefType->name() + "'.");
	}

	mRightHandSide->typeCheck(checker);

	//Check rhs
	std::shared_ptr<Type> fieldType;

	if (std::dynamic_pointer_cast<ArrayAccessAST>(mMemberExpression)) {
		fieldType = std::dynamic_pointer_cast<ArrayType>(object.getField(memberName).type())->elementType();
	} else {
		fieldType = object.getField(memberName).type();
	}

	checker.assertSameType(
		*fieldType,
		*mRightHandSide->expressionType(checker),
		asString());
}
开发者ID:svenslaggare,项目名称:StackLang,代码行数:43,代码来源:objectast.cpp

示例10: typeConformsToCodable

/// Returns whether the given type conforms to the given {En,De}codable
/// protocol.
///
/// \param tc The typechecker to use in validating {En,De}codable conformance.
///
/// \param context The \c DeclContext the var declarations belong to.
///
/// \param target The \c Type to validate.
///
/// \param proto The \c ProtocolDecl to check conformance to.
static CodableConformanceType typeConformsToCodable(TypeChecker &tc,
                                                    DeclContext *context,
                                                    Type target, bool isIUO,
                                                    ProtocolDecl *proto) {
  target = context->mapTypeIntoContext(target->mapTypeOutOfContext());
  // Some generic types need to be introspected to get at their "true" Codable
  // conformance.
  if (auto referenceType = target->getAs<ReferenceStorageType>()) {
    // This is a weak/unowned/unmanaged var. Get the inner type before checking
    // conformance.
    target = referenceType->getReferentType();
  }

  if (isIUO)
    return typeConformsToCodable(tc, context, target->getOptionalObjectType(),
                                 false, proto);

  return tc.conformsToProtocol(target, proto, context,
                               ConformanceCheckFlags::Used) ? Conforms
                                                            : DoesNotConform;
}
开发者ID:DevAndArtist,项目名称:swift,代码行数:31,代码来源:DerivedConformanceCodable.cpp

示例11: deriveRawRepresentable

Type DerivedConformance::deriveRawRepresentable(TypeChecker &tc,
                                                Decl *parentDecl,
                                                NominalTypeDecl *type,
                                                AssociatedTypeDecl *assocType) {

  // We can only synthesize RawRepresentable for enums.
  auto enumDecl = dyn_cast<EnumDecl>(type);
  if (!enumDecl)
    return nullptr;

  // Check other preconditions for synthesized conformance.
  if (!canSynthesizeRawRepresentable(tc, parentDecl, enumDecl))
    return nullptr;

  if (assocType->getName() == tc.Context.Id_RawValue) {
    return deriveRawRepresentable_Raw(tc, parentDecl, enumDecl);
  }
  
  tc.diagnose(assocType->getLoc(),
              diag::broken_raw_representable_requirement);
  return nullptr;
}
开发者ID:yasirmcs,项目名称:swift,代码行数:22,代码来源:DerivedConformanceRawRepresentable.cpp

示例12: checkProtocolSelfRequirements

// For a generic requirement in a protocol, make sure that the requirement
// set didn't add any requirements to Self or its associated types.
static bool checkProtocolSelfRequirements(GenericSignature *sig,
                                          ValueDecl *decl,
                                          TypeChecker &TC) {
  // For a generic requirement in a protocol, make sure that the requirement
  // set didn't add any requirements to Self or its associated types.
  if (auto *proto = dyn_cast<ProtocolDecl>(decl->getDeclContext())) {
    auto protoSelf = proto->getSelfInterfaceType();
    for (auto req : sig->getRequirements()) {
      // If one of the types in the requirement is dependent on a non-Self
      // type parameter, this requirement is okay.
      if (!isSelfDerivedOrConcrete(protoSelf, req.getFirstType()) ||
          !isSelfDerivedOrConcrete(protoSelf, req.getSecondType()))
        continue;

      // The conformance of 'Self' to the protocol is okay.
      if (req.getKind() == RequirementKind::Conformance &&
          req.getSecondType()->getAs<ProtocolType>()->getDecl() == proto &&
          req.getFirstType()->is<GenericTypeParamType>())
        continue;

      TC.diagnose(decl,
                  TC.Context.LangOpts.EffectiveLanguageVersion[0] >= 4
                    ? diag::requirement_restricts_self
                    : diag::requirement_restricts_self_swift3,
                  decl->getDescriptiveKind(), decl->getFullName(),
                  req.getFirstType().getString(),
                  static_cast<unsigned>(req.getKind()),
                  req.getSecondType().getString());

      if (TC.Context.LangOpts.EffectiveLanguageVersion[0] >= 4)
        return true;
    }
  }

  return false;
}
开发者ID:hulsizer,项目名称:swift,代码行数:38,代码来源:TypeCheckGeneric.cpp

示例13: checkReferencedGenericParams

/// All generic parameters of a generic function must be referenced in the
/// declaration's type, otherwise we have no way to infer them.
static void checkReferencedGenericParams(GenericContext *dc,
                                         GenericSignature *sig,
                                         TypeChecker &TC) {
  auto *genericParams = dc->getGenericParams();
  if (!genericParams)
    return;

  auto *decl = cast<ValueDecl>(dc->getInnermostDeclarationDeclContext());

  // A helper class to collect referenced generic type parameters
  // and dependent member types.
  class ReferencedGenericTypeWalker : public TypeWalker {
    SmallPtrSet<CanType, 4> ReferencedGenericParams;

  public:
    ReferencedGenericTypeWalker() {}
    Action walkToTypePre(Type ty) override {
      // Find generic parameters or dependent member types.
      // Once such a type is found, don't recurse into its children.
      if (!ty->hasTypeParameter())
        return Action::SkipChildren;
      if (ty->isTypeParameter()) {
        ReferencedGenericParams.insert(ty->getCanonicalType());
        return Action::SkipChildren;
      }
      return Action::Continue;
    }

    SmallPtrSet<CanType, 4> &getReferencedGenericParams() {
      return ReferencedGenericParams;
    }
  };

  // Collect all generic params referenced in parameter types and
  // return type.
  ReferencedGenericTypeWalker paramsAndResultWalker;
  auto *funcTy = decl->getInterfaceType()->castTo<GenericFunctionType>();
  funcTy->getInput().walk(paramsAndResultWalker);
  funcTy->getResult().walk(paramsAndResultWalker);

  // Set of generic params referenced in parameter types,
  // return type or requirements.
  auto &referencedGenericParams =
      paramsAndResultWalker.getReferencedGenericParams();

  // Check if at least one of the generic params in the requirement refers
  // to an already referenced generic parameter. If this is the case,
  // then the other type is also considered as referenced, because
  // it is used to put requirements on the first type.
  auto reqTypesVisitor = [&referencedGenericParams](Requirement req) -> bool {
    Type first;
    Type second;

    switch (req.getKind()) {
    case RequirementKind::Superclass:
    case RequirementKind::SameType:
      second = req.getSecondType();
      LLVM_FALLTHROUGH;

    case RequirementKind::Conformance:
    case RequirementKind::Layout:
      first = req.getFirstType();
      break;
    }

    // Collect generic parameter types referenced by types used in a requirement.
    ReferencedGenericTypeWalker walker;
    if (first && first->hasTypeParameter())
      first.walk(walker);
    if (second && second->hasTypeParameter())
      second.walk(walker);
    auto &genericParamsUsedByRequirementTypes =
        walker.getReferencedGenericParams();

    // If at least one of the collected generic types or a root generic
    // parameter of dependent member types is known to be referenced by
    // parameter types, return types or other types known to be "referenced",
    // then all the types used in the requirement are considered to be
    // referenced, because they are used to defined something that is known
    // to be referenced.
    bool foundNewReferencedGenericParam = false;
    if (std::any_of(genericParamsUsedByRequirementTypes.begin(),
                    genericParamsUsedByRequirementTypes.end(),
                    [&referencedGenericParams](CanType t) {
                      assert(t->isTypeParameter());
                      return referencedGenericParams.find(
                                 t->getRootGenericParam()
                                     ->getCanonicalType()) !=
                             referencedGenericParams.end();
                    })) {
      std::for_each(genericParamsUsedByRequirementTypes.begin(),
                    genericParamsUsedByRequirementTypes.end(),
                    [&referencedGenericParams,
                     &foundNewReferencedGenericParam](CanType t) {
                      // Add only generic type parameters, but ignore any
                      // dependent member types, because requirement
                      // on a dependent member type does not provide enough
                      // information to infer the base generic type
//.........这里部分代码省略.........
开发者ID:hulsizer,项目名称:swift,代码行数:101,代码来源:TypeCheckGeneric.cpp

示例14: bindExtensionDecl

static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) {
  if (ED->getExtendedType())
    return;

  // If we didn't parse a type, fill in an error type and bail out.
  if (!ED->getExtendedTypeLoc().getTypeRepr()) {
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }

  auto dc = ED->getDeclContext();

  // Validate the representation.
  // FIXME: Perform some kind of "shallow" validation here?
  TypeResolutionOptions options;
  options |= TR_AllowUnboundGenerics;
  options |= TR_ExtensionBinding;
  if (TC.validateType(ED->getExtendedTypeLoc(), dc, options)) {
    ED->setInvalid();
    return;
  }

  // Dig out the extended type.
  auto extendedType = ED->getExtendedType();

  // Hack to allow extending a generic typealias.
  if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
    if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
      auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
      if (extendedNominal) {
        extendedType = extendedNominal->getDeclaredType();
        ED->getExtendedTypeLoc().setType(extendedType);
      }
    }
  }

  // Handle easy cases.

  // Cannot extend a metatype.
  if (extendedType->is<AnyMetatypeType>()) {
    TC.diagnose(ED->getLoc(), diag::extension_metatype, extendedType)
      .highlight(ED->getExtendedTypeLoc().getSourceRange());
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }

  // Cannot extend a bound generic type.
  if (extendedType->isSpecialized()) {
    TC.diagnose(ED->getLoc(), diag::extension_specialization,
                extendedType->getAnyNominal()->getName())
      .highlight(ED->getExtendedTypeLoc().getSourceRange());
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }

  // Dig out the nominal type being extended.
  NominalTypeDecl *extendedNominal = extendedType->getAnyNominal();
  if (!extendedNominal) {
    TC.diagnose(ED->getLoc(), diag::non_nominal_extension, extendedType)
      .highlight(ED->getExtendedTypeLoc().getSourceRange());
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }
  assert(extendedNominal && "Should have the nominal type being extended");

  // If the extended type is generic or is a protocol. Clone or create
  // the generic parameters.
  if (extendedNominal->isGenericContext()) {
    if (auto proto = dyn_cast<ProtocolDecl>(extendedNominal)) {
      // For a protocol extension, build the generic parameter list.
      ED->setGenericParams(proto->createGenericParams(ED));
    } else {
      // Clone the existing generic parameter list.
      ED->setGenericParams(
        cloneGenericParams(TC.Context, ED,
                           extendedNominal->getGenericParamsOfContext()));
    }
  }

  // If we have a trailing where clause, deal with it now.
  // For now, trailing where clauses are only permitted on protocol extensions.
  if (auto trailingWhereClause = ED->getTrailingWhereClause()) {
    if (!extendedNominal->isGenericContext()) {
      // Only generic and protocol types are permitted to have
      // trailing where clauses.
      TC.diagnose(ED, diag::extension_nongeneric_trailing_where, extendedType)
        .highlight(trailingWhereClause->getSourceRange());
      ED->setTrailingWhereClause(nullptr);
    } else {
      // Merge the trailing where clause into the generic parameter list.
      // FIXME: Long-term, we'd like clients to deal with the trailing where
      // clause explicitly, but for now it's far more direct to represent
      // the trailing where clause as part of the requirements.
      ED->getGenericParams()->addTrailingWhereClause(
        TC.Context,
        trailingWhereClause->getWhereLoc(),
//.........这里部分代码省略.........
开发者ID:KoKumagai,项目名称:swift,代码行数:101,代码来源:TypeChecker.cpp

示例15: validateCodingKeysEnum

/// Validates the given CodingKeys enum decl by ensuring its cases are a 1-to-1
/// match with the stored vars of the given type.
///
/// \param tc The typechecker to use in validating {En,De}codable conformance.
///
/// \param codingKeysDecl The \c CodingKeys enum decl to validate.
///
/// \param target The nominal type decl to validate the \c CodingKeys against.
///
/// \param proto The {En,De}codable protocol to validate all the keys conform
/// to.
static bool
validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
                       NominalTypeDecl *target, ProtocolDecl *proto) {
  // Look through all var decls in the given type.
  // * Filter out lazy/computed vars (currently already done by
  //   getStoredProperties).
  // * Filter out ones which are present in the given decl (by name).
  //
  // If any of the entries in the CodingKeys decl are not present in the type
  // by name, then this decl doesn't match.
  // If there are any vars left in the type which don't have a default value
  // (for Decodable), then this decl doesn't match.

  // Here we'll hold on to properties by name -- when we've validated a property
  // against its CodingKey entry, it will get removed.
  llvm::SmallDenseMap<Identifier, VarDecl *, 8> properties;
  for (auto *varDecl : target->getStoredProperties(/*skipInaccessible=*/true)) {
    properties[varDecl->getName()] = varDecl;
  }

  bool propertiesAreValid = true;
  for (auto elt : codingKeysDecl->getAllElements()) {
    auto it = properties.find(elt->getName());
    if (it == properties.end()) {
      tc.diagnose(elt->getLoc(), diag::codable_extraneous_codingkey_case_here,
                  elt->getName());
      // TODO: Investigate typo-correction here; perhaps the case name was
      //       misspelled and we can provide a fix-it.
      propertiesAreValid = false;
      continue;
    }

    // We have a property to map to. Ensure it's {En,De}codable.
    auto conformance = varConformsToCodable(tc, target->getDeclContext(),
                                            it->second, proto);
    switch (conformance) {
      case Conforms:
        // The property was valid. Remove it from the list.
        properties.erase(it);
        break;

      case DoesNotConform:
        tc.diagnose(it->second->getLoc(),
                    diag::codable_non_conforming_property_here,
                    proto->getDeclaredType(), it->second->getType());
        LLVM_FALLTHROUGH;

      case TypeNotValidated:
        // We don't produce a diagnostic for a type which failed to validate.
        // This will produce a diagnostic elsewhere anyway.
        propertiesAreValid = false;
        continue;
    }
  }

  if (!propertiesAreValid)
    return false;

  // If there are any remaining properties which the CodingKeys did not cover,
  // we can skip them on encode. On decode, though, we can only skip them if
  // they have a default value.
  if (!properties.empty() &&
      proto == tc.Context.getProtocol(KnownProtocolKind::Decodable)) {
    for (auto it = properties.begin(); it != properties.end(); ++it) {
      if (it->second->getParentInitializer() != nullptr) {
        // Var has a default value.
        continue;
      }

      propertiesAreValid = false;
      tc.diagnose(it->second->getLoc(), diag::codable_non_decoded_property_here,
                  proto->getDeclaredType(), it->first);
    }
  }

  return propertiesAreValid;
}
开发者ID:Jnosh,项目名称:swift,代码行数:88,代码来源:DerivedConformanceCodable.cpp


注:本文中的TypeChecker类示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。