diff --git a/compiler/src/typed/disambiguation.re b/compiler/src/typed/disambiguation.re index 5c4ac4eb7b..15138d08e8 100644 --- a/compiler/src/typed/disambiguation.re +++ b/compiler/src/typed/disambiguation.re @@ -136,6 +136,7 @@ module NameChoice = ~warn=Location.prerr_warning, ~check_lk=(_, _) => (), ~scope=?, + ~scoped=false, lid, env, opath, @@ -206,25 +207,33 @@ module NameChoice = lbl; }) { | Not_found => - try({ - let lbl = lookup_from_type(env, tpath, lid); - check_lk(tpath, lbl); - if (in_env(lbl)) { - let s = Printtyp.string_of_path(tpath); - warn( - lid.loc, - Warnings.NameOutOfScope( - s, - [Identifier.last(lid.txt)], - false, - ), - ); - }; - if (!pr) { - warn_pr(); - }; - lbl; - }) { + try( + { + if (scoped) { + // When scoped skip looking up directly from the type + raise( + Not_found, + ); + }; + let lbl = lookup_from_type(env, tpath, lid); + check_lk(tpath, lbl); + if (in_env(lbl)) { + let s = Printtyp.string_of_path(tpath); + warn( + lid.loc, + Warnings.NameOutOfScope( + s, + [Identifier.last(lid.txt)], + false, + ), + ); + }; + if (!pr) { + warn_pr(); + }; + lbl; + } + ) { | Not_found => if (lbls == []) { unbound_name_error(env, lid); diff --git a/compiler/src/typed/typecore.re b/compiler/src/typed/typecore.re index 9d3fc47805..33904a411c 100644 --- a/compiler/src/typed/typecore.re +++ b/compiler/src/typed/typecore.re @@ -2104,7 +2104,7 @@ and type_construct = wrap_disambiguate( "This variant expression is expected to have", ty_expected_explained, - Constructor.disambiguate(lid, env, opath), + Constructor.disambiguate(~scoped=true, lid, env, opath), constrs, ); let is_record_cstr_def = constr.cstr_inlined != None; diff --git a/compiler/src/typed/typepat.re b/compiler/src/typed/typepat.re index 43e82b241f..b83e920ae7 100644 --- a/compiler/src/typed/typepat.re +++ b/compiler/src/typed/typepat.re @@ -883,7 +883,7 @@ and type_pat_aux = wrap_disambiguate( "This variant pattern is expected to have", mk_expected(expected_ty), - Constructor.disambiguate(lid, env^, opath), + Constructor.disambiguate(~scoped=true, lid, env^, opath), candidates, ); diff --git a/compiler/test/suites/types.re b/compiler/test/suites/types.re index 0776ebfc68..0ea1b0236e 100644 --- a/compiler/test/suites/types.re +++ b/compiler/test/suites/types.re @@ -548,3 +548,63 @@ describe("function types", ({test, testSkip}) => { "Syntax error after '=>' and before '\\)'.\nExpected a type for the result of the function type.", ); }); + +describe("scoped types", ({test, testSkip}) => { + let assertCompileError = makeCompileErrorRunner(test); + + assertCompileError( + "regression_1968_constructor_scoping_1", + {| + module A { + provide enum Variant { + VariantA, + VariantB, + VariantC, + } + provide let notSame = (x: a, y: b) => (x, y) + } + A.notSame(A.VariantA, A.VariantB) // Valid + A.notSame(A.VariantA, VariantC) // Invalid + |}, + "Error: Unbound constructor VariantC", + ); + assertCompileError( + "regression_1968_constructor_scoping_2", + {| + module A { + provide enum Variant { + VariantA, + VariantB, + VariantC, + } + provide let same = (x: a, y: a) => (x, y) + } + A.same(A.VariantA, A.VariantB) // Valid + A.same(A.VariantA, VariantC) // Invalid + |}, + "Error: Unbound constructor VariantC", + ); + assertCompileError( + "regression_1968_constructor_scoping_3", + {| + module A { + provide enum Variant { + VariantA, + VariantB, + VariantC, + } + } + match (A.VariantA) { + A.VariantA => void, + A.VariantB => void, + _ => void, + } + match (A.VariantA) { + A.VariantA => void, + VariantC => void, + _ => void, + } + |}, + "Error: Unbound constructor VariantC", + ); +});