Skip to content

Commit

Permalink
Prepare for using wfcheck on existential types
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jul 18, 2018
1 parent feb139f commit fdd719a
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 36 deletions.
24 changes: 14 additions & 10 deletions src/librustc/ty/mod.rs
Expand Up @@ -2856,22 +2856,26 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
})
}

/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition
pub fn is_impl_trait_defn(tcx: TyCtxt, def_id: DefId) -> Option<DefId> {
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
if let hir::map::NodeItem(item) = tcx.hir.get(node_id) {
if let hir::ItemKind::Existential(ref exist_ty) = item.node {
return exist_ty.impl_trait_fn;
}
}
}
None
}

/// See `ParamEnv` struct def'n for details.
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> ParamEnv<'tcx> {

// 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) {
if let hir::ItemKind::Existential(ref exist_ty) = item.node {
if let Some(parent) = exist_ty.impl_trait_fn {
return param_env(tcx, parent);
}
}
}
}
if let Some(parent) = is_impl_trait_defn(tcx, def_id) {
return param_env(tcx, parent);
}
// Compute the bounds on Self and the type parameters.

Expand Down
8 changes: 7 additions & 1 deletion src/librustc/ty/wf.rs
Expand Up @@ -360,10 +360,16 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
// types appearing in the fn signature
}

ty::TyAnon(..) => {
ty::TyAnon(did, substs) => {
// all of the requirements on type parameters
// should've been checked by the instantiation
// of whatever returned this exact `impl Trait`.

// for named existential types we still need to check them
if super::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
let obligations = self.nominal_obligations(did, substs);
self.out.extend(obligations);
}
}

ty::TyDynamic(data, r) => {
Expand Down
12 changes: 3 additions & 9 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -1037,15 +1037,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
match path.def {
Def::Existential(did) => {
// check for desugared impl trait
if let Some(node_id) = tcx.hir.as_local_node_id(did) {
if let hir::map::NodeItem(item) = tcx.hir.get(node_id) {
if let hir::ItemKind::Existential(ref exist_ty) = item.node {
if exist_ty.impl_trait_fn.is_some() {
let lifetimes = &path.segments[0].args.as_ref().unwrap().args;
return self.impl_trait_ty_to_ty(did, lifetimes);
}
}
}
if ty::is_impl_trait_defn(tcx, did).is_some() {
let lifetimes = &path.segments[0].args.as_ref().unwrap().args;
return self.impl_trait_ty_to_ty(did, lifetimes);
}
let item_segment = path.segments.split_last().unwrap();
self.prohibit_generics(item_segment.1);
Expand Down
@@ -1,17 +1,18 @@
error[E0308]: mismatched types
--> $DIR/generic_type_does_not_live_long_enough.rs:16:18
|
LL | let z: i32 = x; //~ ERROR mismatched types
| ^ expected i32, found anonymized type
|
= note: expected type `i32`
found type `WrongGeneric::<&{integer}>`

warning: not reporting region error due to nll
--> $DIR/generic_type_does_not_live_long_enough.rs:16:1
--> $DIR/generic_type_does_not_live_long_enough.rs:19:1
|
LL | existential type WrongGeneric<T>: 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generic_type_does_not_live_long_enough.rs:20:5
|
LL | t
| ^
|
= help: consider adding an explicit lifetime bound `T: 'static`...

error: aborting due to previous error

For more information about this error, try `rustc --explain E0310`.
For more information about this error, try `rustc --explain E0308`.
Expand Up @@ -8,10 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.


#![feature(existential_type)]

fn main() {}
fn main() {
let y = 42;
let x = wrong_generic(&y);
let z: i32 = x; //~ ERROR mismatched types
}

existential type WrongGeneric<T>: 'static;
//~^ ERROR the parameter type `T` may not live long enough
Expand Down
@@ -1,5 +1,14 @@
error[E0308]: mismatched types
--> $DIR/generic_type_does_not_live_long_enough.rs:16:18
|
LL | let z: i32 = x; //~ ERROR mismatched types
| ^ expected i32, found anonymized type
|
= note: expected type `i32`
found type `WrongGeneric::<&{integer}>`

error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generic_type_does_not_live_long_enough.rs:16:1
--> $DIR/generic_type_does_not_live_long_enough.rs:19:1
|
LL | existential type WrongGeneric<T>: 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -8,11 +17,12 @@ LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
| - help: consider adding an explicit lifetime bound `T: 'static`...
|
note: ...so that the type `T` will meet its required lifetime bounds
--> $DIR/generic_type_does_not_live_long_enough.rs:16:1
--> $DIR/generic_type_does_not_live_long_enough.rs:19:1
|
LL | existential type WrongGeneric<T>: 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0310`.
Some errors occurred: E0308, E0310.
For more information about an error, try `rustc --explain E0308`.

0 comments on commit fdd719a

Please sign in to comment.