Skip to content

Commit

Permalink
Only check existential types, not the desugared impl Trait
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jul 18, 2018
1 parent 3e215a3 commit 2ed1aca
Showing 1 changed file with 58 additions and 50 deletions.
108 changes: 58 additions & 50 deletions src/librustc_typeck/check/wfcheck.rs
Expand Up @@ -549,57 +549,65 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
fldop: |ty| {
if let ty::TyAnon(def_id, substs) = ty.sty {
trace!("check_existential_types: anon_ty, {:?}, {:?}", def_id, substs);
let anon_node_id = tcx.hir.as_local_node_id(def_id).unwrap();
if may_define_existential_type(tcx, fn_def_id, anon_node_id) {
let generics = tcx.generics_of(def_id);
trace!("check_existential_types may define. Generics: {:#?}", generics);
for (subst, param) in substs.iter().zip(&generics.params) {
if let ty::subst::UnpackedKind::Type(ty) = subst.unpack() {
match ty.sty {
ty::TyParam(..) => {},
// prevent `fn foo() -> Foo<u32>` from being defining
_ => {
tcx
.sess
.struct_span_err(
span,
"non-defining existential type use in defining scope",
)
.span_note(
tcx.def_span(param.def_id),
&format!(
"used non-generic type {} for generic parameter",
ty,
),
)
.emit();
return tcx.types.err;
},
} // match ty
} // if let Type = subst
} // for (subst, param)
} // if may_define_existential_type

// now register the bounds on the parameters of the existential type
// so the parameters given by the function need to fulfil them
// ```rust
// existential type Foo<T: Bar>: 'static;
// fn foo<U>() -> Foo<U> { .. *}
// ```
// becomes
// ```rust
// existential type Foo<T: Bar>: 'static;
// fn foo<U: Bar>() -> Foo<U> { .. *}
// ```
let predicates = tcx.predicates_of(def_id);
trace!("check_existential_types may define. adding predicates: {:#?}", predicates);
for &pred in predicates.predicates.iter() {
let substituted_pred = pred.subst(fcx.tcx, substs);
// Avoid duplication of predicates that contain no parameters, for example.
if !predicates.predicates.contains(&substituted_pred) {
substituted_predicates.push(substituted_pred);
let generics = tcx.generics_of(def_id);
// only check named existential types
if generics.parent.is_none() {
let anon_node_id = tcx.hir.as_local_node_id(def_id).unwrap();
if may_define_existential_type(tcx, fn_def_id, anon_node_id) {
trace!("check_existential_types may define. Generics: {:#?}", generics);
for (subst, param) in substs.iter().zip(&generics.params) {
if let ty::subst::UnpackedKind::Type(ty) = subst.unpack() {
match ty.sty {
ty::TyParam(..) => {},
// prevent `fn foo() -> Foo<u32>` from being defining
_ => {
tcx
.sess
.struct_span_err(
span,
"non-defining existential type use \
in defining scope",
)
.span_note(
tcx.def_span(param.def_id),
&format!(
"used non-generic type {} for \
generic parameter",
ty,
),
)
.emit();
return tcx.types.err;
},
} // match ty
} // if let Type = subst
} // for (subst, param)
} // if may_define_existential_type

// now register the bounds on the parameters of the existential type
// so the parameters given by the function need to fulfil them
// ```rust
// existential type Foo<T: Bar>: 'static;
// fn foo<U>() -> Foo<U> { .. *}
// ```
// becomes
// ```rust
// existential type Foo<T: Bar>: 'static;
// fn foo<U: Bar>() -> Foo<U> { .. *}
// ```
let predicates = tcx.predicates_of(def_id);
trace!(
"check_existential_types may define. adding predicates: {:#?}",
predicates,
);
for &pred in predicates.predicates.iter() {
let substituted_pred = pred.subst(fcx.tcx, substs);
// Avoid duplication of predicates that contain no parameters, for example.
if !predicates.predicates.contains(&substituted_pred) {
substituted_predicates.push(substituted_pred);
}
}
}
} // if is_named_existential_type
} // if let TyAnon
ty
},
Expand Down

0 comments on commit 2ed1aca

Please sign in to comment.