Skip to content

Commit

Permalink
[flow] reposition type guard before use in refinement
Browse files Browse the repository at this point in the history
Summary:
When refining with type guards it is possible that we end up using the type guard itself as the result of the refinement. In that case that type needs to be repositioned. If not if the type guard happens to be an opaque type then we risk having the reason associated with it point to a remote file, thus making it invalid.

Changelog: [fix] fixed a bug when using opaque types in type guards in files other than the one where the type guard function was defined.

Reviewed By: SamChou19815

Differential Revision: D67153109

fbshipit-source-id: 2702a2e670fcceef3d817349591db4c04d5373cb
  • Loading branch information
panagosg7 authored and facebook-github-bot committed Dec 12, 2024
1 parent e6c80af commit d41d995
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/typing/predicate_kit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,10 @@ and call_latent_pred cx trace fun_t ~use_op ~reason ~targs ~argts ~sense ~idx ti
(* This is not the refined parameter. *)
Type_filter.TypeFilterResult { type_ = tin; changed = false }
else if sense then
let type_ = intersect cx tin type_guard in
let type_ = intersect cx tin (reposition_reason cx ~trace reason type_guard) in
Type_filter.TypeFilterResult { type_; changed = type_ != tin }
else if not one_sided then
type_guard_diff cx tin type_guard
type_guard_diff cx tin (reposition_reason cx ~trace reason type_guard)
else
(* Do not refine else branch on one-sided type-guard *)
Type_filter.TypeFilterResult { type_ = tin; changed = false }
Expand Down
6 changes: 6 additions & 0 deletions tests/type_guards/opaque_exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ export opaque type OpaqueC = C;
export opaque type OpaqueAs = As;
export opaque type OpaqueT = void | OpaqueB | OpaqueC | OpaqueAs;
export type OpaqueOrString = OpaqueT | string;

export opaque type Animal: string = string;
export opaque type Raccoon: Animal = string;

declare export function isAnimal(_s: string): implies _s is Animal;
declare export function isRaccoon(_s: string): implies _s is Raccoon;
11 changes: 11 additions & 0 deletions tests/type_guards/refinement.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,14 @@ function sentinel_refinement() {
}
}
}

import type {Animal, Raccoon} from './opaque_exports';
import {isAnimal, isRaccoon} from './opaque_exports';

function getRaccoon(s: string): ?Raccoon {
if (!isAnimal(s)) return null;
if (isRaccoon(s)) {
return s; // okay
}
return null;
}

0 comments on commit d41d995

Please sign in to comment.