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