]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_typeck/src/check/check.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / compiler / rustc_typeck / src / check / check.rs
1 use super::coercion::CoerceMany;
2 use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
3 use super::*;
4
5 use rustc_attr as attr;
6 use rustc_errors::Applicability;
7 use rustc_hir as hir;
8 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
9 use rustc_hir::lang_items::LangItem;
10 use rustc_hir::{ItemKind, Node};
11 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
12 use rustc_infer::infer::RegionVariableOrigin;
13 use rustc_middle::ty::fold::TypeFoldable;
14 use rustc_middle::ty::subst::GenericArgKind;
15 use rustc_middle::ty::util::{Discr, IntTypeExt, Representability};
16 use rustc_middle::ty::{self, RegionKind, ToPredicate, Ty, TyCtxt};
17 use rustc_session::config::EntryFnType;
18 use rustc_span::symbol::sym;
19 use rustc_span::{self, MultiSpan, Span};
20 use rustc_target::spec::abi::Abi;
21 use rustc_trait_selection::traits::{self, ObligationCauseCode};
22
23 pub fn check_wf_new(tcx: TyCtxt<'_>) {
24 let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
25 tcx.hir().krate().par_visit_all_item_likes(&visit);
26 }
27
28 pub(super) fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) {
29 if !tcx.sess.target.target.is_abi_supported(abi) {
30 struct_span_err!(
31 tcx.sess,
32 span,
33 E0570,
34 "The ABI `{}` is not supported for the current target",
35 abi
36 )
37 .emit()
38 }
39 }
40
41 /// Helper used for fns and closures. Does the grungy work of checking a function
42 /// body and returns the function context used for that purpose, since in the case of a fn item
43 /// there is still a bit more to do.
44 ///
45 /// * ...
46 /// * inherited: other fields inherited from the enclosing fn (if any)
47 pub(super) fn check_fn<'a, 'tcx>(
48 inherited: &'a Inherited<'a, 'tcx>,
49 param_env: ty::ParamEnv<'tcx>,
50 fn_sig: ty::FnSig<'tcx>,
51 decl: &'tcx hir::FnDecl<'tcx>,
52 fn_id: hir::HirId,
53 body: &'tcx hir::Body<'tcx>,
54 can_be_generator: Option<hir::Movability>,
55 ) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
56 let mut fn_sig = fn_sig;
57
58 debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env);
59
60 // Create the function context. This is either derived from scratch or,
61 // in the case of closures, based on the outer context.
62 let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
63 *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
64
65 let tcx = fcx.tcx;
66 let sess = tcx.sess;
67 let hir = tcx.hir();
68
69 let declared_ret_ty = fn_sig.output();
70
71 let revealed_ret_ty =
72 fcx.instantiate_opaque_types_from_value(fn_id, &declared_ret_ty, decl.output.span());
73 debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty);
74 fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
75 fcx.ret_type_span = Some(decl.output.span());
76 if let ty::Opaque(..) = declared_ret_ty.kind() {
77 fcx.ret_coercion_impl_trait = Some(declared_ret_ty);
78 }
79 fn_sig = tcx.mk_fn_sig(
80 fn_sig.inputs().iter().cloned(),
81 revealed_ret_ty,
82 fn_sig.c_variadic,
83 fn_sig.unsafety,
84 fn_sig.abi,
85 );
86
87 let span = body.value.span;
88
89 fn_maybe_err(tcx, span, fn_sig.abi);
90
91 if body.generator_kind.is_some() && can_be_generator.is_some() {
92 let yield_ty = fcx
93 .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
94 fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
95
96 // Resume type defaults to `()` if the generator has no argument.
97 let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit());
98
99 fcx.resume_yield_tys = Some((resume_ty, yield_ty));
100 }
101
102 let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
103 let outer_hir_id = hir.local_def_id_to_hir_id(outer_def_id);
104 GatherLocalsVisitor::new(&fcx, outer_hir_id).visit_body(body);
105
106 // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
107 // (as it's created inside the body itself, not passed in from outside).
108 let maybe_va_list = if fn_sig.c_variadic {
109 let span = body.params.last().unwrap().span;
110 let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
111 let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
112
113 Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()]))
114 } else {
115 None
116 };
117
118 // Add formal parameters.
119 let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
120 let inputs_fn = fn_sig.inputs().iter().copied();
121 for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
122 // Check the pattern.
123 let ty_span = try { inputs_hir?.get(idx)?.span };
124 fcx.check_pat_top(&param.pat, param_ty, ty_span, false);
125
126 // Check that argument is Sized.
127 // The check for a non-trivial pattern is a hack to avoid duplicate warnings
128 // for simple cases like `fn foo(x: Trait)`,
129 // where we would error once on the parameter as a whole, and once on the binding `x`.
130 if param.pat.simple_ident().is_none() && !tcx.features().unsized_locals {
131 fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
132 }
133
134 fcx.write_ty(param.hir_id, param_ty);
135 }
136
137 inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
138
139 fcx.in_tail_expr = true;
140 if let ty::Dynamic(..) = declared_ret_ty.kind() {
141 // FIXME: We need to verify that the return type is `Sized` after the return expression has
142 // been evaluated so that we have types available for all the nodes being returned, but that
143 // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
144 // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
145 // while keeping the current ordering we will ignore the tail expression's type because we
146 // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
147 // because we will trigger "unreachable expression" lints unconditionally.
148 // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
149 // case that a newcomer might make, returning a bare trait, and in that case we populate
150 // the tail expression's type so that the suggestion will be correct, but ignore all other
151 // possible cases.
152 fcx.check_expr(&body.value);
153 fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
154 tcx.sess.delay_span_bug(decl.output.span(), "`!Sized` return type");
155 } else {
156 fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
157 fcx.check_return_expr(&body.value);
158 }
159 fcx.in_tail_expr = false;
160
161 // We insert the deferred_generator_interiors entry after visiting the body.
162 // This ensures that all nested generators appear before the entry of this generator.
163 // resolve_generator_interiors relies on this property.
164 let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) {
165 let interior = fcx
166 .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
167 fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind));
168
169 let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
170 Some(GeneratorTypes {
171 resume_ty,
172 yield_ty,
173 interior,
174 movability: can_be_generator.unwrap(),
175 })
176 } else {
177 None
178 };
179
180 // Finalize the return check by taking the LUB of the return types
181 // we saw and assigning it to the expected return type. This isn't
182 // really expected to fail, since the coercions would have failed
183 // earlier when trying to find a LUB.
184 //
185 // However, the behavior around `!` is sort of complex. In the
186 // event that the `actual_return_ty` comes back as `!`, that
187 // indicates that the fn either does not return or "returns" only
188 // values of type `!`. In this case, if there is an expected
189 // return type that is *not* `!`, that should be ok. But if the
190 // return type is being inferred, we want to "fallback" to `!`:
191 //
192 // let x = move || panic!();
193 //
194 // To allow for that, I am creating a type variable with diverging
195 // fallback. This was deemed ever so slightly better than unifying
196 // the return value with `!` because it allows for the caller to
197 // make more assumptions about the return type (e.g., they could do
198 //
199 // let y: Option<u32> = Some(x());
200 //
201 // which would then cause this return type to become `u32`, not
202 // `!`).
203 let coercion = fcx.ret_coercion.take().unwrap().into_inner();
204 let mut actual_return_ty = coercion.complete(&fcx);
205 if actual_return_ty.is_never() {
206 actual_return_ty = fcx.next_diverging_ty_var(TypeVariableOrigin {
207 kind: TypeVariableOriginKind::DivergingFn,
208 span,
209 });
210 }
211 fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
212
213 // Check that the main return type implements the termination trait.
214 if let Some(term_id) = tcx.lang_items().termination() {
215 if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) {
216 let main_id = hir.local_def_id_to_hir_id(def_id);
217 if main_id == fn_id {
218 let substs = tcx.mk_substs_trait(declared_ret_ty, &[]);
219 let trait_ref = ty::TraitRef::new(term_id, substs);
220 let return_ty_span = decl.output.span();
221 let cause = traits::ObligationCause::new(
222 return_ty_span,
223 fn_id,
224 ObligationCauseCode::MainFunctionType,
225 );
226
227 inherited.register_predicate(traits::Obligation::new(
228 cause,
229 param_env,
230 trait_ref.without_const().to_predicate(tcx),
231 ));
232 }
233 }
234 }
235
236 // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
237 if let Some(panic_impl_did) = tcx.lang_items().panic_impl() {
238 if panic_impl_did == hir.local_def_id(fn_id).to_def_id() {
239 if let Some(panic_info_did) = tcx.lang_items().panic_info() {
240 if *declared_ret_ty.kind() != ty::Never {
241 sess.span_err(decl.output.span(), "return type should be `!`");
242 }
243
244 let inputs = fn_sig.inputs();
245 let span = hir.span(fn_id);
246 if inputs.len() == 1 {
247 let arg_is_panic_info = match *inputs[0].kind() {
248 ty::Ref(region, ty, mutbl) => match *ty.kind() {
249 ty::Adt(ref adt, _) => {
250 adt.did == panic_info_did
251 && mutbl == hir::Mutability::Not
252 && *region != RegionKind::ReStatic
253 }
254 _ => false,
255 },
256 _ => false,
257 };
258
259 if !arg_is_panic_info {
260 sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
261 }
262
263 if let Node::Item(item) = hir.get(fn_id) {
264 if let ItemKind::Fn(_, ref generics, _) = item.kind {
265 if !generics.params.is_empty() {
266 sess.span_err(span, "should have no type parameters");
267 }
268 }
269 }
270 } else {
271 let span = sess.source_map().guess_head_span(span);
272 sess.span_err(span, "function should have one argument");
273 }
274 } else {
275 sess.err("language item required, but not found: `panic_info`");
276 }
277 }
278 }
279
280 // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
281 if let Some(alloc_error_handler_did) = tcx.lang_items().oom() {
282 if alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() {
283 if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() {
284 if *declared_ret_ty.kind() != ty::Never {
285 sess.span_err(decl.output.span(), "return type should be `!`");
286 }
287
288 let inputs = fn_sig.inputs();
289 let span = hir.span(fn_id);
290 if inputs.len() == 1 {
291 let arg_is_alloc_layout = match inputs[0].kind() {
292 ty::Adt(ref adt, _) => adt.did == alloc_layout_did,
293 _ => false,
294 };
295
296 if !arg_is_alloc_layout {
297 sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
298 }
299
300 if let Node::Item(item) = hir.get(fn_id) {
301 if let ItemKind::Fn(_, ref generics, _) = item.kind {
302 if !generics.params.is_empty() {
303 sess.span_err(
304 span,
305 "`#[alloc_error_handler]` function should have no type \
306 parameters",
307 );
308 }
309 }
310 }
311 } else {
312 let span = sess.source_map().guess_head_span(span);
313 sess.span_err(span, "function should have one argument");
314 }
315 } else {
316 sess.err("language item required, but not found: `alloc_layout`");
317 }
318 }
319 }
320
321 (fcx, gen_ty)
322 }
323
324 pub(super) fn check_struct(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
325 let def_id = tcx.hir().local_def_id(id);
326 let def = tcx.adt_def(def_id);
327 def.destructor(tcx); // force the destructor to be evaluated
328 check_representable(tcx, span, def_id);
329
330 if def.repr.simd() {
331 check_simd(tcx, span, def_id);
332 }
333
334 check_transparent(tcx, span, def);
335 check_packed(tcx, span, def);
336 }
337
338 pub(super) fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
339 let def_id = tcx.hir().local_def_id(id);
340 let def = tcx.adt_def(def_id);
341 def.destructor(tcx); // force the destructor to be evaluated
342 check_representable(tcx, span, def_id);
343 check_transparent(tcx, span, def);
344 check_union_fields(tcx, span, def_id);
345 check_packed(tcx, span, def);
346 }
347
348 /// When the `#![feature(untagged_unions)]` gate is active,
349 /// check that the fields of the `union` does not contain fields that need dropping.
350 pub(super) fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
351 let item_type = tcx.type_of(item_def_id);
352 if let ty::Adt(def, substs) = item_type.kind() {
353 assert!(def.is_union());
354 let fields = &def.non_enum_variant().fields;
355 let param_env = tcx.param_env(item_def_id);
356 for field in fields {
357 let field_ty = field.ty(tcx, substs);
358 // We are currently checking the type this field came from, so it must be local.
359 let field_span = tcx.hir().span_if_local(field.did).unwrap();
360 if field_ty.needs_drop(tcx, param_env) {
361 struct_span_err!(
362 tcx.sess,
363 field_span,
364 E0740,
365 "unions may not contain fields that need dropping"
366 )
367 .span_note(field_span, "`std::mem::ManuallyDrop` can be used to wrap the type")
368 .emit();
369 return false;
370 }
371 }
372 } else {
373 span_bug!(span, "unions must be ty::Adt, but got {:?}", item_type.kind());
374 }
375 true
376 }
377
378 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
379 /// projections that would result in "inheriting lifetimes".
380 pub(super) fn check_opaque<'tcx>(
381 tcx: TyCtxt<'tcx>,
382 def_id: LocalDefId,
383 substs: SubstsRef<'tcx>,
384 span: Span,
385 origin: &hir::OpaqueTyOrigin,
386 ) {
387 check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
388 tcx.ensure().type_of(def_id);
389 check_opaque_for_cycles(tcx, def_id, substs, span, origin);
390 }
391
392 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
393 /// in "inheriting lifetimes".
394 pub(super) fn check_opaque_for_inheriting_lifetimes(
395 tcx: TyCtxt<'tcx>,
396 def_id: LocalDefId,
397 span: Span,
398 ) {
399 let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
400 debug!(
401 "check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
402 def_id, span, item
403 );
404
405 #[derive(Debug)]
406 struct ProhibitOpaqueVisitor<'tcx> {
407 opaque_identity_ty: Ty<'tcx>,
408 generics: &'tcx ty::Generics,
409 ty: Option<Ty<'tcx>>,
410 };
411
412 impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
413 fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
414 debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
415 if t != self.opaque_identity_ty && t.super_visit_with(self) {
416 self.ty = Some(t);
417 return true;
418 }
419 false
420 }
421
422 fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
423 debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
424 if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
425 return *index < self.generics.parent_count as u32;
426 }
427
428 r.super_visit_with(self)
429 }
430
431 fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
432 if let ty::ConstKind::Unevaluated(..) = c.val {
433 // FIXME(#72219) We currenctly don't detect lifetimes within substs
434 // which would violate this check. Even though the particular substitution is not used
435 // within the const, this should still be fixed.
436 return false;
437 }
438 c.super_visit_with(self)
439 }
440 }
441
442 if let ItemKind::OpaqueTy(hir::OpaqueTy {
443 origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn,
444 ..
445 }) = item.kind
446 {
447 let mut visitor = ProhibitOpaqueVisitor {
448 opaque_identity_ty: tcx.mk_opaque(
449 def_id.to_def_id(),
450 InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
451 ),
452 generics: tcx.generics_of(def_id),
453 ty: None,
454 };
455 let prohibit_opaque = tcx
456 .predicates_of(def_id)
457 .predicates
458 .iter()
459 .any(|(predicate, _)| predicate.visit_with(&mut visitor));
460 debug!(
461 "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}",
462 prohibit_opaque, visitor
463 );
464
465 if prohibit_opaque {
466 let is_async = match item.kind {
467 ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => match origin {
468 hir::OpaqueTyOrigin::AsyncFn => true,
469 _ => false,
470 },
471 _ => unreachable!(),
472 };
473
474 let mut err = struct_span_err!(
475 tcx.sess,
476 span,
477 E0760,
478 "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
479 a parent scope",
480 if is_async { "async fn" } else { "impl Trait" },
481 );
482
483 if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
484 if snippet == "Self" {
485 if let Some(ty) = visitor.ty {
486 err.span_suggestion(
487 span,
488 "consider spelling out the type instead",
489 format!("{:?}", ty),
490 Applicability::MaybeIncorrect,
491 );
492 }
493 }
494 }
495 err.emit();
496 }
497 }
498 }
499
500 /// Checks that an opaque type does not contain cycles.
501 pub(super) fn check_opaque_for_cycles<'tcx>(
502 tcx: TyCtxt<'tcx>,
503 def_id: LocalDefId,
504 substs: SubstsRef<'tcx>,
505 span: Span,
506 origin: &hir::OpaqueTyOrigin,
507 ) {
508 if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
509 {
510 match origin {
511 hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span),
512 hir::OpaqueTyOrigin::Binding => {
513 binding_opaque_type_cycle_error(tcx, def_id, span, partially_expanded_type)
514 }
515 _ => opaque_type_cycle_error(tcx, def_id, span),
516 }
517 }
518 }
519
520 pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
521 debug!(
522 "check_item_type(it.hir_id={}, it.name={})",
523 it.hir_id,
524 tcx.def_path_str(tcx.hir().local_def_id(it.hir_id).to_def_id())
525 );
526 let _indenter = indenter();
527 match it.kind {
528 // Consts can play a role in type-checking, so they are included here.
529 hir::ItemKind::Static(..) => {
530 let def_id = tcx.hir().local_def_id(it.hir_id);
531 tcx.ensure().typeck(def_id);
532 maybe_check_static_with_link_section(tcx, def_id, it.span);
533 }
534 hir::ItemKind::Const(..) => {
535 tcx.ensure().typeck(tcx.hir().local_def_id(it.hir_id));
536 }
537 hir::ItemKind::Enum(ref enum_definition, _) => {
538 check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
539 }
540 hir::ItemKind::Fn(..) => {} // entirely within check_item_body
541 hir::ItemKind::Impl { ref items, .. } => {
542 debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id);
543 let impl_def_id = tcx.hir().local_def_id(it.hir_id);
544 if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
545 check_impl_items_against_trait(tcx, it.span, impl_def_id, impl_trait_ref, items);
546 let trait_def_id = impl_trait_ref.def_id;
547 check_on_unimplemented(tcx, trait_def_id, it);
548 }
549 }
550 hir::ItemKind::Trait(_, _, _, _, ref items) => {
551 let def_id = tcx.hir().local_def_id(it.hir_id);
552 check_on_unimplemented(tcx, def_id.to_def_id(), it);
553
554 for item in items.iter() {
555 let item = tcx.hir().trait_item(item.id);
556 if let hir::TraitItemKind::Fn(sig, _) = &item.kind {
557 let abi = sig.header.abi;
558 fn_maybe_err(tcx, item.ident.span, abi);
559 }
560 }
561 }
562 hir::ItemKind::Struct(..) => {
563 check_struct(tcx, it.hir_id, it.span);
564 }
565 hir::ItemKind::Union(..) => {
566 check_union(tcx, it.hir_id, it.span);
567 }
568 hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
569 // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
570 // `async-std` (and `pub async fn` in general).
571 // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
572 // See https://github.com/rust-lang/rust/issues/75100
573 if !tcx.sess.opts.actually_rustdoc {
574 let def_id = tcx.hir().local_def_id(it.hir_id);
575
576 let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
577 check_opaque(tcx, def_id, substs, it.span, &origin);
578 }
579 }
580 hir::ItemKind::TyAlias(..) => {
581 let def_id = tcx.hir().local_def_id(it.hir_id);
582 let pty_ty = tcx.type_of(def_id);
583 let generics = tcx.generics_of(def_id);
584 check_type_params_are_used(tcx, &generics, pty_ty);
585 }
586 hir::ItemKind::ForeignMod(ref m) => {
587 check_abi(tcx, it.span, m.abi);
588
589 if m.abi == Abi::RustIntrinsic {
590 for item in m.items {
591 intrinsic::check_intrinsic_type(tcx, item);
592 }
593 } else if m.abi == Abi::PlatformIntrinsic {
594 for item in m.items {
595 intrinsic::check_platform_intrinsic_type(tcx, item);
596 }
597 } else {
598 for item in m.items {
599 let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
600 let own_counts = generics.own_counts();
601 if generics.params.len() - own_counts.lifetimes != 0 {
602 let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) {
603 (_, 0) => ("type", "types", Some("u32")),
604 // We don't specify an example value, because we can't generate
605 // a valid value for any type.
606 (0, _) => ("const", "consts", None),
607 _ => ("type or const", "types or consts", None),
608 };
609 struct_span_err!(
610 tcx.sess,
611 item.span,
612 E0044,
613 "foreign items may not have {} parameters",
614 kinds,
615 )
616 .span_label(item.span, &format!("can't have {} parameters", kinds))
617 .help(
618 // FIXME: once we start storing spans for type arguments, turn this
619 // into a suggestion.
620 &format!(
621 "replace the {} parameters with concrete {}{}",
622 kinds,
623 kinds_pl,
624 egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
625 ),
626 )
627 .emit();
628 }
629
630 if let hir::ForeignItemKind::Fn(ref fn_decl, _, _) = item.kind {
631 require_c_abi_if_c_variadic(tcx, fn_decl, m.abi, item.span);
632 }
633 }
634 }
635 }
636 _ => { /* nothing to do */ }
637 }
638 }
639
640 pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item<'_>) {
641 let item_def_id = tcx.hir().local_def_id(item.hir_id);
642 // an error would be reported if this fails.
643 let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id.to_def_id());
644 }
645
646 pub(super) fn check_specialization_validity<'tcx>(
647 tcx: TyCtxt<'tcx>,
648 trait_def: &ty::TraitDef,
649 trait_item: &ty::AssocItem,
650 impl_id: DefId,
651 impl_item: &hir::ImplItem<'_>,
652 ) {
653 let kind = match impl_item.kind {
654 hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
655 hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn,
656 hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type,
657 };
658
659 let ancestors = match trait_def.ancestors(tcx, impl_id) {
660 Ok(ancestors) => ancestors,
661 Err(_) => return,
662 };
663 let mut ancestor_impls = ancestors
664 .skip(1)
665 .filter_map(|parent| {
666 if parent.is_from_trait() {
667 None
668 } else {
669 Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id)))
670 }
671 })
672 .peekable();
673
674 if ancestor_impls.peek().is_none() {
675 // No parent, nothing to specialize.
676 return;
677 }
678
679 let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| {
680 match parent_item {
681 // Parent impl exists, and contains the parent item we're trying to specialize, but
682 // doesn't mark it `default`.
683 Some(parent_item) if traits::impl_item_is_final(tcx, &parent_item) => {
684 Some(Err(parent_impl.def_id()))
685 }
686
687 // Parent impl contains item and makes it specializable.
688 Some(_) => Some(Ok(())),
689
690 // Parent impl doesn't mention the item. This means it's inherited from the
691 // grandparent. In that case, if parent is a `default impl`, inherited items use the
692 // "defaultness" from the grandparent, else they are final.
693 None => {
694 if tcx.impl_defaultness(parent_impl.def_id()).is_default() {
695 None
696 } else {
697 Some(Err(parent_impl.def_id()))
698 }
699 }
700 }
701 });
702
703 // If `opt_result` is `None`, we have only encountered `default impl`s that don't contain the
704 // item. This is allowed, the item isn't actually getting specialized here.
705 let result = opt_result.unwrap_or(Ok(()));
706
707 if let Err(parent_impl) = result {
708 report_forbidden_specialization(tcx, impl_item, parent_impl);
709 }
710 }
711
712 pub(super) fn check_impl_items_against_trait<'tcx>(
713 tcx: TyCtxt<'tcx>,
714 full_impl_span: Span,
715 impl_id: LocalDefId,
716 impl_trait_ref: ty::TraitRef<'tcx>,
717 impl_item_refs: &[hir::ImplItemRef<'_>],
718 ) {
719 let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span);
720
721 // If the trait reference itself is erroneous (so the compilation is going
722 // to fail), skip checking the items here -- the `impl_item` table in `tcx`
723 // isn't populated for such impls.
724 if impl_trait_ref.references_error() {
725 return;
726 }
727
728 // Negative impls are not expected to have any items
729 match tcx.impl_polarity(impl_id) {
730 ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
731 ty::ImplPolarity::Negative => {
732 if let [first_item_ref, ..] = impl_item_refs {
733 let first_item_span = tcx.hir().impl_item(first_item_ref.id).span;
734 struct_span_err!(
735 tcx.sess,
736 first_item_span,
737 E0749,
738 "negative impls cannot have any items"
739 )
740 .emit();
741 }
742 return;
743 }
744 }
745
746 // Locate trait definition and items
747 let trait_def = tcx.trait_def(impl_trait_ref.def_id);
748
749 let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id));
750
751 // Check existing impl methods to see if they are both present in trait
752 // and compatible with trait signature
753 for impl_item in impl_items() {
754 let namespace = impl_item.kind.namespace();
755 let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id));
756 let ty_trait_item = tcx
757 .associated_items(impl_trait_ref.def_id)
758 .find_by_name_and_namespace(tcx, ty_impl_item.ident, namespace, impl_trait_ref.def_id)
759 .or_else(|| {
760 // Not compatible, but needed for the error message
761 tcx.associated_items(impl_trait_ref.def_id)
762 .filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id)
763 .next()
764 });
765
766 // Check that impl definition matches trait definition
767 if let Some(ty_trait_item) = ty_trait_item {
768 match impl_item.kind {
769 hir::ImplItemKind::Const(..) => {
770 // Find associated const definition.
771 if ty_trait_item.kind == ty::AssocKind::Const {
772 compare_const_impl(
773 tcx,
774 &ty_impl_item,
775 impl_item.span,
776 &ty_trait_item,
777 impl_trait_ref,
778 );
779 } else {
780 let mut err = struct_span_err!(
781 tcx.sess,
782 impl_item.span,
783 E0323,
784 "item `{}` is an associated const, \
785 which doesn't match its trait `{}`",
786 ty_impl_item.ident,
787 impl_trait_ref.print_only_trait_path()
788 );
789 err.span_label(impl_item.span, "does not match trait");
790 // We can only get the spans from local trait definition
791 // Same for E0324 and E0325
792 if let Some(trait_span) = tcx.hir().span_if_local(ty_trait_item.def_id) {
793 err.span_label(trait_span, "item in trait");
794 }
795 err.emit()
796 }
797 }
798 hir::ImplItemKind::Fn(..) => {
799 let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
800 if ty_trait_item.kind == ty::AssocKind::Fn {
801 compare_impl_method(
802 tcx,
803 &ty_impl_item,
804 impl_item.span,
805 &ty_trait_item,
806 impl_trait_ref,
807 opt_trait_span,
808 );
809 } else {
810 let mut err = struct_span_err!(
811 tcx.sess,
812 impl_item.span,
813 E0324,
814 "item `{}` is an associated method, \
815 which doesn't match its trait `{}`",
816 ty_impl_item.ident,
817 impl_trait_ref.print_only_trait_path()
818 );
819 err.span_label(impl_item.span, "does not match trait");
820 if let Some(trait_span) = opt_trait_span {
821 err.span_label(trait_span, "item in trait");
822 }
823 err.emit()
824 }
825 }
826 hir::ImplItemKind::TyAlias(_) => {
827 let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
828 if ty_trait_item.kind == ty::AssocKind::Type {
829 compare_ty_impl(
830 tcx,
831 &ty_impl_item,
832 impl_item.span,
833 &ty_trait_item,
834 impl_trait_ref,
835 opt_trait_span,
836 );
837 } else {
838 let mut err = struct_span_err!(
839 tcx.sess,
840 impl_item.span,
841 E0325,
842 "item `{}` is an associated type, \
843 which doesn't match its trait `{}`",
844 ty_impl_item.ident,
845 impl_trait_ref.print_only_trait_path()
846 );
847 err.span_label(impl_item.span, "does not match trait");
848 if let Some(trait_span) = opt_trait_span {
849 err.span_label(trait_span, "item in trait");
850 }
851 err.emit()
852 }
853 }
854 }
855
856 check_specialization_validity(
857 tcx,
858 trait_def,
859 &ty_trait_item,
860 impl_id.to_def_id(),
861 impl_item,
862 );
863 }
864 }
865
866 // Check for missing items from trait
867 let mut missing_items = Vec::new();
868 if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) {
869 for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
870 let is_implemented = ancestors
871 .leaf_def(tcx, trait_item.ident, trait_item.kind)
872 .map(|node_item| !node_item.defining_node.is_from_trait())
873 .unwrap_or(false);
874
875 if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
876 if !trait_item.defaultness.has_value() {
877 missing_items.push(*trait_item);
878 }
879 }
880 }
881 }
882
883 if !missing_items.is_empty() {
884 missing_items_err(tcx, impl_span, &missing_items, full_impl_span);
885 }
886 }
887
888 /// Checks whether a type can be represented in memory. In particular, it
889 /// identifies types that contain themselves without indirection through a
890 /// pointer, which would mean their size is unbounded.
891 pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bool {
892 let rty = tcx.type_of(item_def_id);
893
894 // Check that it is possible to represent this type. This call identifies
895 // (1) types that contain themselves and (2) types that contain a different
896 // recursive type. It is only necessary to throw an error on those that
897 // contain themselves. For case 2, there must be an inner type that will be
898 // caught by case 1.
899 match rty.is_representable(tcx, sp) {
900 Representability::SelfRecursive(spans) => {
901 recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
902 return false;
903 }
904 Representability::Representable | Representability::ContainsRecursive => (),
905 }
906 true
907 }
908
909 pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
910 let t = tcx.type_of(def_id);
911 if let ty::Adt(def, substs) = t.kind() {
912 if def.is_struct() {
913 let fields = &def.non_enum_variant().fields;
914 if fields.is_empty() {
915 struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
916 return;
917 }
918 let e = fields[0].ty(tcx, substs);
919 if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
920 struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
921 .span_label(sp, "SIMD elements must have the same type")
922 .emit();
923 return;
924 }
925 match e.kind() {
926 ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
927 _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
928 _ => {
929 struct_span_err!(
930 tcx.sess,
931 sp,
932 E0077,
933 "SIMD vector element type should be machine type"
934 )
935 .emit();
936 return;
937 }
938 }
939 }
940 }
941 }
942
943 pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) {
944 let repr = def.repr;
945 if repr.packed() {
946 for attr in tcx.get_attrs(def.did).iter() {
947 for r in attr::find_repr_attrs(&tcx.sess, attr) {
948 if let attr::ReprPacked(pack) = r {
949 if let Some(repr_pack) = repr.pack {
950 if pack as u64 != repr_pack.bytes() {
951 struct_span_err!(
952 tcx.sess,
953 sp,
954 E0634,
955 "type has conflicting packed representation hints"
956 )
957 .emit();
958 }
959 }
960 }
961 }
962 }
963 if repr.align.is_some() {
964 struct_span_err!(
965 tcx.sess,
966 sp,
967 E0587,
968 "type has conflicting packed and align representation hints"
969 )
970 .emit();
971 } else {
972 if let Some(def_spans) = check_packed_inner(tcx, def.did, &mut vec![]) {
973 let mut err = struct_span_err!(
974 tcx.sess,
975 sp,
976 E0588,
977 "packed type cannot transitively contain a `#[repr(align)]` type"
978 );
979
980 err.span_note(
981 tcx.def_span(def_spans[0].0),
982 &format!(
983 "`{}` has a `#[repr(align)]` attribute",
984 tcx.item_name(def_spans[0].0)
985 ),
986 );
987
988 if def_spans.len() > 2 {
989 let mut first = true;
990 for (adt_def, span) in def_spans.iter().skip(1).rev() {
991 let ident = tcx.item_name(*adt_def);
992 err.span_note(
993 *span,
994 &if first {
995 format!(
996 "`{}` contains a field of type `{}`",
997 tcx.type_of(def.did),
998 ident
999 )
1000 } else {
1001 format!("...which contains a field of type `{}`", ident)
1002 },
1003 );
1004 first = false;
1005 }
1006 }
1007
1008 err.emit();
1009 }
1010 }
1011 }
1012 }
1013
1014 pub(super) fn check_packed_inner(
1015 tcx: TyCtxt<'_>,
1016 def_id: DefId,
1017 stack: &mut Vec<DefId>,
1018 ) -> Option<Vec<(DefId, Span)>> {
1019 if let ty::Adt(def, substs) = tcx.type_of(def_id).kind() {
1020 if def.is_struct() || def.is_union() {
1021 if def.repr.align.is_some() {
1022 return Some(vec![(def.did, DUMMY_SP)]);
1023 }
1024
1025 stack.push(def_id);
1026 for field in &def.non_enum_variant().fields {
1027 if let ty::Adt(def, _) = field.ty(tcx, substs).kind() {
1028 if !stack.contains(&def.did) {
1029 if let Some(mut defs) = check_packed_inner(tcx, def.did, stack) {
1030 defs.push((def.did, field.ident.span));
1031 return Some(defs);
1032 }
1033 }
1034 }
1035 }
1036 stack.pop();
1037 }
1038 }
1039
1040 None
1041 }
1042
1043 pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: &'tcx ty::AdtDef) {
1044 if !adt.repr.transparent() {
1045 return;
1046 }
1047 let sp = tcx.sess.source_map().guess_head_span(sp);
1048
1049 if adt.is_union() && !tcx.features().transparent_unions {
1050 feature_err(
1051 &tcx.sess.parse_sess,
1052 sym::transparent_unions,
1053 sp,
1054 "transparent unions are unstable",
1055 )
1056 .emit();
1057 }
1058
1059 if adt.variants.len() != 1 {
1060 bad_variant_count(tcx, adt, sp, adt.did);
1061 if adt.variants.is_empty() {
1062 // Don't bother checking the fields. No variants (and thus no fields) exist.
1063 return;
1064 }
1065 }
1066
1067 // For each field, figure out if it's known to be a ZST and align(1)
1068 let field_infos = adt.all_fields().map(|field| {
1069 let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
1070 let param_env = tcx.param_env(field.did);
1071 let layout = tcx.layout_of(param_env.and(ty));
1072 // We are currently checking the type this field came from, so it must be local
1073 let span = tcx.hir().span_if_local(field.did).unwrap();
1074 let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false);
1075 let align1 = layout.map(|layout| layout.align.abi.bytes() == 1).unwrap_or(false);
1076 (span, zst, align1)
1077 });
1078
1079 let non_zst_fields =
1080 field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None });
1081 let non_zst_count = non_zst_fields.clone().count();
1082 if non_zst_count != 1 {
1083 bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
1084 }
1085 for (span, zst, align1) in field_infos {
1086 if zst && !align1 {
1087 struct_span_err!(
1088 tcx.sess,
1089 span,
1090 E0691,
1091 "zero-sized field in transparent {} has alignment larger than 1",
1092 adt.descr(),
1093 )
1094 .span_label(span, "has alignment larger than 1")
1095 .emit();
1096 }
1097 }
1098 }
1099
1100 #[allow(trivial_numeric_casts)]
1101 pub fn check_enum<'tcx>(
1102 tcx: TyCtxt<'tcx>,
1103 sp: Span,
1104 vs: &'tcx [hir::Variant<'tcx>],
1105 id: hir::HirId,
1106 ) {
1107 let def_id = tcx.hir().local_def_id(id);
1108 let def = tcx.adt_def(def_id);
1109 def.destructor(tcx); // force the destructor to be evaluated
1110
1111 if vs.is_empty() {
1112 let attributes = tcx.get_attrs(def_id.to_def_id());
1113 if let Some(attr) = tcx.sess.find_by_name(&attributes, sym::repr) {
1114 struct_span_err!(
1115 tcx.sess,
1116 attr.span,
1117 E0084,
1118 "unsupported representation for zero-variant enum"
1119 )
1120 .span_label(sp, "zero-variant enum")
1121 .emit();
1122 }
1123 }
1124
1125 let repr_type_ty = def.repr.discr_type().to_ty(tcx);
1126 if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
1127 if !tcx.features().repr128 {
1128 feature_err(
1129 &tcx.sess.parse_sess,
1130 sym::repr128,
1131 sp,
1132 "repr with 128-bit type is unstable",
1133 )
1134 .emit();
1135 }
1136 }
1137
1138 for v in vs {
1139 if let Some(ref e) = v.disr_expr {
1140 tcx.ensure().typeck(tcx.hir().local_def_id(e.hir_id));
1141 }
1142 }
1143
1144 if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
1145 let is_unit = |var: &hir::Variant<'_>| match var.data {
1146 hir::VariantData::Unit(..) => true,
1147 _ => false,
1148 };
1149
1150 let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
1151 let has_non_units = vs.iter().any(|var| !is_unit(var));
1152 let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var));
1153 let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var));
1154
1155 if disr_non_unit || (disr_units && has_non_units) {
1156 let mut err =
1157 struct_span_err!(tcx.sess, sp, E0732, "`#[repr(inttype)]` must be specified");
1158 err.emit();
1159 }
1160 }
1161
1162 let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len());
1163 for ((_, discr), v) in def.discriminants(tcx).zip(vs) {
1164 // Check for duplicate discriminant values
1165 if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
1166 let variant_did = def.variants[VariantIdx::new(i)].def_id;
1167 let variant_i_hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.expect_local());
1168 let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
1169 let i_span = match variant_i.disr_expr {
1170 Some(ref expr) => tcx.hir().span(expr.hir_id),
1171 None => tcx.hir().span(variant_i_hir_id),
1172 };
1173 let span = match v.disr_expr {
1174 Some(ref expr) => tcx.hir().span(expr.hir_id),
1175 None => v.span,
1176 };
1177 struct_span_err!(
1178 tcx.sess,
1179 span,
1180 E0081,
1181 "discriminant value `{}` already exists",
1182 disr_vals[i]
1183 )
1184 .span_label(i_span, format!("first use of `{}`", disr_vals[i]))
1185 .span_label(span, format!("enum already has `{}`", disr_vals[i]))
1186 .emit();
1187 }
1188 disr_vals.push(discr);
1189 }
1190
1191 check_representable(tcx, sp, def_id);
1192 check_transparent(tcx, sp, def);
1193 }
1194
1195 pub(super) fn check_type_params_are_used<'tcx>(
1196 tcx: TyCtxt<'tcx>,
1197 generics: &ty::Generics,
1198 ty: Ty<'tcx>,
1199 ) {
1200 debug!("check_type_params_are_used(generics={:?}, ty={:?})", generics, ty);
1201
1202 assert_eq!(generics.parent, None);
1203
1204 if generics.own_counts().types == 0 {
1205 return;
1206 }
1207
1208 let mut params_used = BitSet::new_empty(generics.params.len());
1209
1210 if ty.references_error() {
1211 // If there is already another error, do not emit
1212 // an error for not using a type parameter.
1213 assert!(tcx.sess.has_errors());
1214 return;
1215 }
1216
1217 for leaf in ty.walk() {
1218 if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
1219 if let ty::Param(param) = leaf_ty.kind() {
1220 debug!("found use of ty param {:?}", param);
1221 params_used.insert(param.index);
1222 }
1223 }
1224 }
1225
1226 for param in &generics.params {
1227 if !params_used.contains(param.index) {
1228 if let ty::GenericParamDefKind::Type { .. } = param.kind {
1229 let span = tcx.def_span(param.def_id);
1230 struct_span_err!(
1231 tcx.sess,
1232 span,
1233 E0091,
1234 "type parameter `{}` is unused",
1235 param.name,
1236 )
1237 .span_label(span, "unused type parameter")
1238 .emit();
1239 }
1240 }
1241 }
1242 }
1243
1244 pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
1245 tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
1246 }
1247
1248 pub(super) fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
1249 wfcheck::check_item_well_formed(tcx, def_id);
1250 }
1251
1252 pub(super) fn check_trait_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
1253 wfcheck::check_trait_item(tcx, def_id);
1254 }
1255
1256 pub(super) fn check_impl_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
1257 wfcheck::check_impl_item(tcx, def_id);
1258 }
1259
1260 fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) {
1261 struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
1262 .span_label(span, "recursive `async fn`")
1263 .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
1264 .emit();
1265 }
1266
1267 /// Emit an error for recursive opaque types.
1268 ///
1269 /// If this is a return `impl Trait`, find the item's return expressions and point at them. For
1270 /// direct recursion this is enough, but for indirect recursion also point at the last intermediary
1271 /// `impl Trait`.
1272 ///
1273 /// If all the return expressions evaluate to `!`, then we explain that the error will go away
1274 /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
1275 fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
1276 let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
1277
1278 let mut label = false;
1279 if let Some((hir_id, visitor)) = get_owner_return_paths(tcx, def_id) {
1280 let typeck_results = tcx.typeck(tcx.hir().local_def_id(hir_id));
1281 if visitor
1282 .returns
1283 .iter()
1284 .filter_map(|expr| typeck_results.node_type_opt(expr.hir_id))
1285 .all(|ty| matches!(ty.kind(), ty::Never))
1286 {
1287 let spans = visitor
1288 .returns
1289 .iter()
1290 .filter(|expr| typeck_results.node_type_opt(expr.hir_id).is_some())
1291 .map(|expr| expr.span)
1292 .collect::<Vec<Span>>();
1293 let span_len = spans.len();
1294 if span_len == 1 {
1295 err.span_label(spans[0], "this returned value is of `!` type");
1296 } else {
1297 let mut multispan: MultiSpan = spans.clone().into();
1298 for span in spans {
1299 multispan
1300 .push_span_label(span, "this returned value is of `!` type".to_string());
1301 }
1302 err.span_note(multispan, "these returned values have a concrete \"never\" type");
1303 }
1304 err.help("this error will resolve once the item's body returns a concrete type");
1305 } else {
1306 let mut seen = FxHashSet::default();
1307 seen.insert(span);
1308 err.span_label(span, "recursive opaque type");
1309 label = true;
1310 for (sp, ty) in visitor
1311 .returns
1312 .iter()
1313 .filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
1314 .filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
1315 {
1316 struct VisitTypes(Vec<DefId>);
1317 impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
1318 fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
1319 match *t.kind() {
1320 ty::Opaque(def, _) => {
1321 self.0.push(def);
1322 false
1323 }
1324 _ => t.super_visit_with(self),
1325 }
1326 }
1327 }
1328 let mut visitor = VisitTypes(vec![]);
1329 ty.visit_with(&mut visitor);
1330 for def_id in visitor.0 {
1331 let ty_span = tcx.def_span(def_id);
1332 if !seen.contains(&ty_span) {
1333 err.span_label(ty_span, &format!("returning this opaque type `{}`", ty));
1334 seen.insert(ty_span);
1335 }
1336 err.span_label(sp, &format!("returning here with type `{}`", ty));
1337 }
1338 }
1339 }
1340 }
1341 if !label {
1342 err.span_label(span, "cannot resolve opaque type");
1343 }
1344 err.emit();
1345 }