When using RX 2 Contract Assemblies from the RXX project, Static Analyzer doesn't seem to understand contracts on the observable creation methods

Unanswered When using RX 2 Contract Assemblies from the RXX project, Static Analyzer doesn't seem to understand contracts on the observable creation methods

  • Tuesday, February 05, 2013 4:33 PM
     
     

    When I use methods such as:

    IObservable<T> Observable.Create<T>(Func<IObserver<T>,IDisposable>);
    IObservable<T> Observable.Defer<T>(Func<IObservable<T>);
    IObservable<T2> Observable.Using<T1,T2>(Func<T1>,Func<T1,IObserver<T2>,IObservable<T2>>)

    The Analyzer cannot prove that their return value is not NULL, even though in the contract assembly they have a contract.Ensures on them:

    public static IObservable<TValue> Defer<TValue>(Func<IObservable<TValue>> observableFactory)
    {
    Contract.Requires(observableFactory != null, null, "observableFactory != null");
    Contract.Ensures(Contract.Result<IObservable<TValue>>() != null, null, "Contract.Result<IObservable<TValue>>() != null");
    return null;
    }

    Here are some examples:

    "ensures unproven: Contract.Result<IObservable<object>>() != null"

            private IObservable<object> ExecuteObservableService<TRequestDto, TResponseDto>(TRequestDto request)
                where TResponseDto : class, IObservable<object>
                where TRequestDto : class
            {
                Contract.Requires(request != null);
                Contract.Ensures(Contract.Result<IObservable<object>>() != null);

                return Observable.Using(_serviceFactory.GetService<TRequestDto, TResponseDto>, service => service.Instance.Execute(request));
            }

    "ensures unproven: Contract.Result<IObservable<ProjectorResult>>() != null"

            /// <inheritdoc/>
            public IObservable<ProjectorResult> Project(IProjector[] projectors, Func<long, IObservable<Commit>> queryCommits)
            {
                return Observable.Create<ProjectorResult>(observer => ProjectionistObservable(observer, projectors, queryCommits));
            }

    "requires unproven: source != null" (it is complaining about the "Requires" rule for the .Where operator)

                return Observable
                    .Defer(async () => _zookeeperClient.WatchData(await GetJobPathAsync(request.WorkflowId, request.JobId).NoContext()))
                    .Where(data => data != null && data.Count() >= 8)

    The last example proves that the analyzer is using the contract assembly (since it is complaining about a Requires within the Where method.

    Any ideas how to fix this?

All Replies

  • Tuesday, February 05, 2013 8:36 PM
     
     

    Hi,

    I've run into the same problem as well.  It's one of the reasons that I never published the contract assemblies for Rx 2.0 as a separate download.

    I assume the issue has something to do with the fact that I created the contract assemblies by hand.  There must be some subtle difference between these assemblies and contract assemblies that are generated by the CC tools.  The contract assemblies that I had created for Rx 1.0 worked fine.  I combed over the new contract assemblies carefully, comparing them to existing contract assemblies that ship with CC, but I couldn't find any obvious differences.  I tried several small adjustments to match the attributes in FCL contract assemblies, but nothing has worked.

    The issue may go away once I add the contracts directly to the Rx library and let CC generate contract assemblies from the source, but it's only a work-in-progress:

    http://rx.codeplex.com/SourceControl/network/forks/davedev/RxCodeContracts

    Note that I've actually made some progress already, I just haven't checked it in yet.

    - Dave


    http://davesexton.com/blog