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