]>
Commit | Line | Data |
---|---|---|
5869c6ff | 1 | use super::IsMethodCall; |
3dfed10e | 2 | use crate::astconv::{ |
fc512014 XL |
3 | AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch, |
4 | GenericArgCountResult, GenericArgPosition, | |
3dfed10e | 5 | }; |
1b1a35ee | 6 | use crate::errors::AssocTypeBindingNotAllowed; |
5869c6ff | 7 | use crate::structured_errors::{StructuredDiagnostic, WrongNumberOfGenericArgs}; |
3dfed10e | 8 | use rustc_ast::ast::ParamKindOrd; |
6a06907d | 9 | use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; |
3dfed10e | 10 | use rustc_hir as hir; |
6a06907d | 11 | use rustc_hir::def::{DefKind, Res}; |
3dfed10e | 12 | use rustc_hir::def_id::DefId; |
fc512014 | 13 | use rustc_hir::GenericArg; |
3dfed10e XL |
14 | use rustc_middle::ty::{ |
15 | self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt, | |
16 | }; | |
5869c6ff | 17 | use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; |
3dfed10e | 18 | use rustc_span::{symbol::kw, MultiSpan, Span}; |
3dfed10e XL |
19 | use smallvec::SmallVec; |
20 | ||
21 | impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { | |
22 | /// Report an error that a generic argument did not match the generic parameter that was | |
23 | /// expected. | |
24 | fn generic_arg_mismatch_err( | |
5869c6ff | 25 | tcx: TyCtxt<'_>, |
3dfed10e | 26 | arg: &GenericArg<'_>, |
5869c6ff | 27 | param: &GenericParamDef, |
fc512014 | 28 | possible_ordering_error: bool, |
3dfed10e XL |
29 | help: Option<&str>, |
30 | ) { | |
5869c6ff | 31 | let sess = tcx.sess; |
3dfed10e XL |
32 | let mut err = struct_span_err!( |
33 | sess, | |
34 | arg.span(), | |
35 | E0747, | |
36 | "{} provided when a {} was expected", | |
37 | arg.descr(), | |
5869c6ff | 38 | param.kind.descr(), |
3dfed10e XL |
39 | ); |
40 | ||
5869c6ff | 41 | if let GenericParamDefKind::Const { .. } = param.kind { |
fc512014 XL |
42 | if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg { |
43 | err.help("const arguments cannot yet be inferred with `_`"); | |
44 | } | |
45 | } | |
46 | ||
6a06907d XL |
47 | let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut DiagnosticBuilder<'_>| { |
48 | let suggestions = vec![ | |
49 | (arg.span().shrink_to_lo(), String::from("{ ")), | |
50 | (arg.span().shrink_to_hi(), String::from(" }")), | |
51 | ]; | |
52 | err.multipart_suggestion( | |
53 | "if this generic argument was intended as a const parameter, \ | |
54 | surround it with braces", | |
55 | suggestions, | |
56 | Applicability::MaybeIncorrect, | |
57 | ); | |
58 | }; | |
59 | ||
5869c6ff XL |
60 | // Specific suggestion set for diagnostics |
61 | match (arg, ¶m.kind) { | |
62 | ( | |
6a06907d XL |
63 | GenericArg::Type(hir::Ty { |
64 | kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)), | |
65 | .. | |
66 | }), | |
cdc7bbd5 | 67 | GenericParamDefKind::Const { .. }, |
6a06907d XL |
68 | ) => match path.res { |
69 | Res::Err => { | |
70 | add_braces_suggestion(arg, &mut err); | |
71 | err.set_primary_message( | |
72 | "unresolved item provided when a constant was expected", | |
73 | ) | |
74 | .emit(); | |
75 | return; | |
76 | } | |
77 | Res::Def(DefKind::TyParam, src_def_id) => { | |
78 | if let Some(param_local_id) = param.def_id.as_local() { | |
79 | let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id); | |
80 | let param_name = tcx.hir().ty_param_name(param_hir_id); | |
81 | let param_type = tcx.type_of(param.def_id); | |
82 | if param_type.is_suggestable() { | |
83 | err.span_suggestion( | |
84 | tcx.def_span(src_def_id), | |
cdc7bbd5 | 85 | "consider changing this type parameter to be a `const` generic", |
6a06907d XL |
86 | format!("const {}: {}", param_name, param_type), |
87 | Applicability::MaybeIncorrect, | |
88 | ); | |
89 | }; | |
90 | } | |
91 | } | |
92 | _ => add_braces_suggestion(arg, &mut err), | |
93 | }, | |
94 | ( | |
95 | GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }), | |
cdc7bbd5 | 96 | GenericParamDefKind::Const { .. }, |
6a06907d | 97 | ) => add_braces_suggestion(arg, &mut err), |
5869c6ff XL |
98 | ( |
99 | GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), | |
100 | GenericParamDefKind::Const { .. }, | |
101 | ) if tcx.type_of(param.def_id) == tcx.types.usize => { | |
102 | let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id)); | |
103 | if let Ok(snippet) = snippet { | |
104 | err.span_suggestion( | |
105 | arg.span(), | |
106 | "array type provided where a `usize` was expected, try", | |
107 | format!("{{ {} }}", snippet), | |
108 | Applicability::MaybeIncorrect, | |
109 | ); | |
110 | } | |
111 | } | |
cdc7bbd5 XL |
112 | (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => { |
113 | let body = tcx.hir().body(cnst.value.body); | |
114 | if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = | |
115 | body.value.kind | |
116 | { | |
117 | if let Res::Def(DefKind::Fn { .. }, id) = path.res { | |
118 | err.help(&format!( | |
119 | "`{}` is a function item, not a type", | |
120 | tcx.item_name(id) | |
121 | )); | |
122 | err.help("function item types cannot be named directly"); | |
123 | } | |
124 | } | |
125 | } | |
5869c6ff | 126 | _ => {} |
fc512014 XL |
127 | } |
128 | ||
5869c6ff XL |
129 | let kind_ord = param.kind.to_ord(tcx); |
130 | let arg_ord = arg.to_ord(&tcx.features()); | |
131 | ||
3dfed10e | 132 | // This note is only true when generic parameters are strictly ordered by their kind. |
fc512014 | 133 | if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal { |
5869c6ff XL |
134 | let (first, last) = if kind_ord < arg_ord { |
135 | (param.kind.descr(), arg.descr()) | |
136 | } else { | |
137 | (arg.descr(), param.kind.descr()) | |
138 | }; | |
3dfed10e XL |
139 | err.note(&format!("{} arguments must be provided before {} arguments", first, last)); |
140 | if let Some(help) = help { | |
141 | err.help(help); | |
142 | } | |
143 | } | |
144 | ||
145 | err.emit(); | |
146 | } | |
147 | ||
148 | /// Creates the relevant generic argument substitutions | |
149 | /// corresponding to a set of generic parameters. This is a | |
150 | /// rather complex function. Let us try to explain the role | |
151 | /// of each of its parameters: | |
152 | /// | |
153 | /// To start, we are given the `def_id` of the thing we are | |
154 | /// creating the substitutions for, and a partial set of | |
155 | /// substitutions `parent_substs`. In general, the substitutions | |
156 | /// for an item begin with substitutions for all the "parents" of | |
157 | /// that item -- e.g., for a method it might include the | |
158 | /// parameters from the impl. | |
159 | /// | |
160 | /// Therefore, the method begins by walking down these parents, | |
161 | /// starting with the outermost parent and proceed inwards until | |
162 | /// it reaches `def_id`. For each parent `P`, it will check `parent_substs` | |
163 | /// first to see if the parent's substitutions are listed in there. If so, | |
164 | /// we can append those and move on. Otherwise, it invokes the | |
165 | /// three callback functions: | |
166 | /// | |
167 | /// - `args_for_def_id`: given the `DefId` `P`, supplies back the | |
168 | /// generic arguments that were given to that parent from within | |
169 | /// the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId` | |
170 | /// might refer to the trait `Foo`, and the arguments might be | |
171 | /// `[T]`. The boolean value indicates whether to infer values | |
172 | /// for arguments whose values were not explicitly provided. | |
173 | /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`, | |
174 | /// instantiate a `GenericArg`. | |
175 | /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then | |
176 | /// creates a suitable inference variable. | |
fc512014 | 177 | pub fn create_substs_for_generic_args<'a>( |
3dfed10e XL |
178 | tcx: TyCtxt<'tcx>, |
179 | def_id: DefId, | |
180 | parent_substs: &[subst::GenericArg<'tcx>], | |
181 | has_self: bool, | |
182 | self_ty: Option<Ty<'tcx>>, | |
cdc7bbd5 | 183 | arg_count: &GenericArgCountResult, |
fc512014 | 184 | ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, |
3dfed10e XL |
185 | ) -> SubstsRef<'tcx> { |
186 | // Collect the segments of the path; we need to substitute arguments | |
187 | // for parameters throughout the entire path (wherever there are | |
188 | // generic parameters). | |
189 | let mut parent_defs = tcx.generics_of(def_id); | |
190 | let count = parent_defs.count(); | |
191 | let mut stack = vec![(def_id, parent_defs)]; | |
192 | while let Some(def_id) = parent_defs.parent { | |
193 | parent_defs = tcx.generics_of(def_id); | |
194 | stack.push((def_id, parent_defs)); | |
195 | } | |
196 | ||
197 | // We manually build up the substitution, rather than using convenience | |
198 | // methods in `subst.rs`, so that we can iterate over the arguments and | |
199 | // parameters in lock-step linearly, instead of trying to match each pair. | |
200 | let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); | |
201 | // Iterate over each segment of the path. | |
202 | while let Some((def_id, defs)) = stack.pop() { | |
203 | let mut params = defs.params.iter().peekable(); | |
204 | ||
205 | // If we have already computed substitutions for parents, we can use those directly. | |
206 | while let Some(¶m) = params.peek() { | |
207 | if let Some(&kind) = parent_substs.get(param.index as usize) { | |
208 | substs.push(kind); | |
209 | params.next(); | |
210 | } else { | |
211 | break; | |
212 | } | |
213 | } | |
214 | ||
215 | // `Self` is handled first, unless it's been handled in `parent_substs`. | |
216 | if has_self { | |
217 | if let Some(¶m) = params.peek() { | |
218 | if param.index == 0 { | |
219 | if let GenericParamDefKind::Type { .. } = param.kind { | |
220 | substs.push( | |
221 | self_ty | |
222 | .map(|ty| ty.into()) | |
fc512014 | 223 | .unwrap_or_else(|| ctx.inferred_kind(None, param, true)), |
3dfed10e XL |
224 | ); |
225 | params.next(); | |
226 | } | |
227 | } | |
228 | } | |
229 | } | |
230 | ||
231 | // Check whether this segment takes generic arguments and the user has provided any. | |
fc512014 | 232 | let (generic_args, infer_args) = ctx.args_for_def_id(def_id); |
3dfed10e | 233 | |
fc512014 XL |
234 | let args_iter = generic_args.iter().flat_map(|generic_args| generic_args.args.iter()); |
235 | let mut args = args_iter.clone().peekable(); | |
3dfed10e XL |
236 | |
237 | // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. | |
238 | // If we later encounter a lifetime, we know that the arguments were provided in the | |
239 | // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be | |
240 | // inferred, so we can use it for diagnostics later. | |
241 | let mut force_infer_lt = None; | |
242 | ||
243 | loop { | |
244 | // We're going to iterate through the generic arguments that the user | |
245 | // provided, matching them with the generic parameters we expect. | |
246 | // Mismatches can occur as a result of elided lifetimes, or for malformed | |
247 | // input. We try to handle both sensibly. | |
248 | match (args.peek(), params.peek()) { | |
249 | (Some(&arg), Some(¶m)) => { | |
250 | match (arg, ¶m.kind, arg_count.explicit_late_bound) { | |
251 | (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) | |
252 | | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _) | |
cdc7bbd5 | 253 | | (GenericArg::Const(_), GenericParamDefKind::Const { .. }, _) => { |
fc512014 | 254 | substs.push(ctx.provided_kind(param, arg)); |
3dfed10e XL |
255 | args.next(); |
256 | params.next(); | |
257 | } | |
258 | ( | |
259 | GenericArg::Type(_) | GenericArg::Const(_), | |
260 | GenericParamDefKind::Lifetime, | |
261 | _, | |
262 | ) => { | |
263 | // We expected a lifetime argument, but got a type or const | |
264 | // argument. That means we're inferring the lifetimes. | |
fc512014 | 265 | substs.push(ctx.inferred_kind(None, param, infer_args)); |
5869c6ff | 266 | force_infer_lt = Some((arg, param)); |
3dfed10e XL |
267 | params.next(); |
268 | } | |
269 | (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => { | |
270 | // We've come across a lifetime when we expected something else in | |
271 | // the presence of explicit late bounds. This is most likely | |
272 | // due to the presence of the explicit bound so we're just going to | |
273 | // ignore it. | |
274 | args.next(); | |
275 | } | |
5869c6ff | 276 | (_, _, _) => { |
3dfed10e XL |
277 | // We expected one kind of parameter, but the user provided |
278 | // another. This is an error. However, if we already know that | |
279 | // the arguments don't match up with the parameters, we won't issue | |
280 | // an additional error, as the user already knows what's wrong. | |
281 | if arg_count.correct.is_ok() | |
282 | && arg_count.explicit_late_bound == ExplicitLateBound::No | |
283 | { | |
284 | // We're going to iterate over the parameters to sort them out, and | |
285 | // show that order to the user as a possible order for the parameters | |
286 | let mut param_types_present = defs | |
287 | .params | |
288 | .clone() | |
289 | .into_iter() | |
290 | .map(|param| { | |
291 | ( | |
292 | match param.kind { | |
293 | GenericParamDefKind::Lifetime => { | |
294 | ParamKindOrd::Lifetime | |
295 | } | |
296 | GenericParamDefKind::Type { .. } => { | |
297 | ParamKindOrd::Type | |
298 | } | |
cdc7bbd5 | 299 | GenericParamDefKind::Const { .. } => { |
3dfed10e XL |
300 | ParamKindOrd::Const { |
301 | unordered: tcx | |
fc512014 | 302 | .features() |
cdc7bbd5 | 303 | .unordered_const_ty_params(), |
3dfed10e XL |
304 | } |
305 | } | |
306 | }, | |
307 | param, | |
308 | ) | |
309 | }) | |
310 | .collect::<Vec<(ParamKindOrd, GenericParamDef)>>(); | |
311 | param_types_present.sort_by_key(|(ord, _)| *ord); | |
312 | let (mut param_types_present, ordered_params): ( | |
313 | Vec<ParamKindOrd>, | |
314 | Vec<GenericParamDef>, | |
315 | ) = param_types_present.into_iter().unzip(); | |
316 | param_types_present.dedup(); | |
317 | ||
318 | Self::generic_arg_mismatch_err( | |
5869c6ff | 319 | tcx, |
3dfed10e | 320 | arg, |
5869c6ff | 321 | param, |
fc512014 XL |
322 | !args_iter.clone().is_sorted_by_key(|arg| match arg { |
323 | GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, | |
324 | GenericArg::Type(_) => ParamKindOrd::Type, | |
325 | GenericArg::Const(_) => ParamKindOrd::Const { | |
cdc7bbd5 XL |
326 | unordered: tcx |
327 | .features() | |
328 | .unordered_const_ty_params(), | |
fc512014 XL |
329 | }, |
330 | }), | |
3dfed10e XL |
331 | Some(&format!( |
332 | "reorder the arguments: {}: `<{}>`", | |
333 | param_types_present | |
334 | .into_iter() | |
335 | .map(|ord| format!("{}s", ord.to_string())) | |
336 | .collect::<Vec<String>>() | |
337 | .join(", then "), | |
338 | ordered_params | |
339 | .into_iter() | |
340 | .filter_map(|param| { | |
341 | if param.name == kw::SelfUpper { | |
342 | None | |
343 | } else { | |
344 | Some(param.name.to_string()) | |
345 | } | |
346 | }) | |
347 | .collect::<Vec<String>>() | |
348 | .join(", ") | |
349 | )), | |
350 | ); | |
351 | } | |
352 | ||
353 | // We've reported the error, but we want to make sure that this | |
354 | // problem doesn't bubble down and create additional, irrelevant | |
355 | // errors. In this case, we're simply going to ignore the argument | |
356 | // and any following arguments. The rest of the parameters will be | |
357 | // inferred. | |
358 | while args.next().is_some() {} | |
359 | } | |
360 | } | |
361 | } | |
362 | ||
363 | (Some(&arg), None) => { | |
364 | // We should never be able to reach this point with well-formed input. | |
365 | // There are three situations in which we can encounter this issue. | |
366 | // | |
367 | // 1. The number of arguments is incorrect. In this case, an error | |
368 | // will already have been emitted, and we can ignore it. | |
369 | // 2. There are late-bound lifetime parameters present, yet the | |
370 | // lifetime arguments have also been explicitly specified by the | |
371 | // user. | |
372 | // 3. We've inferred some lifetimes, which have been provided later (i.e. | |
373 | // after a type or const). We want to throw an error in this case. | |
374 | ||
375 | if arg_count.correct.is_ok() | |
376 | && arg_count.explicit_late_bound == ExplicitLateBound::No | |
377 | { | |
378 | let kind = arg.descr(); | |
379 | assert_eq!(kind, "lifetime"); | |
5869c6ff | 380 | let (provided_arg, param) = |
3dfed10e | 381 | force_infer_lt.expect("lifetimes ought to have been inferred"); |
5869c6ff | 382 | Self::generic_arg_mismatch_err(tcx, provided_arg, param, false, None); |
3dfed10e XL |
383 | } |
384 | ||
385 | break; | |
386 | } | |
387 | ||
388 | (None, Some(¶m)) => { | |
389 | // If there are fewer arguments than parameters, it means | |
390 | // we're inferring the remaining arguments. | |
fc512014 | 391 | substs.push(ctx.inferred_kind(Some(&substs), param, infer_args)); |
3dfed10e XL |
392 | params.next(); |
393 | } | |
394 | ||
395 | (None, None) => break, | |
396 | } | |
397 | } | |
398 | } | |
399 | ||
400 | tcx.intern_substs(&substs) | |
401 | } | |
402 | ||
403 | /// Checks that the correct number of generic arguments have been provided. | |
404 | /// Used specifically for function calls. | |
405 | pub fn check_generic_arg_count_for_call( | |
406 | tcx: TyCtxt<'_>, | |
407 | span: Span, | |
5869c6ff XL |
408 | def_id: DefId, |
409 | generics: &ty::Generics, | |
3dfed10e | 410 | seg: &hir::PathSegment<'_>, |
5869c6ff | 411 | is_method_call: IsMethodCall, |
3dfed10e XL |
412 | ) -> GenericArgCountResult { |
413 | let empty_args = hir::GenericArgs::none(); | |
5869c6ff XL |
414 | let suppress_mismatch = Self::check_impl_trait(tcx, seg, &generics); |
415 | ||
416 | let gen_args = seg.args.unwrap_or(&empty_args); | |
417 | let gen_pos = if is_method_call == IsMethodCall::Yes { | |
418 | GenericArgPosition::MethodCall | |
419 | } else { | |
420 | GenericArgPosition::Value | |
421 | }; | |
422 | let has_self = generics.parent.is_none() && generics.has_self; | |
423 | let infer_args = seg.infer_args || suppress_mismatch; | |
424 | ||
3dfed10e | 425 | Self::check_generic_arg_count( |
5869c6ff | 426 | tcx, span, def_id, seg, generics, gen_args, gen_pos, has_self, infer_args, |
3dfed10e XL |
427 | ) |
428 | } | |
429 | ||
430 | /// Checks that the correct number of generic arguments have been provided. | |
431 | /// This is used both for datatypes and function calls. | |
432 | pub(crate) fn check_generic_arg_count( | |
433 | tcx: TyCtxt<'_>, | |
434 | span: Span, | |
5869c6ff XL |
435 | def_id: DefId, |
436 | seg: &hir::PathSegment<'_>, | |
437 | gen_params: &ty::Generics, | |
438 | gen_args: &hir::GenericArgs<'_>, | |
439 | gen_pos: GenericArgPosition, | |
3dfed10e XL |
440 | has_self: bool, |
441 | infer_args: bool, | |
442 | ) -> GenericArgCountResult { | |
5869c6ff XL |
443 | let default_counts = gen_params.own_defaults(); |
444 | let param_counts = gen_params.own_counts(); | |
fc512014 | 445 | let named_type_param_count = param_counts.types - has_self as usize; |
5869c6ff XL |
446 | let arg_counts = gen_args.own_counts(); |
447 | let infer_lifetimes = gen_pos != GenericArgPosition::Type && arg_counts.lifetimes == 0; | |
3dfed10e | 448 | |
5869c6ff XL |
449 | if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() { |
450 | Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span); | |
3dfed10e XL |
451 | } |
452 | ||
453 | let explicit_late_bound = | |
5869c6ff | 454 | Self::prohibit_explicit_late_bound_lifetimes(tcx, gen_params, gen_args, gen_pos); |
3dfed10e | 455 | |
5869c6ff | 456 | let mut invalid_args = vec![]; |
3dfed10e | 457 | |
5869c6ff XL |
458 | let mut check_generics = |
459 | |kind, expected_min, expected_max, provided, params_offset, args_offset, silent| { | |
460 | if (expected_min..=expected_max).contains(&provided) { | |
461 | return true; | |
3dfed10e | 462 | } |
3dfed10e | 463 | |
5869c6ff XL |
464 | if silent { |
465 | return false; | |
466 | } | |
3dfed10e | 467 | |
5869c6ff XL |
468 | if provided > expected_max { |
469 | invalid_args.extend( | |
470 | gen_args.args[args_offset + expected_max..args_offset + provided] | |
471 | .iter() | |
472 | .map(|arg| arg.span()), | |
473 | ); | |
474 | }; | |
475 | ||
476 | WrongNumberOfGenericArgs { | |
477 | tcx, | |
478 | kind, | |
479 | expected_min, | |
480 | expected_max, | |
481 | provided, | |
482 | params_offset, | |
483 | args_offset, | |
484 | path_segment: seg, | |
485 | gen_params, | |
486 | gen_args, | |
487 | def_id, | |
488 | span, | |
489 | } | |
490 | .diagnostic() | |
491 | .emit(); | |
3dfed10e | 492 | |
5869c6ff XL |
493 | false |
494 | }; | |
3dfed10e | 495 | |
5869c6ff | 496 | let lifetimes_correct = check_generics( |
fc512014 XL |
497 | "lifetime", |
498 | if infer_lifetimes { 0 } else { param_counts.lifetimes }, | |
499 | param_counts.lifetimes, | |
500 | arg_counts.lifetimes, | |
5869c6ff | 501 | has_self as usize, |
fc512014 | 502 | 0, |
fc512014 XL |
503 | explicit_late_bound == ExplicitLateBound::Yes, |
504 | ); | |
3dfed10e | 505 | |
5869c6ff XL |
506 | let args_correct = { |
507 | let kind = if param_counts.consts + arg_counts.consts == 0 { | |
508 | "type" | |
509 | } else if named_type_param_count + arg_counts.types == 0 { | |
510 | "const" | |
511 | } else { | |
512 | "generic" | |
513 | }; | |
1b1a35ee | 514 | |
5869c6ff | 515 | let expected_min = if infer_args { |
fc512014 XL |
516 | 0 |
517 | } else { | |
cdc7bbd5 XL |
518 | param_counts.consts + named_type_param_count |
519 | - default_counts.types | |
520 | - default_counts.consts | |
5869c6ff XL |
521 | }; |
522 | ||
523 | check_generics( | |
524 | kind, | |
525 | expected_min, | |
526 | param_counts.consts + named_type_param_count, | |
527 | arg_counts.consts + arg_counts.types, | |
528 | param_counts.lifetimes + has_self as usize, | |
529 | arg_counts.lifetimes, | |
530 | false, | |
531 | ) | |
532 | }; | |
1b1a35ee | 533 | |
3dfed10e XL |
534 | GenericArgCountResult { |
535 | explicit_late_bound, | |
5869c6ff | 536 | correct: if lifetimes_correct && args_correct { |
fc512014 XL |
537 | Ok(()) |
538 | } else { | |
5869c6ff | 539 | Err(GenericArgCountMismatch { reported: Some(ErrorReported), invalid_args }) |
fc512014 | 540 | }, |
3dfed10e XL |
541 | } |
542 | } | |
543 | ||
544 | /// Report error if there is an explicit type parameter when using `impl Trait`. | |
545 | pub(crate) fn check_impl_trait( | |
546 | tcx: TyCtxt<'_>, | |
547 | seg: &hir::PathSegment<'_>, | |
548 | generics: &ty::Generics, | |
549 | ) -> bool { | |
550 | let explicit = !seg.infer_args; | |
5869c6ff XL |
551 | let impl_trait = generics.params.iter().any(|param| { |
552 | matches!( | |
553 | param.kind, | |
29967ef6 | 554 | ty::GenericParamDefKind::Type { |
5869c6ff XL |
555 | synthetic: Some( |
556 | hir::SyntheticTyParamKind::ImplTrait | hir::SyntheticTyParamKind::FromAttr, | |
557 | ), | |
29967ef6 | 558 | .. |
5869c6ff XL |
559 | } |
560 | ) | |
561 | }); | |
3dfed10e XL |
562 | |
563 | if explicit && impl_trait { | |
564 | let spans = seg | |
5869c6ff | 565 | .args() |
3dfed10e XL |
566 | .args |
567 | .iter() | |
568 | .filter_map(|arg| match arg { | |
29967ef6 | 569 | GenericArg::Type(_) | GenericArg::Const(_) => Some(arg.span()), |
3dfed10e XL |
570 | _ => None, |
571 | }) | |
572 | .collect::<Vec<_>>(); | |
573 | ||
574 | let mut err = struct_span_err! { | |
575 | tcx.sess, | |
576 | spans.clone(), | |
577 | E0632, | |
578 | "cannot provide explicit generic arguments when `impl Trait` is \ | |
579 | used in argument position" | |
580 | }; | |
581 | ||
582 | for span in spans { | |
583 | err.span_label(span, "explicit generic argument not allowed"); | |
584 | } | |
585 | ||
586 | err.emit(); | |
587 | } | |
588 | ||
589 | impl_trait | |
590 | } | |
591 | ||
592 | /// Emits an error regarding forbidden type binding associations | |
593 | pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) { | |
1b1a35ee | 594 | tcx.sess.emit_err(AssocTypeBindingNotAllowed { span }); |
3dfed10e XL |
595 | } |
596 | ||
597 | /// Prohibits explicit lifetime arguments if late-bound lifetime parameters | |
598 | /// are present. This is used both for datatypes and function calls. | |
599 | pub(crate) fn prohibit_explicit_late_bound_lifetimes( | |
600 | tcx: TyCtxt<'_>, | |
601 | def: &ty::Generics, | |
602 | args: &hir::GenericArgs<'_>, | |
603 | position: GenericArgPosition, | |
604 | ) -> ExplicitLateBound { | |
605 | let param_counts = def.own_counts(); | |
606 | let arg_counts = args.own_counts(); | |
607 | let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0; | |
608 | ||
609 | if infer_lifetimes { | |
5869c6ff XL |
610 | return ExplicitLateBound::No; |
611 | } | |
612 | ||
613 | if let Some(span_late) = def.has_late_bound_regions { | |
3dfed10e XL |
614 | let msg = "cannot specify lifetime arguments explicitly \ |
615 | if late bound lifetime parameters are present"; | |
616 | let note = "the late bound lifetime parameter is introduced here"; | |
617 | let span = args.args[0].span(); | |
5869c6ff | 618 | |
3dfed10e XL |
619 | if position == GenericArgPosition::Value |
620 | && arg_counts.lifetimes != param_counts.lifetimes | |
621 | { | |
622 | let mut err = tcx.sess.struct_span_err(span, msg); | |
623 | err.span_note(span_late, note); | |
624 | err.emit(); | |
625 | } else { | |
626 | let mut multispan = MultiSpan::from_span(span); | |
627 | multispan.push_span_label(span_late, note.to_string()); | |
628 | tcx.struct_span_lint_hir( | |
629 | LATE_BOUND_LIFETIME_ARGUMENTS, | |
630 | args.args[0].id(), | |
631 | multispan, | |
632 | |lint| lint.build(msg).emit(), | |
633 | ); | |
634 | } | |
5869c6ff | 635 | |
3dfed10e XL |
636 | ExplicitLateBound::Yes |
637 | } else { | |
638 | ExplicitLateBound::No | |
639 | } | |
640 | } | |
641 | } |