Only check existential types, not the desugared impl Trait

This commit is contained in:
Oliver Schneider 2018-07-16 10:46:27 +02:00
parent 3e215a3c87
commit 2ed1aca101

View File

@ -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
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);
// 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
},