]>
Commit | Line | Data |
---|---|---|
1b1a35ee | 1 | use super::coercion::CoerceMany; |
29967ef6 | 2 | use super::compare_method::check_type_bounds; |
1b1a35ee XL |
3 | use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl}; |
4 | use super::*; | |
5 | ||
6 | use rustc_attr as attr; | |
29967ef6 | 7 | use rustc_errors::{Applicability, ErrorReported}; |
1b1a35ee | 8 | use rustc_hir as hir; |
cdc7bbd5 | 9 | use rustc_hir::def_id::{DefId, LocalDefId}; |
6a06907d | 10 | use rustc_hir::intravisit::Visitor; |
1b1a35ee | 11 | use rustc_hir::lang_items::LangItem; |
6a06907d | 12 | use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; |
1b1a35ee | 13 | use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; |
29967ef6 | 14 | use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; |
1b1a35ee | 15 | use rustc_middle::ty::fold::TypeFoldable; |
6a06907d | 16 | use rustc_middle::ty::layout::MAX_SIMD_LANES; |
1b1a35ee | 17 | use rustc_middle::ty::subst::GenericArgKind; |
cdc7bbd5 | 18 | use rustc_middle::ty::util::{Discr, IntTypeExt}; |
17df50a5 | 19 | use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt}; |
136023e0 | 20 | use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; |
1b1a35ee XL |
21 | use rustc_span::symbol::sym; |
22 | use rustc_span::{self, MultiSpan, Span}; | |
23 | use rustc_target::spec::abi::Abi; | |
29967ef6 | 24 | use rustc_trait_selection::opaque_types::InferCtxtExt as _; |
cdc7bbd5 | 25 | use rustc_trait_selection::traits; |
29967ef6 | 26 | use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; |
cdc7bbd5 | 27 | use rustc_ty_utils::representability::{self, Representability}; |
1b1a35ee | 28 | |
cdc7bbd5 | 29 | use std::iter; |
29967ef6 XL |
30 | use std::ops::ControlFlow; |
31 | ||
1b1a35ee XL |
32 | pub fn check_wf_new(tcx: TyCtxt<'_>) { |
33 | let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); | |
34 | tcx.hir().krate().par_visit_all_item_likes(&visit); | |
35 | } | |
36 | ||
136023e0 XL |
37 | pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { |
38 | match tcx.sess.target.is_abi_supported(abi) { | |
39 | Some(true) => (), | |
40 | Some(false) => struct_span_err!( | |
1b1a35ee XL |
41 | tcx.sess, |
42 | span, | |
43 | E0570, | |
136023e0 | 44 | "`{}` is not a supported ABI for the current target", |
1b1a35ee XL |
45 | abi |
46 | ) | |
136023e0 XL |
47 | .emit(), |
48 | None => { | |
49 | tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { | |
50 | lint.build("use of calling convention not supported on this target").emit() | |
51 | }); | |
52 | } | |
1b1a35ee | 53 | } |
5869c6ff XL |
54 | |
55 | // This ABI is only allowed on function pointers | |
56 | if abi == Abi::CCmseNonSecureCall { | |
57 | struct_span_err!( | |
58 | tcx.sess, | |
59 | span, | |
60 | E0781, | |
61 | "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers." | |
62 | ) | |
63 | .emit() | |
64 | } | |
1b1a35ee XL |
65 | } |
66 | ||
67 | /// Helper used for fns and closures. Does the grungy work of checking a function | |
68 | /// body and returns the function context used for that purpose, since in the case of a fn item | |
69 | /// there is still a bit more to do. | |
70 | /// | |
71 | /// * ... | |
72 | /// * inherited: other fields inherited from the enclosing fn (if any) | |
73 | pub(super) fn check_fn<'a, 'tcx>( | |
74 | inherited: &'a Inherited<'a, 'tcx>, | |
75 | param_env: ty::ParamEnv<'tcx>, | |
76 | fn_sig: ty::FnSig<'tcx>, | |
77 | decl: &'tcx hir::FnDecl<'tcx>, | |
78 | fn_id: hir::HirId, | |
79 | body: &'tcx hir::Body<'tcx>, | |
80 | can_be_generator: Option<hir::Movability>, | |
81 | ) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) { | |
82 | let mut fn_sig = fn_sig; | |
83 | ||
84 | debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env); | |
85 | ||
86 | // Create the function context. This is either derived from scratch or, | |
87 | // in the case of closures, based on the outer context. | |
88 | let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); | |
5869c6ff | 89 | fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id)); |
1b1a35ee XL |
90 | |
91 | let tcx = fcx.tcx; | |
92 | let sess = tcx.sess; | |
93 | let hir = tcx.hir(); | |
94 | ||
95 | let declared_ret_ty = fn_sig.output(); | |
96 | ||
6a06907d XL |
97 | let feature = match tcx.hir().get(fn_id) { |
98 | // TAIT usage in function return position. | |
99 | // Example: | |
100 | // | |
101 | // ```rust | |
102 | // type Foo = impl Debug; | |
103 | // fn bar() -> Foo { 42 } | |
104 | // ``` | |
105 | Node::Item(hir::Item { kind: ItemKind::Fn(..), .. }) | | |
106 | // TAIT usage in associated function return position. | |
107 | // | |
108 | // Example with a free type alias: | |
109 | // | |
110 | // ```rust | |
111 | // type Foo = impl Debug; | |
112 | // impl SomeTrait for SomeType { | |
113 | // fn bar() -> Foo { 42 } | |
114 | // } | |
115 | // ``` | |
116 | // | |
117 | // Example with an associated TAIT: | |
118 | // | |
119 | // ```rust | |
120 | // impl SomeTrait for SomeType { | |
121 | // type Foo = impl Debug; | |
122 | // fn bar() -> Self::Foo { 42 } | |
123 | // } | |
124 | // ``` | |
125 | Node::ImplItem(hir::ImplItem { | |
126 | kind: hir::ImplItemKind::Fn(..), .. | |
127 | }) => None, | |
128 | // Forbid TAIT in trait declarations for now. | |
129 | // Examples: | |
130 | // | |
131 | // ```rust | |
132 | // type Foo = impl Debug; | |
133 | // trait Bar { | |
134 | // fn bar() -> Foo; | |
135 | // } | |
136 | // trait Bop { | |
137 | // type Bop: PartialEq<Foo>; | |
138 | // } | |
139 | // ``` | |
140 | Node::TraitItem(hir::TraitItem { | |
141 | kind: hir::TraitItemKind::Fn(..), | |
142 | .. | |
143 | }) | | |
144 | // Forbid TAIT in closure return position for now. | |
145 | // Example: | |
146 | // | |
147 | // ```rust | |
148 | // type Foo = impl Debug; | |
149 | // let x = |y| -> Foo { 42 + y }; | |
150 | // ``` | |
151 | Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => Some(sym::type_alias_impl_trait), | |
152 | node => bug!("Item being checked wasn't a function/closure: {:?}", node), | |
153 | }; | |
154 | let revealed_ret_ty = fcx.instantiate_opaque_types_from_value( | |
155 | fn_id, | |
156 | declared_ret_ty, | |
157 | decl.output.span(), | |
158 | feature, | |
159 | ); | |
1b1a35ee XL |
160 | debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty); |
161 | fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty))); | |
162 | fcx.ret_type_span = Some(decl.output.span()); | |
163 | if let ty::Opaque(..) = declared_ret_ty.kind() { | |
164 | fcx.ret_coercion_impl_trait = Some(declared_ret_ty); | |
165 | } | |
166 | fn_sig = tcx.mk_fn_sig( | |
167 | fn_sig.inputs().iter().cloned(), | |
168 | revealed_ret_ty, | |
169 | fn_sig.c_variadic, | |
170 | fn_sig.unsafety, | |
171 | fn_sig.abi, | |
172 | ); | |
173 | ||
174 | let span = body.value.span; | |
175 | ||
176 | fn_maybe_err(tcx, span, fn_sig.abi); | |
177 | ||
fc512014 XL |
178 | if fn_sig.abi == Abi::RustCall { |
179 | let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 }; | |
180 | ||
181 | let err = || { | |
182 | let item = match tcx.hir().get(fn_id) { | |
183 | Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header), | |
184 | Node::ImplItem(hir::ImplItem { | |
185 | kind: hir::ImplItemKind::Fn(header, ..), .. | |
186 | }) => Some(header), | |
5869c6ff XL |
187 | Node::TraitItem(hir::TraitItem { |
188 | kind: hir::TraitItemKind::Fn(header, ..), | |
189 | .. | |
190 | }) => Some(header), | |
fc512014 XL |
191 | // Closures are RustCall, but they tuple their arguments, so shouldn't be checked |
192 | Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None, | |
193 | node => bug!("Item being checked wasn't a function/closure: {:?}", node), | |
194 | }; | |
195 | ||
196 | if let Some(header) = item { | |
5869c6ff | 197 | tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple") |
fc512014 XL |
198 | } |
199 | }; | |
200 | ||
201 | if fn_sig.inputs().len() != expected_args { | |
202 | err() | |
203 | } else { | |
204 | // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on | |
205 | // This will probably require wide-scale changes to support a TupleKind obligation | |
206 | // We can't resolve this without knowing the type of the param | |
207 | if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) { | |
208 | err() | |
209 | } | |
210 | } | |
211 | } | |
212 | ||
1b1a35ee XL |
213 | if body.generator_kind.is_some() && can_be_generator.is_some() { |
214 | let yield_ty = fcx | |
215 | .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); | |
216 | fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType); | |
217 | ||
218 | // Resume type defaults to `()` if the generator has no argument. | |
219 | let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit()); | |
220 | ||
221 | fcx.resume_yield_tys = Some((resume_ty, yield_ty)); | |
222 | } | |
223 | ||
136023e0 | 224 | GatherLocalsVisitor::new(&fcx).visit_body(body); |
1b1a35ee XL |
225 | |
226 | // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` | |
227 | // (as it's created inside the body itself, not passed in from outside). | |
228 | let maybe_va_list = if fn_sig.c_variadic { | |
229 | let span = body.params.last().unwrap().span; | |
230 | let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span)); | |
231 | let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span)); | |
232 | ||
233 | Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()])) | |
234 | } else { | |
235 | None | |
236 | }; | |
237 | ||
238 | // Add formal parameters. | |
239 | let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs); | |
240 | let inputs_fn = fn_sig.inputs().iter().copied(); | |
241 | for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { | |
242 | // Check the pattern. | |
243 | let ty_span = try { inputs_hir?.get(idx)?.span }; | |
244 | fcx.check_pat_top(¶m.pat, param_ty, ty_span, false); | |
245 | ||
246 | // Check that argument is Sized. | |
247 | // The check for a non-trivial pattern is a hack to avoid duplicate warnings | |
248 | // for simple cases like `fn foo(x: Trait)`, | |
249 | // where we would error once on the parameter as a whole, and once on the binding `x`. | |
29967ef6 | 250 | if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params { |
1b1a35ee XL |
251 | fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span)); |
252 | } | |
253 | ||
254 | fcx.write_ty(param.hir_id, param_ty); | |
255 | } | |
256 | ||
257 | inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); | |
258 | ||
259 | fcx.in_tail_expr = true; | |
260 | if let ty::Dynamic(..) = declared_ret_ty.kind() { | |
261 | // FIXME: We need to verify that the return type is `Sized` after the return expression has | |
262 | // been evaluated so that we have types available for all the nodes being returned, but that | |
263 | // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this | |
264 | // causes unsized errors caused by the `declared_ret_ty` to point at the return expression, | |
265 | // while keeping the current ordering we will ignore the tail expression's type because we | |
266 | // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr` | |
267 | // because we will trigger "unreachable expression" lints unconditionally. | |
268 | // Because of all of this, we perform a crude check to know whether the simplest `!Sized` | |
269 | // case that a newcomer might make, returning a bare trait, and in that case we populate | |
270 | // the tail expression's type so that the suggestion will be correct, but ignore all other | |
271 | // possible cases. | |
272 | fcx.check_expr(&body.value); | |
273 | fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); | |
1b1a35ee XL |
274 | } else { |
275 | fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); | |
276 | fcx.check_return_expr(&body.value); | |
277 | } | |
278 | fcx.in_tail_expr = false; | |
279 | ||
280 | // We insert the deferred_generator_interiors entry after visiting the body. | |
281 | // This ensures that all nested generators appear before the entry of this generator. | |
282 | // resolve_generator_interiors relies on this property. | |
283 | let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) { | |
284 | let interior = fcx | |
285 | .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span }); | |
286 | fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind)); | |
287 | ||
288 | let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap(); | |
289 | Some(GeneratorTypes { | |
290 | resume_ty, | |
291 | yield_ty, | |
292 | interior, | |
293 | movability: can_be_generator.unwrap(), | |
294 | }) | |
295 | } else { | |
296 | None | |
297 | }; | |
298 | ||
299 | // Finalize the return check by taking the LUB of the return types | |
300 | // we saw and assigning it to the expected return type. This isn't | |
301 | // really expected to fail, since the coercions would have failed | |
302 | // earlier when trying to find a LUB. | |
303 | // | |
304 | // However, the behavior around `!` is sort of complex. In the | |
305 | // event that the `actual_return_ty` comes back as `!`, that | |
306 | // indicates that the fn either does not return or "returns" only | |
307 | // values of type `!`. In this case, if there is an expected | |
308 | // return type that is *not* `!`, that should be ok. But if the | |
309 | // return type is being inferred, we want to "fallback" to `!`: | |
310 | // | |
311 | // let x = move || panic!(); | |
312 | // | |
313 | // To allow for that, I am creating a type variable with diverging | |
314 | // fallback. This was deemed ever so slightly better than unifying | |
315 | // the return value with `!` because it allows for the caller to | |
316 | // make more assumptions about the return type (e.g., they could do | |
317 | // | |
318 | // let y: Option<u32> = Some(x()); | |
319 | // | |
320 | // which would then cause this return type to become `u32`, not | |
321 | // `!`). | |
322 | let coercion = fcx.ret_coercion.take().unwrap().into_inner(); | |
323 | let mut actual_return_ty = coercion.complete(&fcx); | |
324 | if actual_return_ty.is_never() { | |
325 | actual_return_ty = fcx.next_diverging_ty_var(TypeVariableOrigin { | |
326 | kind: TypeVariableOriginKind::DivergingFn, | |
327 | span, | |
328 | }); | |
329 | } | |
330 | fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty); | |
331 | ||
1b1a35ee XL |
332 | // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` |
333 | if let Some(panic_impl_did) = tcx.lang_items().panic_impl() { | |
334 | if panic_impl_did == hir.local_def_id(fn_id).to_def_id() { | |
335 | if let Some(panic_info_did) = tcx.lang_items().panic_info() { | |
336 | if *declared_ret_ty.kind() != ty::Never { | |
337 | sess.span_err(decl.output.span(), "return type should be `!`"); | |
338 | } | |
339 | ||
340 | let inputs = fn_sig.inputs(); | |
341 | let span = hir.span(fn_id); | |
342 | if inputs.len() == 1 { | |
343 | let arg_is_panic_info = match *inputs[0].kind() { | |
344 | ty::Ref(region, ty, mutbl) => match *ty.kind() { | |
345 | ty::Adt(ref adt, _) => { | |
346 | adt.did == panic_info_did | |
347 | && mutbl == hir::Mutability::Not | |
348 | && *region != RegionKind::ReStatic | |
349 | } | |
350 | _ => false, | |
351 | }, | |
352 | _ => false, | |
353 | }; | |
354 | ||
355 | if !arg_is_panic_info { | |
356 | sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); | |
357 | } | |
358 | ||
359 | if let Node::Item(item) = hir.get(fn_id) { | |
360 | if let ItemKind::Fn(_, ref generics, _) = item.kind { | |
361 | if !generics.params.is_empty() { | |
362 | sess.span_err(span, "should have no type parameters"); | |
363 | } | |
364 | } | |
365 | } | |
366 | } else { | |
367 | let span = sess.source_map().guess_head_span(span); | |
368 | sess.span_err(span, "function should have one argument"); | |
369 | } | |
370 | } else { | |
371 | sess.err("language item required, but not found: `panic_info`"); | |
372 | } | |
373 | } | |
374 | } | |
375 | ||
376 | // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !` | |
377 | if let Some(alloc_error_handler_did) = tcx.lang_items().oom() { | |
378 | if alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() { | |
379 | if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() { | |
380 | if *declared_ret_ty.kind() != ty::Never { | |
381 | sess.span_err(decl.output.span(), "return type should be `!`"); | |
382 | } | |
383 | ||
384 | let inputs = fn_sig.inputs(); | |
385 | let span = hir.span(fn_id); | |
386 | if inputs.len() == 1 { | |
387 | let arg_is_alloc_layout = match inputs[0].kind() { | |
388 | ty::Adt(ref adt, _) => adt.did == alloc_layout_did, | |
389 | _ => false, | |
390 | }; | |
391 | ||
392 | if !arg_is_alloc_layout { | |
393 | sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); | |
394 | } | |
395 | ||
396 | if let Node::Item(item) = hir.get(fn_id) { | |
397 | if let ItemKind::Fn(_, ref generics, _) = item.kind { | |
398 | if !generics.params.is_empty() { | |
399 | sess.span_err( | |
400 | span, | |
401 | "`#[alloc_error_handler]` function should have no type \ | |
402 | parameters", | |
403 | ); | |
404 | } | |
405 | } | |
406 | } | |
407 | } else { | |
408 | let span = sess.source_map().guess_head_span(span); | |
409 | sess.span_err(span, "function should have one argument"); | |
410 | } | |
411 | } else { | |
412 | sess.err("language item required, but not found: `alloc_layout`"); | |
413 | } | |
414 | } | |
415 | } | |
416 | ||
417 | (fcx, gen_ty) | |
418 | } | |
419 | ||
6a06907d | 420 | fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { |
1b1a35ee XL |
421 | let def = tcx.adt_def(def_id); |
422 | def.destructor(tcx); // force the destructor to be evaluated | |
423 | check_representable(tcx, span, def_id); | |
424 | ||
425 | if def.repr.simd() { | |
426 | check_simd(tcx, span, def_id); | |
427 | } | |
428 | ||
429 | check_transparent(tcx, span, def); | |
430 | check_packed(tcx, span, def); | |
431 | } | |
432 | ||
6a06907d | 433 | fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { |
1b1a35ee XL |
434 | let def = tcx.adt_def(def_id); |
435 | def.destructor(tcx); // force the destructor to be evaluated | |
436 | check_representable(tcx, span, def_id); | |
437 | check_transparent(tcx, span, def); | |
438 | check_union_fields(tcx, span, def_id); | |
439 | check_packed(tcx, span, def); | |
440 | } | |
441 | ||
29967ef6 XL |
442 | /// Check that the fields of the `union` do not need dropping. |
443 | fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool { | |
1b1a35ee XL |
444 | let item_type = tcx.type_of(item_def_id); |
445 | if let ty::Adt(def, substs) = item_type.kind() { | |
446 | assert!(def.is_union()); | |
447 | let fields = &def.non_enum_variant().fields; | |
448 | let param_env = tcx.param_env(item_def_id); | |
449 | for field in fields { | |
450 | let field_ty = field.ty(tcx, substs); | |
451 | // We are currently checking the type this field came from, so it must be local. | |
452 | let field_span = tcx.hir().span_if_local(field.did).unwrap(); | |
453 | if field_ty.needs_drop(tcx, param_env) { | |
454 | struct_span_err!( | |
455 | tcx.sess, | |
456 | field_span, | |
457 | E0740, | |
458 | "unions may not contain fields that need dropping" | |
459 | ) | |
460 | .span_note(field_span, "`std::mem::ManuallyDrop` can be used to wrap the type") | |
461 | .emit(); | |
462 | return false; | |
463 | } | |
464 | } | |
465 | } else { | |
466 | span_bug!(span, "unions must be ty::Adt, but got {:?}", item_type.kind()); | |
467 | } | |
468 | true | |
469 | } | |
470 | ||
29967ef6 XL |
471 | /// Check that a `static` is inhabited. |
472 | fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { | |
473 | // Make sure statics are inhabited. | |
474 | // Other parts of the compiler assume that there are no uninhabited places. In principle it | |
475 | // would be enough to check this for `extern` statics, as statics with an initializer will | |
476 | // have UB during initialization if they are uninhabited, but there also seems to be no good | |
477 | // reason to allow any statics to be uninhabited. | |
478 | let ty = tcx.type_of(def_id); | |
479 | let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) { | |
480 | Ok(l) => l, | |
481 | Err(_) => { | |
482 | // Generic statics are rejected, but we still reach this case. | |
483 | tcx.sess.delay_span_bug(span, "generic static must be rejected"); | |
484 | return; | |
485 | } | |
486 | }; | |
487 | if layout.abi.is_uninhabited() { | |
488 | tcx.struct_span_lint_hir( | |
489 | UNINHABITED_STATIC, | |
490 | tcx.hir().local_def_id_to_hir_id(def_id), | |
491 | span, | |
492 | |lint| { | |
493 | lint.build("static of uninhabited type") | |
494 | .note("uninhabited statics cannot be initialized, and any access would be an immediate error") | |
495 | .emit(); | |
496 | }, | |
497 | ); | |
498 | } | |
499 | } | |
500 | ||
1b1a35ee XL |
501 | /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` |
502 | /// projections that would result in "inheriting lifetimes". | |
503 | pub(super) fn check_opaque<'tcx>( | |
504 | tcx: TyCtxt<'tcx>, | |
505 | def_id: LocalDefId, | |
506 | substs: SubstsRef<'tcx>, | |
507 | span: Span, | |
508 | origin: &hir::OpaqueTyOrigin, | |
509 | ) { | |
510 | check_opaque_for_inheriting_lifetimes(tcx, def_id, span); | |
29967ef6 XL |
511 | if tcx.type_of(def_id).references_error() { |
512 | return; | |
513 | } | |
514 | if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() { | |
515 | return; | |
516 | } | |
517 | check_opaque_meets_bounds(tcx, def_id, substs, span, origin); | |
1b1a35ee XL |
518 | } |
519 | ||
520 | /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result | |
521 | /// in "inheriting lifetimes". | |
6a06907d | 522 | #[instrument(level = "debug", skip(tcx, span))] |
1b1a35ee XL |
523 | pub(super) fn check_opaque_for_inheriting_lifetimes( |
524 | tcx: TyCtxt<'tcx>, | |
525 | def_id: LocalDefId, | |
526 | span: Span, | |
527 | ) { | |
528 | let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id)); | |
fc512014 | 529 | debug!(?item, ?span); |
1b1a35ee | 530 | |
fc512014 XL |
531 | struct FoundParentLifetime; |
532 | struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics); | |
533 | impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> { | |
534 | type BreakTy = FoundParentLifetime; | |
1b1a35ee | 535 | |
fc512014 XL |
536 | fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { |
537 | debug!("FindParentLifetimeVisitor: r={:?}", r); | |
1b1a35ee | 538 | if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r { |
fc512014 XL |
539 | if *index < self.0.parent_count as u32 { |
540 | return ControlFlow::Break(FoundParentLifetime); | |
29967ef6 XL |
541 | } else { |
542 | return ControlFlow::CONTINUE; | |
543 | } | |
1b1a35ee XL |
544 | } |
545 | ||
546 | r.super_visit_with(self) | |
547 | } | |
548 | ||
fc512014 | 549 | fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { |
1b1a35ee | 550 | if let ty::ConstKind::Unevaluated(..) = c.val { |
fc512014 | 551 | // FIXME(#72219) We currently don't detect lifetimes within substs |
1b1a35ee XL |
552 | // which would violate this check. Even though the particular substitution is not used |
553 | // within the const, this should still be fixed. | |
29967ef6 | 554 | return ControlFlow::CONTINUE; |
1b1a35ee XL |
555 | } |
556 | c.super_visit_with(self) | |
557 | } | |
558 | } | |
559 | ||
fc512014 XL |
560 | struct ProhibitOpaqueVisitor<'tcx> { |
561 | opaque_identity_ty: Ty<'tcx>, | |
562 | generics: &'tcx ty::Generics, | |
6a06907d XL |
563 | tcx: TyCtxt<'tcx>, |
564 | selftys: Vec<(Span, Option<String>)>, | |
fc512014 XL |
565 | } |
566 | ||
567 | impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { | |
568 | type BreakTy = Ty<'tcx>; | |
569 | ||
570 | fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { | |
571 | debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); | |
572 | if t == self.opaque_identity_ty { | |
573 | ControlFlow::CONTINUE | |
574 | } else { | |
575 | t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics)) | |
576 | .map_break(|FoundParentLifetime| t) | |
577 | } | |
578 | } | |
579 | } | |
580 | ||
6a06907d XL |
581 | impl Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { |
582 | type Map = rustc_middle::hir::map::Map<'tcx>; | |
583 | ||
584 | fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> { | |
585 | hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir()) | |
586 | } | |
587 | ||
588 | fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { | |
589 | match arg.kind { | |
590 | hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { | |
591 | [PathSegment { res: Some(Res::SelfTy(_, impl_ref)), .. }] => { | |
592 | let impl_ty_name = | |
593 | impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id)); | |
594 | self.selftys.push((path.span, impl_ty_name)); | |
595 | } | |
596 | _ => {} | |
597 | }, | |
598 | _ => {} | |
599 | } | |
600 | hir::intravisit::walk_ty(self, arg); | |
601 | } | |
602 | } | |
603 | ||
1b1a35ee XL |
604 | if let ItemKind::OpaqueTy(hir::OpaqueTy { |
605 | origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, | |
606 | .. | |
607 | }) = item.kind | |
608 | { | |
609 | let mut visitor = ProhibitOpaqueVisitor { | |
610 | opaque_identity_ty: tcx.mk_opaque( | |
611 | def_id.to_def_id(), | |
612 | InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), | |
613 | ), | |
614 | generics: tcx.generics_of(def_id), | |
6a06907d XL |
615 | tcx, |
616 | selftys: vec![], | |
1b1a35ee XL |
617 | }; |
618 | let prohibit_opaque = tcx | |
29967ef6 | 619 | .explicit_item_bounds(def_id) |
1b1a35ee | 620 | .iter() |
fc512014 | 621 | .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); |
1b1a35ee | 622 | debug!( |
6a06907d XL |
623 | "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor.opaque_identity_ty={:?}, visitor.generics={:?}", |
624 | prohibit_opaque, visitor.opaque_identity_ty, visitor.generics | |
1b1a35ee XL |
625 | ); |
626 | ||
fc512014 | 627 | if let Some(ty) = prohibit_opaque.break_value() { |
6a06907d | 628 | visitor.visit_item(&item); |
1b1a35ee | 629 | let is_async = match item.kind { |
5869c6ff XL |
630 | ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { |
631 | matches!(origin, hir::OpaqueTyOrigin::AsyncFn) | |
632 | } | |
1b1a35ee XL |
633 | _ => unreachable!(), |
634 | }; | |
635 | ||
636 | let mut err = struct_span_err!( | |
637 | tcx.sess, | |
638 | span, | |
639 | E0760, | |
640 | "`{}` return type cannot contain a projection or `Self` that references lifetimes from \ | |
29967ef6 | 641 | a parent scope", |
1b1a35ee XL |
642 | if is_async { "async fn" } else { "impl Trait" }, |
643 | ); | |
644 | ||
6a06907d XL |
645 | for (span, name) in visitor.selftys { |
646 | err.span_suggestion( | |
647 | span, | |
648 | "consider spelling out the type instead", | |
649 | name.unwrap_or_else(|| format!("{:?}", ty)), | |
650 | Applicability::MaybeIncorrect, | |
651 | ); | |
1b1a35ee XL |
652 | } |
653 | err.emit(); | |
654 | } | |
655 | } | |
656 | } | |
657 | ||
658 | /// Checks that an opaque type does not contain cycles. | |
659 | pub(super) fn check_opaque_for_cycles<'tcx>( | |
660 | tcx: TyCtxt<'tcx>, | |
661 | def_id: LocalDefId, | |
662 | substs: SubstsRef<'tcx>, | |
663 | span: Span, | |
664 | origin: &hir::OpaqueTyOrigin, | |
29967ef6 | 665 | ) -> Result<(), ErrorReported> { |
136023e0 | 666 | if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { |
1b1a35ee XL |
667 | match origin { |
668 | hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span), | |
1b1a35ee XL |
669 | _ => opaque_type_cycle_error(tcx, def_id, span), |
670 | } | |
29967ef6 XL |
671 | Err(ErrorReported) |
672 | } else { | |
673 | Ok(()) | |
1b1a35ee XL |
674 | } |
675 | } | |
676 | ||
29967ef6 XL |
677 | /// Check that the concrete type behind `impl Trait` actually implements `Trait`. |
678 | /// | |
679 | /// This is mostly checked at the places that specify the opaque type, but we | |
680 | /// check those cases in the `param_env` of that function, which may have | |
681 | /// bounds not on this opaque type: | |
682 | /// | |
683 | /// type X<T> = impl Clone | |
684 | /// fn f<T: Clone>(t: T) -> X<T> { | |
685 | /// t | |
686 | /// } | |
687 | /// | |
688 | /// Without this check the above code is incorrectly accepted: we would ICE if | |
689 | /// some tried, for example, to clone an `Option<X<&mut ()>>`. | |
690 | fn check_opaque_meets_bounds<'tcx>( | |
691 | tcx: TyCtxt<'tcx>, | |
692 | def_id: LocalDefId, | |
693 | substs: SubstsRef<'tcx>, | |
694 | span: Span, | |
695 | origin: &hir::OpaqueTyOrigin, | |
696 | ) { | |
697 | match origin { | |
698 | // Checked when type checking the function containing them. | |
699 | hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, | |
700 | // Can have different predicates to their defining use | |
136023e0 | 701 | hir::OpaqueTyOrigin::TyAlias => {} |
29967ef6 XL |
702 | } |
703 | ||
704 | let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); | |
705 | let param_env = tcx.param_env(def_id); | |
706 | ||
707 | tcx.infer_ctxt().enter(move |infcx| { | |
708 | let inh = Inherited::new(infcx, def_id); | |
709 | let infcx = &inh.infcx; | |
710 | let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); | |
711 | ||
712 | let misc_cause = traits::ObligationCause::misc(span, hir_id); | |
713 | ||
714 | let (_, opaque_type_map) = inh.register_infer_ok_obligations( | |
fc512014 | 715 | infcx.instantiate_opaque_types(def_id, hir_id, param_env, opaque_ty, span), |
29967ef6 XL |
716 | ); |
717 | ||
17df50a5 | 718 | for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map { |
29967ef6 XL |
719 | match infcx |
720 | .at(&misc_cause, param_env) | |
17df50a5 | 721 | .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, substs)) |
29967ef6 XL |
722 | { |
723 | Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), | |
724 | Err(ty_err) => tcx.sess.delay_span_bug( | |
725 | opaque_defn.definition_span, | |
726 | &format!( | |
727 | "could not unify `{}` with revealed type:\n{}", | |
728 | opaque_defn.concrete_ty, ty_err, | |
729 | ), | |
730 | ), | |
731 | } | |
732 | } | |
733 | ||
734 | // Check that all obligations are satisfied by the implementation's | |
735 | // version. | |
736 | if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { | |
737 | infcx.report_fulfillment_errors(errors, None, false); | |
738 | } | |
739 | ||
740 | // Finally, resolve all regions. This catches wily misuses of | |
741 | // lifetime parameters. | |
742 | let fcx = FnCtxt::new(&inh, param_env, hir_id); | |
743 | fcx.regionck_item(hir_id, span, &[]); | |
744 | }); | |
745 | } | |
746 | ||
1b1a35ee XL |
747 | pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { |
748 | debug!( | |
6a06907d XL |
749 | "check_item_type(it.def_id={:?}, it.name={})", |
750 | it.def_id, | |
751 | tcx.def_path_str(it.def_id.to_def_id()) | |
1b1a35ee XL |
752 | ); |
753 | let _indenter = indenter(); | |
754 | match it.kind { | |
755 | // Consts can play a role in type-checking, so they are included here. | |
756 | hir::ItemKind::Static(..) => { | |
6a06907d XL |
757 | tcx.ensure().typeck(it.def_id); |
758 | maybe_check_static_with_link_section(tcx, it.def_id, it.span); | |
759 | check_static_inhabited(tcx, it.def_id, it.span); | |
1b1a35ee XL |
760 | } |
761 | hir::ItemKind::Const(..) => { | |
6a06907d | 762 | tcx.ensure().typeck(it.def_id); |
1b1a35ee XL |
763 | } |
764 | hir::ItemKind::Enum(ref enum_definition, _) => { | |
6a06907d | 765 | check_enum(tcx, it.span, &enum_definition.variants, it.def_id); |
1b1a35ee XL |
766 | } |
767 | hir::ItemKind::Fn(..) => {} // entirely within check_item_body | |
5869c6ff | 768 | hir::ItemKind::Impl(ref impl_) => { |
6a06907d XL |
769 | debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id); |
770 | if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) { | |
5869c6ff XL |
771 | check_impl_items_against_trait( |
772 | tcx, | |
773 | it.span, | |
6a06907d | 774 | it.def_id, |
5869c6ff XL |
775 | impl_trait_ref, |
776 | &impl_.items, | |
777 | ); | |
1b1a35ee XL |
778 | let trait_def_id = impl_trait_ref.def_id; |
779 | check_on_unimplemented(tcx, trait_def_id, it); | |
780 | } | |
781 | } | |
782 | hir::ItemKind::Trait(_, _, _, _, ref items) => { | |
6a06907d | 783 | check_on_unimplemented(tcx, it.def_id.to_def_id(), it); |
1b1a35ee XL |
784 | |
785 | for item in items.iter() { | |
786 | let item = tcx.hir().trait_item(item.id); | |
29967ef6 XL |
787 | match item.kind { |
788 | hir::TraitItemKind::Fn(ref sig, _) => { | |
789 | let abi = sig.header.abi; | |
790 | fn_maybe_err(tcx, item.ident.span, abi); | |
791 | } | |
792 | hir::TraitItemKind::Type(.., Some(_default)) => { | |
6a06907d | 793 | let assoc_item = tcx.associated_item(item.def_id); |
29967ef6 | 794 | let trait_substs = |
6a06907d | 795 | InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); |
29967ef6 XL |
796 | let _: Result<_, rustc_errors::ErrorReported> = check_type_bounds( |
797 | tcx, | |
798 | assoc_item, | |
799 | assoc_item, | |
800 | item.span, | |
6a06907d | 801 | ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs }, |
29967ef6 XL |
802 | ); |
803 | } | |
804 | _ => {} | |
1b1a35ee XL |
805 | } |
806 | } | |
807 | } | |
808 | hir::ItemKind::Struct(..) => { | |
6a06907d | 809 | check_struct(tcx, it.def_id, it.span); |
1b1a35ee XL |
810 | } |
811 | hir::ItemKind::Union(..) => { | |
6a06907d | 812 | check_union(tcx, it.def_id, it.span); |
1b1a35ee XL |
813 | } |
814 | hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { | |
815 | // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting | |
816 | // `async-std` (and `pub async fn` in general). | |
817 | // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it! | |
818 | // See https://github.com/rust-lang/rust/issues/75100 | |
819 | if !tcx.sess.opts.actually_rustdoc { | |
6a06907d XL |
820 | let substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); |
821 | check_opaque(tcx, it.def_id, substs, it.span, &origin); | |
1b1a35ee XL |
822 | } |
823 | } | |
824 | hir::ItemKind::TyAlias(..) => { | |
6a06907d XL |
825 | let pty_ty = tcx.type_of(it.def_id); |
826 | let generics = tcx.generics_of(it.def_id); | |
1b1a35ee XL |
827 | check_type_params_are_used(tcx, &generics, pty_ty); |
828 | } | |
fc512014 | 829 | hir::ItemKind::ForeignMod { abi, items } => { |
136023e0 | 830 | check_abi(tcx, it.hir_id(), it.span, abi); |
1b1a35ee | 831 | |
fc512014 XL |
832 | if abi == Abi::RustIntrinsic { |
833 | for item in items { | |
834 | let item = tcx.hir().foreign_item(item.id); | |
1b1a35ee XL |
835 | intrinsic::check_intrinsic_type(tcx, item); |
836 | } | |
fc512014 XL |
837 | } else if abi == Abi::PlatformIntrinsic { |
838 | for item in items { | |
839 | let item = tcx.hir().foreign_item(item.id); | |
1b1a35ee XL |
840 | intrinsic::check_platform_intrinsic_type(tcx, item); |
841 | } | |
842 | } else { | |
fc512014 | 843 | for item in items { |
6a06907d | 844 | let def_id = item.id.def_id; |
29967ef6 | 845 | let generics = tcx.generics_of(def_id); |
1b1a35ee XL |
846 | let own_counts = generics.own_counts(); |
847 | if generics.params.len() - own_counts.lifetimes != 0 { | |
848 | let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) { | |
849 | (_, 0) => ("type", "types", Some("u32")), | |
850 | // We don't specify an example value, because we can't generate | |
851 | // a valid value for any type. | |
852 | (0, _) => ("const", "consts", None), | |
853 | _ => ("type or const", "types or consts", None), | |
854 | }; | |
855 | struct_span_err!( | |
856 | tcx.sess, | |
857 | item.span, | |
858 | E0044, | |
859 | "foreign items may not have {} parameters", | |
860 | kinds, | |
861 | ) | |
862 | .span_label(item.span, &format!("can't have {} parameters", kinds)) | |
863 | .help( | |
864 | // FIXME: once we start storing spans for type arguments, turn this | |
865 | // into a suggestion. | |
866 | &format!( | |
867 | "replace the {} parameters with concrete {}{}", | |
868 | kinds, | |
869 | kinds_pl, | |
870 | egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(), | |
871 | ), | |
872 | ) | |
873 | .emit(); | |
874 | } | |
875 | ||
fc512014 | 876 | let item = tcx.hir().foreign_item(item.id); |
29967ef6 XL |
877 | match item.kind { |
878 | hir::ForeignItemKind::Fn(ref fn_decl, _, _) => { | |
fc512014 | 879 | require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span); |
29967ef6 XL |
880 | } |
881 | hir::ForeignItemKind::Static(..) => { | |
882 | check_static_inhabited(tcx, def_id, item.span); | |
883 | } | |
884 | _ => {} | |
1b1a35ee XL |
885 | } |
886 | } | |
887 | } | |
888 | } | |
889 | _ => { /* nothing to do */ } | |
890 | } | |
891 | } | |
892 | ||
893 | pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item<'_>) { | |
1b1a35ee | 894 | // an error would be reported if this fails. |
6a06907d | 895 | let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item.def_id.to_def_id()); |
1b1a35ee XL |
896 | } |
897 | ||
898 | pub(super) fn check_specialization_validity<'tcx>( | |
899 | tcx: TyCtxt<'tcx>, | |
900 | trait_def: &ty::TraitDef, | |
901 | trait_item: &ty::AssocItem, | |
902 | impl_id: DefId, | |
903 | impl_item: &hir::ImplItem<'_>, | |
904 | ) { | |
905 | let kind = match impl_item.kind { | |
906 | hir::ImplItemKind::Const(..) => ty::AssocKind::Const, | |
907 | hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn, | |
908 | hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type, | |
909 | }; | |
910 | ||
911 | let ancestors = match trait_def.ancestors(tcx, impl_id) { | |
912 | Ok(ancestors) => ancestors, | |
913 | Err(_) => return, | |
914 | }; | |
5869c6ff XL |
915 | let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| { |
916 | if parent.is_from_trait() { | |
917 | None | |
918 | } else { | |
919 | Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id))) | |
920 | } | |
921 | }); | |
1b1a35ee XL |
922 | |
923 | let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| { | |
924 | match parent_item { | |
925 | // Parent impl exists, and contains the parent item we're trying to specialize, but | |
926 | // doesn't mark it `default`. | |
927 | Some(parent_item) if traits::impl_item_is_final(tcx, &parent_item) => { | |
928 | Some(Err(parent_impl.def_id())) | |
929 | } | |
930 | ||
931 | // Parent impl contains item and makes it specializable. | |
932 | Some(_) => Some(Ok(())), | |
933 | ||
934 | // Parent impl doesn't mention the item. This means it's inherited from the | |
935 | // grandparent. In that case, if parent is a `default impl`, inherited items use the | |
936 | // "defaultness" from the grandparent, else they are final. | |
937 | None => { | |
938 | if tcx.impl_defaultness(parent_impl.def_id()).is_default() { | |
939 | None | |
940 | } else { | |
941 | Some(Err(parent_impl.def_id())) | |
942 | } | |
943 | } | |
944 | } | |
945 | }); | |
946 | ||
947 | // If `opt_result` is `None`, we have only encountered `default impl`s that don't contain the | |
948 | // item. This is allowed, the item isn't actually getting specialized here. | |
949 | let result = opt_result.unwrap_or(Ok(())); | |
950 | ||
951 | if let Err(parent_impl) = result { | |
952 | report_forbidden_specialization(tcx, impl_item, parent_impl); | |
953 | } | |
954 | } | |
955 | ||
956 | pub(super) fn check_impl_items_against_trait<'tcx>( | |
957 | tcx: TyCtxt<'tcx>, | |
958 | full_impl_span: Span, | |
959 | impl_id: LocalDefId, | |
960 | impl_trait_ref: ty::TraitRef<'tcx>, | |
961 | impl_item_refs: &[hir::ImplItemRef<'_>], | |
962 | ) { | |
1b1a35ee XL |
963 | // If the trait reference itself is erroneous (so the compilation is going |
964 | // to fail), skip checking the items here -- the `impl_item` table in `tcx` | |
965 | // isn't populated for such impls. | |
966 | if impl_trait_ref.references_error() { | |
967 | return; | |
968 | } | |
969 | ||
970 | // Negative impls are not expected to have any items | |
971 | match tcx.impl_polarity(impl_id) { | |
972 | ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {} | |
973 | ty::ImplPolarity::Negative => { | |
974 | if let [first_item_ref, ..] = impl_item_refs { | |
975 | let first_item_span = tcx.hir().impl_item(first_item_ref.id).span; | |
976 | struct_span_err!( | |
977 | tcx.sess, | |
978 | first_item_span, | |
979 | E0749, | |
980 | "negative impls cannot have any items" | |
981 | ) | |
982 | .emit(); | |
983 | } | |
984 | return; | |
985 | } | |
986 | } | |
987 | ||
988 | // Locate trait definition and items | |
989 | let trait_def = tcx.trait_def(impl_trait_ref.def_id); | |
5869c6ff XL |
990 | let impl_items = impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id)); |
991 | let associated_items = tcx.associated_items(impl_trait_ref.def_id); | |
1b1a35ee XL |
992 | |
993 | // Check existing impl methods to see if they are both present in trait | |
994 | // and compatible with trait signature | |
5869c6ff | 995 | for impl_item in impl_items { |
6a06907d | 996 | let ty_impl_item = tcx.associated_item(impl_item.def_id); |
5869c6ff XL |
997 | |
998 | let mut items = | |
999 | associated_items.filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id); | |
1000 | ||
1001 | let (compatible_kind, ty_trait_item) = if let Some(ty_trait_item) = items.next() { | |
1002 | let is_compatible = |ty: &&ty::AssocItem| match (ty.kind, &impl_item.kind) { | |
1003 | (ty::AssocKind::Const, hir::ImplItemKind::Const(..)) => true, | |
1004 | (ty::AssocKind::Fn, hir::ImplItemKind::Fn(..)) => true, | |
1005 | (ty::AssocKind::Type, hir::ImplItemKind::TyAlias(..)) => true, | |
1006 | _ => false, | |
1007 | }; | |
1008 | ||
1009 | // If we don't have a compatible item, we'll use the first one whose name matches | |
1010 | // to report an error. | |
1011 | let mut compatible_kind = is_compatible(&ty_trait_item); | |
1012 | let mut trait_item = ty_trait_item; | |
1013 | ||
1014 | if !compatible_kind { | |
1015 | if let Some(ty_trait_item) = items.find(is_compatible) { | |
1016 | compatible_kind = true; | |
1017 | trait_item = ty_trait_item; | |
1018 | } | |
1019 | } | |
1020 | ||
1021 | (compatible_kind, trait_item) | |
1022 | } else { | |
1023 | continue; | |
1024 | }; | |
1025 | ||
1026 | if compatible_kind { | |
1b1a35ee XL |
1027 | match impl_item.kind { |
1028 | hir::ImplItemKind::Const(..) => { | |
1029 | // Find associated const definition. | |
5869c6ff XL |
1030 | compare_const_impl( |
1031 | tcx, | |
1032 | &ty_impl_item, | |
1033 | impl_item.span, | |
1034 | &ty_trait_item, | |
1035 | impl_trait_ref, | |
1036 | ); | |
1b1a35ee XL |
1037 | } |
1038 | hir::ImplItemKind::Fn(..) => { | |
1039 | let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); | |
5869c6ff XL |
1040 | compare_impl_method( |
1041 | tcx, | |
1042 | &ty_impl_item, | |
1043 | impl_item.span, | |
1044 | &ty_trait_item, | |
1045 | impl_trait_ref, | |
1046 | opt_trait_span, | |
1047 | ); | |
1b1a35ee XL |
1048 | } |
1049 | hir::ImplItemKind::TyAlias(_) => { | |
1050 | let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); | |
5869c6ff XL |
1051 | compare_ty_impl( |
1052 | tcx, | |
1053 | &ty_impl_item, | |
1054 | impl_item.span, | |
1055 | &ty_trait_item, | |
1056 | impl_trait_ref, | |
1057 | opt_trait_span, | |
1058 | ); | |
1b1a35ee XL |
1059 | } |
1060 | } | |
1061 | ||
1062 | check_specialization_validity( | |
1063 | tcx, | |
1064 | trait_def, | |
1065 | &ty_trait_item, | |
1066 | impl_id.to_def_id(), | |
1067 | impl_item, | |
1068 | ); | |
5869c6ff XL |
1069 | } else { |
1070 | report_mismatch_error( | |
1071 | tcx, | |
1072 | ty_trait_item.def_id, | |
1073 | impl_trait_ref, | |
1074 | impl_item, | |
1075 | &ty_impl_item, | |
1076 | ); | |
1b1a35ee XL |
1077 | } |
1078 | } | |
1079 | ||
1b1a35ee | 1080 | if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) { |
5869c6ff XL |
1081 | let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); |
1082 | ||
1083 | // Check for missing items from trait | |
1084 | let mut missing_items = Vec::new(); | |
1b1a35ee XL |
1085 | for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { |
1086 | let is_implemented = ancestors | |
1087 | .leaf_def(tcx, trait_item.ident, trait_item.kind) | |
1088 | .map(|node_item| !node_item.defining_node.is_from_trait()) | |
1089 | .unwrap_or(false); | |
1090 | ||
1091 | if !is_implemented && tcx.impl_defaultness(impl_id).is_final() { | |
1092 | if !trait_item.defaultness.has_value() { | |
1093 | missing_items.push(*trait_item); | |
1094 | } | |
1095 | } | |
1096 | } | |
5869c6ff XL |
1097 | |
1098 | if !missing_items.is_empty() { | |
1099 | missing_items_err(tcx, impl_span, &missing_items, full_impl_span); | |
1100 | } | |
1b1a35ee | 1101 | } |
5869c6ff | 1102 | } |
1b1a35ee | 1103 | |
5869c6ff XL |
1104 | #[inline(never)] |
1105 | #[cold] | |
1106 | fn report_mismatch_error<'tcx>( | |
1107 | tcx: TyCtxt<'tcx>, | |
1108 | trait_item_def_id: DefId, | |
1109 | impl_trait_ref: ty::TraitRef<'tcx>, | |
1110 | impl_item: &hir::ImplItem<'_>, | |
1111 | ty_impl_item: &ty::AssocItem, | |
1112 | ) { | |
1113 | let mut err = match impl_item.kind { | |
1114 | hir::ImplItemKind::Const(..) => { | |
1115 | // Find associated const definition. | |
1116 | struct_span_err!( | |
1117 | tcx.sess, | |
1118 | impl_item.span, | |
1119 | E0323, | |
1120 | "item `{}` is an associated const, which doesn't match its trait `{}`", | |
1121 | ty_impl_item.ident, | |
1122 | impl_trait_ref.print_only_trait_path() | |
1123 | ) | |
1124 | } | |
1125 | ||
1126 | hir::ImplItemKind::Fn(..) => { | |
1127 | struct_span_err!( | |
1128 | tcx.sess, | |
1129 | impl_item.span, | |
1130 | E0324, | |
1131 | "item `{}` is an associated method, which doesn't match its trait `{}`", | |
1132 | ty_impl_item.ident, | |
1133 | impl_trait_ref.print_only_trait_path() | |
1134 | ) | |
1135 | } | |
1136 | ||
1137 | hir::ImplItemKind::TyAlias(_) => { | |
1138 | struct_span_err!( | |
1139 | tcx.sess, | |
1140 | impl_item.span, | |
1141 | E0325, | |
1142 | "item `{}` is an associated type, which doesn't match its trait `{}`", | |
1143 | ty_impl_item.ident, | |
1144 | impl_trait_ref.print_only_trait_path() | |
1145 | ) | |
1146 | } | |
1147 | }; | |
1148 | ||
1149 | err.span_label(impl_item.span, "does not match trait"); | |
1150 | if let Some(trait_span) = tcx.hir().span_if_local(trait_item_def_id) { | |
1151 | err.span_label(trait_span, "item in trait"); | |
1b1a35ee | 1152 | } |
5869c6ff | 1153 | err.emit(); |
1b1a35ee XL |
1154 | } |
1155 | ||
1156 | /// Checks whether a type can be represented in memory. In particular, it | |
1157 | /// identifies types that contain themselves without indirection through a | |
1158 | /// pointer, which would mean their size is unbounded. | |
1159 | pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bool { | |
1160 | let rty = tcx.type_of(item_def_id); | |
1161 | ||
1162 | // Check that it is possible to represent this type. This call identifies | |
1163 | // (1) types that contain themselves and (2) types that contain a different | |
1164 | // recursive type. It is only necessary to throw an error on those that | |
1165 | // contain themselves. For case 2, there must be an inner type that will be | |
1166 | // caught by case 1. | |
cdc7bbd5 | 1167 | match representability::ty_is_representable(tcx, rty, sp) { |
1b1a35ee XL |
1168 | Representability::SelfRecursive(spans) => { |
1169 | recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans); | |
1170 | return false; | |
1171 | } | |
1172 | Representability::Representable | Representability::ContainsRecursive => (), | |
1173 | } | |
1174 | true | |
1175 | } | |
1176 | ||
1177 | pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { | |
1178 | let t = tcx.type_of(def_id); | |
1179 | if let ty::Adt(def, substs) = t.kind() { | |
1180 | if def.is_struct() { | |
1181 | let fields = &def.non_enum_variant().fields; | |
1182 | if fields.is_empty() { | |
1183 | struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit(); | |
1184 | return; | |
1185 | } | |
1186 | let e = fields[0].ty(tcx, substs); | |
1187 | if !fields.iter().all(|f| f.ty(tcx, substs) == e) { | |
1188 | struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous") | |
1189 | .span_label(sp, "SIMD elements must have the same type") | |
1190 | .emit(); | |
1191 | return; | |
1192 | } | |
6a06907d XL |
1193 | |
1194 | let len = if let ty::Array(_ty, c) = e.kind() { | |
1195 | c.try_eval_usize(tcx, tcx.param_env(def.did)) | |
1196 | } else { | |
1197 | Some(fields.len() as u64) | |
1198 | }; | |
1199 | if let Some(len) = len { | |
1200 | if len == 0 { | |
1201 | struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit(); | |
1202 | return; | |
1203 | } else if len > MAX_SIMD_LANES { | |
1204 | struct_span_err!( | |
1205 | tcx.sess, | |
1206 | sp, | |
1207 | E0075, | |
1208 | "SIMD vector cannot have more than {} elements", | |
1209 | MAX_SIMD_LANES, | |
1210 | ) | |
1211 | .emit(); | |
1212 | return; | |
1213 | } | |
1214 | } | |
1215 | ||
17df50a5 XL |
1216 | // Check that we use types valid for use in the lanes of a SIMD "vector register" |
1217 | // These are scalar types which directly match a "machine" type | |
1218 | // Yes: Integers, floats, "thin" pointers | |
1219 | // No: char, "fat" pointers, compound types | |
1b1a35ee | 1220 | match e.kind() { |
17df50a5 XL |
1221 | ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors |
1222 | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok | |
1223 | ty::Array(t, _clen) | |
1224 | if matches!( | |
1225 | t.kind(), | |
1226 | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) | |
1227 | ) => | |
1228 | { /* struct([f32; 4]) is ok */ } | |
1b1a35ee XL |
1229 | _ => { |
1230 | struct_span_err!( | |
1231 | tcx.sess, | |
1232 | sp, | |
1233 | E0077, | |
fc512014 XL |
1234 | "SIMD vector element type should be a \ |
1235 | primitive scalar (integer/float/pointer) type" | |
1b1a35ee XL |
1236 | ) |
1237 | .emit(); | |
1238 | return; | |
1239 | } | |
1240 | } | |
1241 | } | |
1242 | } | |
1243 | } | |
1244 | ||
1245 | pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) { | |
1246 | let repr = def.repr; | |
1247 | if repr.packed() { | |
1248 | for attr in tcx.get_attrs(def.did).iter() { | |
1249 | for r in attr::find_repr_attrs(&tcx.sess, attr) { | |
1250 | if let attr::ReprPacked(pack) = r { | |
1251 | if let Some(repr_pack) = repr.pack { | |
1252 | if pack as u64 != repr_pack.bytes() { | |
1253 | struct_span_err!( | |
1254 | tcx.sess, | |
1255 | sp, | |
1256 | E0634, | |
1257 | "type has conflicting packed representation hints" | |
1258 | ) | |
1259 | .emit(); | |
1260 | } | |
1261 | } | |
1262 | } | |
1263 | } | |
1264 | } | |
1265 | if repr.align.is_some() { | |
1266 | struct_span_err!( | |
1267 | tcx.sess, | |
1268 | sp, | |
1269 | E0587, | |
1270 | "type has conflicting packed and align representation hints" | |
1271 | ) | |
1272 | .emit(); | |
1273 | } else { | |
1274 | if let Some(def_spans) = check_packed_inner(tcx, def.did, &mut vec![]) { | |
1275 | let mut err = struct_span_err!( | |
1276 | tcx.sess, | |
1277 | sp, | |
1278 | E0588, | |
1279 | "packed type cannot transitively contain a `#[repr(align)]` type" | |
1280 | ); | |
1281 | ||
1282 | err.span_note( | |
1283 | tcx.def_span(def_spans[0].0), | |
1284 | &format!( | |
1285 | "`{}` has a `#[repr(align)]` attribute", | |
1286 | tcx.item_name(def_spans[0].0) | |
1287 | ), | |
1288 | ); | |
1289 | ||
1290 | if def_spans.len() > 2 { | |
1291 | let mut first = true; | |
1292 | for (adt_def, span) in def_spans.iter().skip(1).rev() { | |
1293 | let ident = tcx.item_name(*adt_def); | |
1294 | err.span_note( | |
1295 | *span, | |
1296 | &if first { | |
1297 | format!( | |
1298 | "`{}` contains a field of type `{}`", | |
1299 | tcx.type_of(def.did), | |
1300 | ident | |
1301 | ) | |
1302 | } else { | |
1303 | format!("...which contains a field of type `{}`", ident) | |
1304 | }, | |
1305 | ); | |
1306 | first = false; | |
1307 | } | |
1308 | } | |
1309 | ||
1310 | err.emit(); | |
1311 | } | |
1312 | } | |
1313 | } | |
1314 | } | |
1315 | ||
1316 | pub(super) fn check_packed_inner( | |
1317 | tcx: TyCtxt<'_>, | |
1318 | def_id: DefId, | |
1319 | stack: &mut Vec<DefId>, | |
1320 | ) -> Option<Vec<(DefId, Span)>> { | |
1321 | if let ty::Adt(def, substs) = tcx.type_of(def_id).kind() { | |
1322 | if def.is_struct() || def.is_union() { | |
1323 | if def.repr.align.is_some() { | |
1324 | return Some(vec![(def.did, DUMMY_SP)]); | |
1325 | } | |
1326 | ||
1327 | stack.push(def_id); | |
1328 | for field in &def.non_enum_variant().fields { | |
1329 | if let ty::Adt(def, _) = field.ty(tcx, substs).kind() { | |
1330 | if !stack.contains(&def.did) { | |
1331 | if let Some(mut defs) = check_packed_inner(tcx, def.did, stack) { | |
1332 | defs.push((def.did, field.ident.span)); | |
1333 | return Some(defs); | |
1334 | } | |
1335 | } | |
1336 | } | |
1337 | } | |
1338 | stack.pop(); | |
1339 | } | |
1340 | } | |
1341 | ||
1342 | None | |
1343 | } | |
1344 | ||
1345 | pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: &'tcx ty::AdtDef) { | |
1346 | if !adt.repr.transparent() { | |
1347 | return; | |
1348 | } | |
1349 | let sp = tcx.sess.source_map().guess_head_span(sp); | |
1350 | ||
1351 | if adt.is_union() && !tcx.features().transparent_unions { | |
1352 | feature_err( | |
1353 | &tcx.sess.parse_sess, | |
1354 | sym::transparent_unions, | |
1355 | sp, | |
1356 | "transparent unions are unstable", | |
1357 | ) | |
1358 | .emit(); | |
1359 | } | |
1360 | ||
1361 | if adt.variants.len() != 1 { | |
1362 | bad_variant_count(tcx, adt, sp, adt.did); | |
1363 | if adt.variants.is_empty() { | |
1364 | // Don't bother checking the fields. No variants (and thus no fields) exist. | |
1365 | return; | |
1366 | } | |
1367 | } | |
1368 | ||
1369 | // For each field, figure out if it's known to be a ZST and align(1) | |
1370 | let field_infos = adt.all_fields().map(|field| { | |
1371 | let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did)); | |
1372 | let param_env = tcx.param_env(field.did); | |
1373 | let layout = tcx.layout_of(param_env.and(ty)); | |
1374 | // We are currently checking the type this field came from, so it must be local | |
1375 | let span = tcx.hir().span_if_local(field.did).unwrap(); | |
5869c6ff XL |
1376 | let zst = layout.map_or(false, |layout| layout.is_zst()); |
1377 | let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1); | |
1b1a35ee XL |
1378 | (span, zst, align1) |
1379 | }); | |
1380 | ||
1381 | let non_zst_fields = | |
1382 | field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None }); | |
1383 | let non_zst_count = non_zst_fields.clone().count(); | |
136023e0 | 1384 | if non_zst_count >= 2 { |
1b1a35ee XL |
1385 | bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp); |
1386 | } | |
1387 | for (span, zst, align1) in field_infos { | |
1388 | if zst && !align1 { | |
1389 | struct_span_err!( | |
1390 | tcx.sess, | |
1391 | span, | |
1392 | E0691, | |
1393 | "zero-sized field in transparent {} has alignment larger than 1", | |
1394 | adt.descr(), | |
1395 | ) | |
1396 | .span_label(span, "has alignment larger than 1") | |
1397 | .emit(); | |
1398 | } | |
1399 | } | |
1400 | } | |
1401 | ||
1402 | #[allow(trivial_numeric_casts)] | |
6a06907d | 1403 | fn check_enum<'tcx>( |
1b1a35ee XL |
1404 | tcx: TyCtxt<'tcx>, |
1405 | sp: Span, | |
1406 | vs: &'tcx [hir::Variant<'tcx>], | |
6a06907d | 1407 | def_id: LocalDefId, |
1b1a35ee | 1408 | ) { |
1b1a35ee XL |
1409 | let def = tcx.adt_def(def_id); |
1410 | def.destructor(tcx); // force the destructor to be evaluated | |
1411 | ||
1412 | if vs.is_empty() { | |
1413 | let attributes = tcx.get_attrs(def_id.to_def_id()); | |
1414 | if let Some(attr) = tcx.sess.find_by_name(&attributes, sym::repr) { | |
1415 | struct_span_err!( | |
1416 | tcx.sess, | |
1417 | attr.span, | |
1418 | E0084, | |
1419 | "unsupported representation for zero-variant enum" | |
1420 | ) | |
1421 | .span_label(sp, "zero-variant enum") | |
1422 | .emit(); | |
1423 | } | |
1424 | } | |
1425 | ||
1426 | let repr_type_ty = def.repr.discr_type().to_ty(tcx); | |
1427 | if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { | |
1428 | if !tcx.features().repr128 { | |
1429 | feature_err( | |
1430 | &tcx.sess.parse_sess, | |
1431 | sym::repr128, | |
1432 | sp, | |
1433 | "repr with 128-bit type is unstable", | |
1434 | ) | |
1435 | .emit(); | |
1436 | } | |
1437 | } | |
1438 | ||
1439 | for v in vs { | |
1440 | if let Some(ref e) = v.disr_expr { | |
1441 | tcx.ensure().typeck(tcx.hir().local_def_id(e.hir_id)); | |
1442 | } | |
1443 | } | |
1444 | ||
1445 | if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant { | |
5869c6ff | 1446 | let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..)); |
1b1a35ee XL |
1447 | |
1448 | let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some(); | |
1449 | let has_non_units = vs.iter().any(|var| !is_unit(var)); | |
1450 | let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var)); | |
1451 | let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var)); | |
1452 | ||
1453 | if disr_non_unit || (disr_units && has_non_units) { | |
1454 | let mut err = | |
1455 | struct_span_err!(tcx.sess, sp, E0732, "`#[repr(inttype)]` must be specified"); | |
1456 | err.emit(); | |
1457 | } | |
1458 | } | |
1459 | ||
1460 | let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len()); | |
cdc7bbd5 | 1461 | for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) { |
1b1a35ee XL |
1462 | // Check for duplicate discriminant values |
1463 | if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { | |
1464 | let variant_did = def.variants[VariantIdx::new(i)].def_id; | |
1465 | let variant_i_hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.expect_local()); | |
1466 | let variant_i = tcx.hir().expect_variant(variant_i_hir_id); | |
1467 | let i_span = match variant_i.disr_expr { | |
1468 | Some(ref expr) => tcx.hir().span(expr.hir_id), | |
1469 | None => tcx.hir().span(variant_i_hir_id), | |
1470 | }; | |
1471 | let span = match v.disr_expr { | |
1472 | Some(ref expr) => tcx.hir().span(expr.hir_id), | |
1473 | None => v.span, | |
1474 | }; | |
1475 | struct_span_err!( | |
1476 | tcx.sess, | |
1477 | span, | |
1478 | E0081, | |
1479 | "discriminant value `{}` already exists", | |
1480 | disr_vals[i] | |
1481 | ) | |
1482 | .span_label(i_span, format!("first use of `{}`", disr_vals[i])) | |
1483 | .span_label(span, format!("enum already has `{}`", disr_vals[i])) | |
1484 | .emit(); | |
1485 | } | |
1486 | disr_vals.push(discr); | |
1487 | } | |
1488 | ||
1489 | check_representable(tcx, sp, def_id); | |
1490 | check_transparent(tcx, sp, def); | |
1491 | } | |
1492 | ||
1493 | pub(super) fn check_type_params_are_used<'tcx>( | |
1494 | tcx: TyCtxt<'tcx>, | |
1495 | generics: &ty::Generics, | |
1496 | ty: Ty<'tcx>, | |
1497 | ) { | |
1498 | debug!("check_type_params_are_used(generics={:?}, ty={:?})", generics, ty); | |
1499 | ||
1500 | assert_eq!(generics.parent, None); | |
1501 | ||
1502 | if generics.own_counts().types == 0 { | |
1503 | return; | |
1504 | } | |
1505 | ||
1506 | let mut params_used = BitSet::new_empty(generics.params.len()); | |
1507 | ||
1508 | if ty.references_error() { | |
1509 | // If there is already another error, do not emit | |
1510 | // an error for not using a type parameter. | |
1511 | assert!(tcx.sess.has_errors()); | |
1512 | return; | |
1513 | } | |
1514 | ||
1515 | for leaf in ty.walk() { | |
1516 | if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { | |
1517 | if let ty::Param(param) = leaf_ty.kind() { | |
1518 | debug!("found use of ty param {:?}", param); | |
1519 | params_used.insert(param.index); | |
1520 | } | |
1521 | } | |
1522 | } | |
1523 | ||
1524 | for param in &generics.params { | |
1525 | if !params_used.contains(param.index) { | |
1526 | if let ty::GenericParamDefKind::Type { .. } = param.kind { | |
1527 | let span = tcx.def_span(param.def_id); | |
1528 | struct_span_err!( | |
1529 | tcx.sess, | |
1530 | span, | |
1531 | E0091, | |
1532 | "type parameter `{}` is unused", | |
1533 | param.name, | |
1534 | ) | |
1535 | .span_label(span, "unused type parameter") | |
1536 | .emit(); | |
1537 | } | |
1538 | } | |
1539 | } | |
1540 | } | |
1541 | ||
1542 | pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { | |
1543 | tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); | |
1544 | } | |
1545 | ||
1546 | pub(super) fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { | |
1547 | wfcheck::check_item_well_formed(tcx, def_id); | |
1548 | } | |
1549 | ||
1550 | pub(super) fn check_trait_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { | |
1551 | wfcheck::check_trait_item(tcx, def_id); | |
1552 | } | |
1553 | ||
1554 | pub(super) fn check_impl_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { | |
1555 | wfcheck::check_impl_item(tcx, def_id); | |
1556 | } | |
1557 | ||
1558 | fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) { | |
1559 | struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing") | |
1560 | .span_label(span, "recursive `async fn`") | |
1561 | .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`") | |
6a06907d XL |
1562 | .note( |
1563 | "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion", | |
1564 | ) | |
1b1a35ee XL |
1565 | .emit(); |
1566 | } | |
1567 | ||
1568 | /// Emit an error for recursive opaque types. | |
1569 | /// | |
1570 | /// If this is a return `impl Trait`, find the item's return expressions and point at them. For | |
1571 | /// direct recursion this is enough, but for indirect recursion also point at the last intermediary | |
1572 | /// `impl Trait`. | |
1573 | /// | |
1574 | /// If all the return expressions evaluate to `!`, then we explain that the error will go away | |
1575 | /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder. | |
1576 | fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { | |
1577 | let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type"); | |
1578 | ||
1579 | let mut label = false; | |
1580 | if let Some((hir_id, visitor)) = get_owner_return_paths(tcx, def_id) { | |
1581 | let typeck_results = tcx.typeck(tcx.hir().local_def_id(hir_id)); | |
1582 | if visitor | |
1583 | .returns | |
1584 | .iter() | |
1585 | .filter_map(|expr| typeck_results.node_type_opt(expr.hir_id)) | |
1586 | .all(|ty| matches!(ty.kind(), ty::Never)) | |
1587 | { | |
1588 | let spans = visitor | |
1589 | .returns | |
1590 | .iter() | |
1591 | .filter(|expr| typeck_results.node_type_opt(expr.hir_id).is_some()) | |
1592 | .map(|expr| expr.span) | |
1593 | .collect::<Vec<Span>>(); | |
1594 | let span_len = spans.len(); | |
1595 | if span_len == 1 { | |
1596 | err.span_label(spans[0], "this returned value is of `!` type"); | |
1597 | } else { | |
1598 | let mut multispan: MultiSpan = spans.clone().into(); | |
1599 | for span in spans { | |
1600 | multispan | |
1601 | .push_span_label(span, "this returned value is of `!` type".to_string()); | |
1602 | } | |
1603 | err.span_note(multispan, "these returned values have a concrete \"never\" type"); | |
1604 | } | |
1605 | err.help("this error will resolve once the item's body returns a concrete type"); | |
1606 | } else { | |
1607 | let mut seen = FxHashSet::default(); | |
1608 | seen.insert(span); | |
1609 | err.span_label(span, "recursive opaque type"); | |
1610 | label = true; | |
1611 | for (sp, ty) in visitor | |
1612 | .returns | |
1613 | .iter() | |
1614 | .filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t))) | |
1615 | .filter(|(_, ty)| !matches!(ty.kind(), ty::Never)) | |
1616 | { | |
1617 | struct VisitTypes(Vec<DefId>); | |
1618 | impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes { | |
fc512014 | 1619 | fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { |
1b1a35ee XL |
1620 | match *t.kind() { |
1621 | ty::Opaque(def, _) => { | |
1622 | self.0.push(def); | |
29967ef6 | 1623 | ControlFlow::CONTINUE |
1b1a35ee XL |
1624 | } |
1625 | _ => t.super_visit_with(self), | |
1626 | } | |
1627 | } | |
1628 | } | |
1629 | let mut visitor = VisitTypes(vec![]); | |
1630 | ty.visit_with(&mut visitor); | |
1631 | for def_id in visitor.0 { | |
1632 | let ty_span = tcx.def_span(def_id); | |
1633 | if !seen.contains(&ty_span) { | |
1634 | err.span_label(ty_span, &format!("returning this opaque type `{}`", ty)); | |
1635 | seen.insert(ty_span); | |
1636 | } | |
1637 | err.span_label(sp, &format!("returning here with type `{}`", ty)); | |
1638 | } | |
1639 | } | |
1640 | } | |
1641 | } | |
1642 | if !label { | |
1643 | err.span_label(span, "cannot resolve opaque type"); | |
1644 | } | |
1645 | err.emit(); | |
1646 | } |