diff options
| -rw-r--r-- | src/librustc/infer/anon_types/mod.rs | 17 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/wfcheck.rs | 20 |
3 files changed, 38 insertions, 1 deletions
diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/anon_types/mod.rs index 5e731871e28..8cc8abda708 100644 --- a/src/librustc/infer/anon_types/mod.rs +++ b/src/librustc/infer/anon_types/mod.rs @@ -808,6 +808,23 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { } /// Whether `anon_node_id` is a sibling or a child of a sibling of `def_id` +/// +/// ```rust +/// pub mod foo { +/// pub mod bar { +/// pub existential type Baz; +/// +/// fn f1() -> Baz { .. } +/// } +/// +/// fn f2() -> bar::Baz { .. } +/// } +/// ``` +/// +/// Here, `def_id` will be the `DefId` of the existential type `Baz`. +/// `anon_node_id` is the `NodeId` of the reference to Baz -- so either the return type of f1 or f2. +/// We will return true if the reference is within the same module as the existential type +/// So true for f1, false for f2. pub fn may_define_existential_type( tcx: TyCtxt, def_id: DefId, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2e221424e3c..7ae6f812649 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2861,7 +2861,7 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ParamEnv<'tcx> { - // The param_env of an existential type is its parent's param_env + // The param_env of an impl Trait type is its defining function's param_env if let Some(Def::Existential(_)) = tcx.describe_def(def_id) { if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { if let hir::map::NodeItem(item) = tcx.hir.get(node_id) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index d2c96221991..cd6a1e3fdba 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -535,6 +535,26 @@ fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, check_where_clauses(tcx, fcx, span, def_id, Some(sig.output())); } +/// Checks "defining uses" of existential types to ensure that they meet the restrictions laid for +/// "higher-order pattern unification". +/// This ensures that inference is tractable. +/// In particular, definitions of existential types can only use other generics as arguments, +/// and they cannot repeat an argument. Example: +/// +/// ```rust +/// existential type Foo<A, B>; +/// +/// // ok -- `Foo` is applied to two distinct, generic types. +/// fn a<T, U>() -> Foo<T, U> { .. } +/// +/// // not ok -- `Foo` is applied to `T` twice. +/// fn b<T>() -> Foo<T, T> { .. } +/// +/// +/// // not ok -- `Foo` is applied to a non-generic type. +/// fn b<T>() -> Foo<T, u32> { .. } +/// ``` +/// fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'gcx>, fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, |
