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