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