X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_typeck%2Fcheck%2Fmod.rs;h=09fe92415b91a28ccf6ba81a2a88b8c1e505400f;hb=4b1d404d833929dffcc1ea8d704aa3d2c432ba11;hp=77d45cfa63c10ed0c07dc4b486bedfe2377faaab;hpb=831d33b8b0108c808d5148d434295c4c94f7102b;p=rust.git diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 77d45cfa63c..09fe92415b9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -746,11 +746,12 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option { tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl) } -/// If this `DefId` is a "primary tables entry", returns `Some((body_id, decl))` -/// with information about it's body-id and fn-decl (if any). Otherwise, +/// If this `DefId` is a "primary tables entry", returns +/// `Some((body_id, header, decl))` with information about +/// it's body-id, fn-header and fn-decl (if any). Otherwise, /// returns `None`. /// -/// If this function returns "some", then `typeck_tables(def_id)` will +/// If this function returns `Some`, then `typeck_tables(def_id)` will /// succeed; if it returns `None`, then `typeck_tables(def_id)` may or /// may not succeed. In some cases where this function returns `None` /// (notably closures), `typeck_tables(def_id)` would wind up @@ -758,40 +759,40 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option { fn primary_body_of( tcx: TyCtxt<'_>, id: hir::HirId, -) -> Option<(hir::BodyId, Option<&hir::FnDecl>)> { +) -> Option<(hir::BodyId, Option<&hir::Ty>, Option<&hir::FnHeader>, Option<&hir::FnDecl>)> { match tcx.hir().get(id) { Node::Item(item) => { match item.node { - hir::ItemKind::Const(_, body) | - hir::ItemKind::Static(_, _, body) => - Some((body, None)), - hir::ItemKind::Fn(ref decl, .., body) => - Some((body, Some(decl))), + hir::ItemKind::Const(ref ty, body) | + hir::ItemKind::Static(ref ty, _, body) => + Some((body, Some(ty), None, None)), + hir::ItemKind::Fn(ref decl, ref header, .., body) => + Some((body, None, Some(header), Some(decl))), _ => None, } } Node::TraitItem(item) => { match item.node { - hir::TraitItemKind::Const(_, Some(body)) => - Some((body, None)), + hir::TraitItemKind::Const(ref ty, Some(body)) => + Some((body, Some(ty), None, None)), hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => - Some((body, Some(&sig.decl))), + Some((body, None, Some(&sig.header), Some(&sig.decl))), _ => None, } } Node::ImplItem(item) => { match item.node { - hir::ImplItemKind::Const(_, body) => - Some((body, None)), + hir::ImplItemKind::Const(ref ty, body) => + Some((body, Some(ty), None, None)), hir::ImplItemKind::Method(ref sig, body) => - Some((body, Some(&sig.decl))), + Some((body, None, Some(&sig.header), Some(&sig.decl))), _ => None, } } - Node::AnonConst(constant) => Some((constant.body, None)), + Node::AnonConst(constant) => Some((constant.body, None, None, None)), _ => None, } } @@ -824,15 +825,21 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> { let span = tcx.hir().span(id); // Figure out what primary body this item has. - let (body_id, fn_decl) = primary_body_of(tcx, id).unwrap_or_else(|| { - span_bug!(span, "can't type-check body of {:?}", def_id); - }); + let (body_id, body_ty, fn_header, fn_decl) = primary_body_of(tcx, id) + .unwrap_or_else(|| { + span_bug!(span, "can't type-check body of {:?}", def_id); + }); let body = tcx.hir().body(body_id); let tables = Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); - let fcx = if let Some(decl) = fn_decl { - let fn_sig = tcx.fn_sig(def_id); + let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) { + let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { + let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); + AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl) + } else { + tcx.fn_sig(def_id) + }; check_abi(tcx, span, fn_sig.abi()); @@ -849,7 +856,10 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> { fcx } else { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); - let expected_type = tcx.type_of(def_id); + let expected_type = body_ty.and_then(|ty| match ty.node { + hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)), + _ => None + }).unwrap_or_else(|| tcx.type_of(def_id)); let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); @@ -1315,19 +1325,35 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { check_packed(tcx, span, def_id); } -fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>, span: Span) { +fn check_opaque<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + span: Span, + origin: &hir::ExistTyOrigin +) { if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) { - let mut err = struct_span_err!( - tcx.sess, span, E0720, - "opaque type expands to a recursive type", - ); - err.span_label(span, "expands to self-referential type"); - if let ty::Opaque(..) = partially_expanded_type.sty { - err.note("type resolves to itself"); + if let hir::ExistTyOrigin::AsyncFn = origin { + struct_span_err!( + tcx.sess, span, E0733, + "recursion in an `async fn` requires boxing", + ) + .span_label(span, "an `async fn` cannot invoke itself directly") + .note("a recursive `async fn` must be rewritten to return a boxed future.") + .emit(); } else { - err.note(&format!("expanded type is `{}`", partially_expanded_type)); + let mut err = struct_span_err!( + tcx.sess, span, E0720, + "opaque type expands to a recursive type", + ); + err.span_label(span, "expands to a recursive type"); + if let ty::Opaque(..) = partially_expanded_type.sty { + err.note("type resolves to itself"); + } else { + err.note(&format!("expanded type is `{}`", partially_expanded_type)); + } + err.emit(); } - err.emit(); } } @@ -1377,11 +1403,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) { hir::ItemKind::Union(..) => { check_union(tcx, it.hir_id, it.span); } - hir::ItemKind::Existential(..) => { + hir::ItemKind::Existential(hir::ExistTy{origin, ..}) => { let def_id = tcx.hir().local_def_id(it.hir_id); let substs = InternalSubsts::identity_for_item(tcx, def_id); - check_opaque(tcx, def_id, substs, it.span); + check_opaque(tcx, def_id, substs, it.span, &origin); } hir::ItemKind::Ty(..) => { let def_id = tcx.hir().local_def_id(it.hir_id); @@ -1442,11 +1468,14 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span) return } - // For the wasm32 target statics with #[link_section] are placed into custom + // For the wasm32 target statics with `#[link_section]` are placed into custom // sections of the final output file, but this isn't link custom sections of // other executable formats. Namely we can only embed a list of bytes, // nothing with pointers to anything else or relocations. If any relocation // show up, reject them here. + // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is + // the consumer's responsibility to ensure all bytes that have been read + // have defined values. let instance = ty::Instance::mono(tcx, id); let cid = GlobalId { instance,