Beispiel #1
0
        private static bool interchangeableTypesTo(ComputationContext ctx, IEntityInstance input, IEntityInstance target)
        {
            bool is_input_sealed = input.EnumerateAll()
                                   .Select(it => { ctx.Env.Dereference(it, out IEntityInstance result); return(result); })
                                   .SelectMany(it => it.EnumerateAll())
                                   .All(it => it.Target.Modifier.IsSealed);

            if (is_input_sealed)
            {
                TypeMatch match = input.MatchesTarget(ctx, target, TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: true).WithIgnoredMutability(true));

                // example: we cannot check if x (of Int) is IAlien because Int is sealed and there is no way
                // it could be something else not available in its inheritance tree
                if (!match.Passed)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #2
0
        public void Validate(ComputationContext ctx)
        {
            foreach (NameReference base_of in this.BaseOfNames)
            {
                // we allow slicing because we just need if the hierarchy is not reversed, not to pass actual values
                if (this.InheritsNames.Any(it
                                           =>
                {
                    TypeMatch match = it.Evaluation.Components.MatchesTarget(ctx, base_of.Evaluation.Components,
                                                                             TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: true));
                    return(match == TypeMatch.Same || match == TypeMatch.Substitute);
                }))
                {
                    ctx.AddError(ErrorCode.ConstraintConflictingTypeHierarchy, base_of);
                }
            }

            // the left side: target match (i.e. template inner parameter type) -> template
            // the right side: this -> template parameter -> name definition -> template
            if (this.Name.Binding.Match.Instance.Target.Owner != this.Owner.Owner.Owner)
            {
                ctx.AddError(ErrorCode.MisplacedConstraint, this);
            }
        }
Beispiel #3
0
        public ConstraintMatch ArgumentMatchesParameterConstraints(ComputationContext ctx, EntityInstance closedTemplate,
                                                                   TemplateParameter param)
        {
            if (this.TargetsTemplateParameter && this.TemplateParameterTarget == param)
            {
                return(ConstraintMatch.Yes);
            }

            TypeMutability arg_mutability = this.SurfaceMutabilityOfType(ctx);

            if (param.Constraint.Modifier.HasConst &&
                arg_mutability != TypeMutability.ForceConst && arg_mutability != TypeMutability.ConstAsSource)
            {
                return(ConstraintMatch.MutabilityViolation);
            }
            else if (param.Constraint.Modifier.HasMutable && arg_mutability != TypeMutability.ForceMutable)
            {
                return(ConstraintMatch.MutabilityViolation);
            }
            else if (param.Constraint.Modifier.HasReassignable && !arg_mutability.HasFlag(TypeMutability.Reassignable))
            {
                return(ConstraintMatch.AssignabilityViolation);
            }

            // 'inherits' part of constraint
            foreach (EntityInstance constraint_inherits in param.Constraint.TranslateInherits(closedTemplate))
            {
                TypeMatch match = TypeMatcher.Matches(ctx, this, constraint_inherits,
                                                      TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: true));
                if (match.IsMismatch())
                {
                    return(ConstraintMatch.InheritsViolation);
                }
            }

            {
                VirtualTable vtable = EntityInstanceExtension.BuildDuckVirtualTable(ctx, this, param.AssociatedType.InstanceOf,
                                                                                    allowPartial: false);
                if (vtable == null)
                {
                    return(ConstraintMatch.MissingFunction);
                }
            }


            // 'base-of' part of constraint
            IEnumerable <IEntityInstance> arg_bases = (this.TargetsTemplateParameter
                ? this.TargetType.TemplateParameter.Constraint.TranslateBaseOf(closedTemplate)
                : Enumerable.Empty <EntityInstance>()
                                                       )
                                                      .Concat(this);

            foreach (EntityInstance constraint_base in param.Constraint.TranslateBaseOf(closedTemplate))
            {
                if (!arg_bases.Any(it => !constraint_base.MatchesTarget(ctx, it, TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: true))
                                   .IsMismatch()))
                {
                    return(ConstraintMatch.BaseViolation);
                }
            }

            return(ConstraintMatch.Yes);
        }