]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/compare_method.rs
When checking associated type bounds, use bound vars for GAT params in param_env
[rust.git] / compiler / rustc_typeck / src / check / compare_method.rs
1 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
2 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
3 use rustc_hir as hir;
4 use rustc_hir::def::{DefKind, Res};
5 use rustc_hir::intravisit;
6 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
7 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
8 use rustc_infer::traits::util;
9 use rustc_middle::ty;
10 use rustc_middle::ty::error::{ExpectedFound, TypeError};
11 use rustc_middle::ty::subst::{InternalSubsts, Subst};
12 use rustc_middle::ty::util::ExplicitSelf;
13 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
14 use rustc_span::Span;
15 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
16 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
17 use std::iter;
18
19 use super::{potentially_plural_count, FnCtxt, Inherited};
20
21 /// Checks that a method from an impl conforms to the signature of
22 /// the same method as declared in the trait.
23 ///
24 /// # Parameters
25 ///
26 /// - `impl_m`: type of the method we are checking
27 /// - `impl_m_span`: span to use for reporting errors
28 /// - `trait_m`: the method in the trait
29 /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
30
31 crate fn compare_impl_method<'tcx>(
32     tcx: TyCtxt<'tcx>,
33     impl_m: &ty::AssocItem,
34     impl_m_span: Span,
35     trait_m: &ty::AssocItem,
36     impl_trait_ref: ty::TraitRef<'tcx>,
37     trait_item_span: Option<Span>,
38 ) {
39     debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
40
41     let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span);
42
43     if let Err(ErrorReported) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
44     {
45         return;
46     }
47
48     if let Err(ErrorReported) =
49         compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span)
50     {
51         return;
52     }
53
54     if let Err(ErrorReported) =
55         compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)
56     {
57         return;
58     }
59
60     if let Err(ErrorReported) = compare_synthetic_generics(tcx, impl_m, trait_m) {
61         return;
62     }
63
64     if let Err(ErrorReported) =
65         compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
66     {
67         return;
68     }
69
70     if let Err(ErrorReported) = compare_const_param_types(tcx, impl_m, trait_m, trait_item_span) {
71         return;
72     }
73 }
74
75 fn compare_predicate_entailment<'tcx>(
76     tcx: TyCtxt<'tcx>,
77     impl_m: &ty::AssocItem,
78     impl_m_span: Span,
79     trait_m: &ty::AssocItem,
80     impl_trait_ref: ty::TraitRef<'tcx>,
81 ) -> Result<(), ErrorReported> {
82     let trait_to_impl_substs = impl_trait_ref.substs;
83
84     // This node-id should be used for the `body_id` field on each
85     // `ObligationCause` (and the `FnCtxt`). This is what
86     // `regionck_item` expects.
87     let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
88
89     // We sometimes modify the span further down.
90     let mut cause = ObligationCause::new(
91         impl_m_span,
92         impl_m_hir_id,
93         ObligationCauseCode::CompareImplMethodObligation {
94             item_name: impl_m.ident.name,
95             impl_item_def_id: impl_m.def_id,
96             trait_item_def_id: trait_m.def_id,
97         },
98     );
99
100     // This code is best explained by example. Consider a trait:
101     //
102     //     trait Trait<'t, T> {
103     //         fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
104     //     }
105     //
106     // And an impl:
107     //
108     //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
109     //          fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
110     //     }
111     //
112     // We wish to decide if those two method types are compatible.
113     //
114     // We start out with trait_to_impl_substs, that maps the trait
115     // type parameters to impl type parameters. This is taken from the
116     // impl trait reference:
117     //
118     //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
119     //
120     // We create a mapping `dummy_substs` that maps from the impl type
121     // parameters to fresh types and regions. For type parameters,
122     // this is the identity transform, but we could as well use any
123     // placeholder types. For regions, we convert from bound to free
124     // regions (Note: but only early-bound regions, i.e., those
125     // declared on the impl or used in type parameter bounds).
126     //
127     //     impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
128     //
129     // Now we can apply placeholder_substs to the type of the impl method
130     // to yield a new function type in terms of our fresh, placeholder
131     // types:
132     //
133     //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
134     //
135     // We now want to extract and substitute the type of the *trait*
136     // method and compare it. To do so, we must create a compound
137     // substitution by combining trait_to_impl_substs and
138     // impl_to_placeholder_substs, and also adding a mapping for the method
139     // type parameters. We extend the mapping to also include
140     // the method parameters.
141     //
142     //     trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
143     //
144     // Applying this to the trait method type yields:
145     //
146     //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
147     //
148     // This type is also the same but the name of the bound region ('a
149     // vs 'b).  However, the normal subtyping rules on fn types handle
150     // this kind of equivalency just fine.
151     //
152     // We now use these substitutions to ensure that all declared bounds are
153     // satisfied by the implementation's method.
154     //
155     // We do this by creating a parameter environment which contains a
156     // substitution corresponding to impl_to_placeholder_substs. We then build
157     // trait_to_placeholder_substs and use it to convert the predicates contained
158     // in the trait_m.generics to the placeholder form.
159     //
160     // Finally we register each of these predicates as an obligation in
161     // a fresh FulfillmentCtxt, and invoke select_all_or_error.
162
163     // Create mapping from impl to placeholder.
164     let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
165
166     // Create mapping from trait to placeholder.
167     let trait_to_placeholder_substs =
168         impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs);
169     debug!("compare_impl_method: trait_to_placeholder_substs={:?}", trait_to_placeholder_substs);
170
171     let impl_m_generics = tcx.generics_of(impl_m.def_id);
172     let trait_m_generics = tcx.generics_of(trait_m.def_id);
173     let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
174     let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
175
176     // Check region bounds.
177     check_region_bounds_on_impl_item(
178         tcx,
179         impl_m_span,
180         impl_m,
181         trait_m,
182         &trait_m_generics,
183         &impl_m_generics,
184     )?;
185
186     // Create obligations for each predicate declared by the impl
187     // definition in the context of the trait's parameter
188     // environment. We can't just use `impl_env.caller_bounds`,
189     // however, because we want to replace all late-bound regions with
190     // region variables.
191     let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
192     let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
193
194     debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
195
196     // This is the only tricky bit of the new way we check implementation methods
197     // We need to build a set of predicates where only the method-level bounds
198     // are from the trait and we assume all other bounds from the implementation
199     // to be previously satisfied.
200     //
201     // We then register the obligations from the impl_m and check to see
202     // if all constraints hold.
203     hybrid_preds
204         .predicates
205         .extend(trait_m_predicates.instantiate_own(tcx, trait_to_placeholder_substs).predicates);
206
207     // Construct trait parameter environment and then shift it into the placeholder viewpoint.
208     // The key step here is to update the caller_bounds's predicates to be
209     // the new hybrid bounds we computed.
210     let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id);
211     let param_env =
212         ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing);
213     let param_env = traits::normalize_param_env_or_error(
214         tcx,
215         impl_m.def_id,
216         param_env,
217         normalize_cause.clone(),
218     );
219
220     tcx.infer_ctxt().enter(|infcx| {
221         let inh = Inherited::new(infcx, impl_m.def_id.expect_local());
222         let infcx = &inh.infcx;
223
224         debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
225
226         let mut selcx = traits::SelectionContext::new(&infcx);
227
228         let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
229         for predicate in impl_m_own_bounds.predicates {
230             let traits::Normalized { value: predicate, obligations } =
231                 traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
232
233             inh.register_predicates(obligations);
234             inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate));
235         }
236
237         // We now need to check that the signature of the impl method is
238         // compatible with that of the trait method. We do this by
239         // checking that `impl_fty <: trait_fty`.
240         //
241         // FIXME. Unfortunately, this doesn't quite work right now because
242         // associated type normalization is not integrated into subtype
243         // checks. For the comparison to be valid, we need to
244         // normalize the associated types in the impl/trait methods
245         // first. However, because function types bind regions, just
246         // calling `normalize_associated_types_in` would have no effect on
247         // any associated types appearing in the fn arguments or return
248         // type.
249
250         // Compute placeholder form of impl and trait method tys.
251         let tcx = infcx.tcx;
252
253         let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
254             impl_m_span,
255             infer::HigherRankedType,
256             tcx.fn_sig(impl_m.def_id),
257         );
258         let impl_sig =
259             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
260         let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
261         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
262
263         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
264         let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
265         let trait_sig =
266             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
267         let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
268
269         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
270
271         let sub_result = infcx.at(&cause, param_env).sup(trait_fty, impl_fty).map(
272             |InferOk { obligations, .. }| {
273                 inh.register_predicates(obligations);
274             },
275         );
276
277         if let Err(terr) = sub_result {
278             debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
279
280             let (impl_err_span, trait_err_span) =
281                 extract_spans_for_error_reporting(&infcx, &terr, &cause, impl_m, trait_m);
282
283             cause.make_mut().span = impl_err_span;
284
285             let mut diag = struct_span_err!(
286                 tcx.sess,
287                 cause.span(tcx),
288                 E0053,
289                 "method `{}` has an incompatible type for trait",
290                 trait_m.ident
291             );
292             match &terr {
293                 TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
294                     if trait_m.fn_has_self_parameter =>
295                 {
296                     let ty = trait_sig.inputs()[0];
297                     let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty())
298                     {
299                         ExplicitSelf::ByValue => "self".to_owned(),
300                         ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
301                         ExplicitSelf::ByReference(_, hir::Mutability::Mut) => {
302                             "&mut self".to_owned()
303                         }
304                         _ => format!("self: {}", ty),
305                     };
306
307                     // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
308                     // span points only at the type `Box<Self`>, but we want to cover the whole
309                     // argument pattern and type.
310                     let impl_m_hir_id =
311                         tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
312                     let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
313                         ImplItemKind::Fn(ref sig, body) => tcx
314                             .hir()
315                             .body_param_names(body)
316                             .zip(sig.decl.inputs.iter())
317                             .map(|(param, ty)| param.span.to(ty.span))
318                             .next()
319                             .unwrap_or(impl_err_span),
320                         _ => bug!("{:?} is not a method", impl_m),
321                     };
322
323                     diag.span_suggestion(
324                         span,
325                         "change the self-receiver type to match the trait",
326                         sugg,
327                         Applicability::MachineApplicable,
328                     );
329                 }
330                 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
331                     if trait_sig.inputs().len() == *i {
332                         // Suggestion to change output type. We do not suggest in `async` functions
333                         // to avoid complex logic or incorrect output.
334                         let impl_m_hir_id =
335                             tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
336                         match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
337                             ImplItemKind::Fn(ref sig, _)
338                                 if sig.header.asyncness == hir::IsAsync::NotAsync =>
339                             {
340                                 let msg = "change the output type to match the trait";
341                                 let ap = Applicability::MachineApplicable;
342                                 match sig.decl.output {
343                                     hir::FnRetTy::DefaultReturn(sp) => {
344                                         let sugg = format!("-> {} ", trait_sig.output());
345                                         diag.span_suggestion_verbose(sp, msg, sugg, ap);
346                                     }
347                                     hir::FnRetTy::Return(hir_ty) => {
348                                         let sugg = trait_sig.output().to_string();
349                                         diag.span_suggestion(hir_ty.span, msg, sugg, ap);
350                                     }
351                                 };
352                             }
353                             _ => {}
354                         };
355                     } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
356                         diag.span_suggestion(
357                             impl_err_span,
358                             "change the parameter type to match the trait",
359                             trait_ty.to_string(),
360                             Applicability::MachineApplicable,
361                         );
362                     }
363                 }
364                 _ => {}
365             }
366
367             infcx.note_type_err(
368                 &mut diag,
369                 &cause,
370                 trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
371                 Some(infer::ValuePairs::Types(ExpectedFound {
372                     expected: trait_fty,
373                     found: impl_fty,
374                 })),
375                 &terr,
376             );
377             diag.emit();
378             return Err(ErrorReported);
379         }
380
381         // Check that all obligations are satisfied by the implementation's
382         // version.
383         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
384             infcx.report_fulfillment_errors(errors, None, false);
385             return Err(ErrorReported);
386         }
387
388         // Finally, resolve all regions. This catches wily misuses of
389         // lifetime parameters.
390         let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
391         fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output);
392
393         Ok(())
394     })
395 }
396
397 fn check_region_bounds_on_impl_item<'tcx>(
398     tcx: TyCtxt<'tcx>,
399     span: Span,
400     impl_m: &ty::AssocItem,
401     trait_m: &ty::AssocItem,
402     trait_generics: &ty::Generics,
403     impl_generics: &ty::Generics,
404 ) -> Result<(), ErrorReported> {
405     let trait_params = trait_generics.own_counts().lifetimes;
406     let impl_params = impl_generics.own_counts().lifetimes;
407
408     debug!(
409         "check_region_bounds_on_impl_item: \
410             trait_generics={:?} \
411             impl_generics={:?}",
412         trait_generics, impl_generics
413     );
414
415     // Must have same number of early-bound lifetime parameters.
416     // Unfortunately, if the user screws up the bounds, then this
417     // will change classification between early and late.  E.g.,
418     // if in trait we have `<'a,'b:'a>`, and in impl we just have
419     // `<'a,'b>`, then we have 2 early-bound lifetime parameters
420     // in trait but 0 in the impl. But if we report "expected 2
421     // but found 0" it's confusing, because it looks like there
422     // are zero. Since I don't quite know how to phrase things at
423     // the moment, give a kind of vague error message.
424     if trait_params != impl_params {
425         let item_kind = assoc_item_kind_str(impl_m);
426         let def_span = tcx.sess.source_map().guess_head_span(span);
427         let span = tcx.hir().get_generics(impl_m.def_id).map_or(def_span, |g| g.span);
428         let generics_span = tcx.hir().span_if_local(trait_m.def_id).map(|sp| {
429             let def_sp = tcx.sess.source_map().guess_head_span(sp);
430             tcx.hir().get_generics(trait_m.def_id).map_or(def_sp, |g| g.span)
431         });
432
433         tcx.sess.emit_err(LifetimesOrBoundsMismatchOnTrait {
434             span,
435             item_kind,
436             ident: impl_m.ident,
437             generics_span,
438         });
439         return Err(ErrorReported);
440     }
441
442     Ok(())
443 }
444
445 fn extract_spans_for_error_reporting<'a, 'tcx>(
446     infcx: &infer::InferCtxt<'a, 'tcx>,
447     terr: &TypeError<'_>,
448     cause: &ObligationCause<'tcx>,
449     impl_m: &ty::AssocItem,
450     trait_m: &ty::AssocItem,
451 ) -> (Span, Option<Span>) {
452     let tcx = infcx.tcx;
453     let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
454     let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
455         ImplItemKind::Fn(ref sig, _) => {
456             sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
457         }
458         _ => bug!("{:?} is not a method", impl_m),
459     };
460     let trait_args = trait_m.def_id.as_local().map(|def_id| {
461         let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
462         match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
463             TraitItemKind::Fn(ref sig, _) => {
464                 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
465             }
466             _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
467         }
468     });
469
470     match *terr {
471         TypeError::ArgumentMutability(i) => {
472             (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
473         }
474         TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
475             (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
476         }
477         _ => (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)),
478     }
479 }
480
481 fn compare_self_type<'tcx>(
482     tcx: TyCtxt<'tcx>,
483     impl_m: &ty::AssocItem,
484     impl_m_span: Span,
485     trait_m: &ty::AssocItem,
486     impl_trait_ref: ty::TraitRef<'tcx>,
487 ) -> Result<(), ErrorReported> {
488     // Try to give more informative error messages about self typing
489     // mismatches.  Note that any mismatch will also be detected
490     // below, where we construct a canonical function type that
491     // includes the self parameter as a normal parameter.  It's just
492     // that the error messages you get out of this code are a bit more
493     // inscrutable, particularly for cases where one method has no
494     // self.
495
496     let self_string = |method: &ty::AssocItem| {
497         let untransformed_self_ty = match method.container {
498             ty::ImplContainer(_) => impl_trait_ref.self_ty(),
499             ty::TraitContainer(_) => tcx.types.self_param,
500         };
501         let self_arg_ty = tcx.fn_sig(method.def_id).input(0);
502         let param_env = ty::ParamEnv::reveal_all();
503
504         tcx.infer_ctxt().enter(|infcx| {
505             let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
506             let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
507             match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
508                 ExplicitSelf::ByValue => "self".to_owned(),
509                 ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
510                 ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
511                 _ => format!("self: {}", self_arg_ty),
512             }
513         })
514     };
515
516     match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) {
517         (false, false) | (true, true) => {}
518
519         (false, true) => {
520             let self_descr = self_string(impl_m);
521             let mut err = struct_span_err!(
522                 tcx.sess,
523                 impl_m_span,
524                 E0185,
525                 "method `{}` has a `{}` declaration in the impl, but not in the trait",
526                 trait_m.ident,
527                 self_descr
528             );
529             err.span_label(impl_m_span, format!("`{}` used in impl", self_descr));
530             if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
531                 err.span_label(span, format!("trait method declared without `{}`", self_descr));
532             } else {
533                 err.note_trait_signature(trait_m.ident.to_string(), trait_m.signature(tcx));
534             }
535             err.emit();
536             return Err(ErrorReported);
537         }
538
539         (true, false) => {
540             let self_descr = self_string(trait_m);
541             let mut err = struct_span_err!(
542                 tcx.sess,
543                 impl_m_span,
544                 E0186,
545                 "method `{}` has a `{}` declaration in the trait, but not in the impl",
546                 trait_m.ident,
547                 self_descr
548             );
549             err.span_label(impl_m_span, format!("expected `{}` in impl", self_descr));
550             if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
551                 err.span_label(span, format!("`{}` used in trait", self_descr));
552             } else {
553                 err.note_trait_signature(trait_m.ident.to_string(), trait_m.signature(tcx));
554             }
555             err.emit();
556             return Err(ErrorReported);
557         }
558     }
559
560     Ok(())
561 }
562
563 fn compare_number_of_generics<'tcx>(
564     tcx: TyCtxt<'tcx>,
565     impl_: &ty::AssocItem,
566     _impl_span: Span,
567     trait_: &ty::AssocItem,
568     trait_span: Option<Span>,
569 ) -> Result<(), ErrorReported> {
570     let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
571     let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();
572
573     let matchings = [
574         ("type", trait_own_counts.types, impl_own_counts.types),
575         ("const", trait_own_counts.consts, impl_own_counts.consts),
576     ];
577
578     let item_kind = assoc_item_kind_str(impl_);
579
580     let mut err_occurred = false;
581     for (kind, trait_count, impl_count) in matchings {
582         if impl_count != trait_count {
583             err_occurred = true;
584
585             let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
586                 let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
587                 let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
588                 if trait_item.generics.params.is_empty() {
589                     (Some(vec![trait_item.generics.span]), vec![])
590                 } else {
591                     let arg_spans: Vec<Span> =
592                         trait_item.generics.params.iter().map(|p| p.span).collect();
593                     let impl_trait_spans: Vec<Span> = trait_item
594                         .generics
595                         .params
596                         .iter()
597                         .filter_map(|p| match p.kind {
598                             GenericParamKind::Type {
599                                 synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
600                                 ..
601                             } => Some(p.span),
602                             _ => None,
603                         })
604                         .collect();
605                     (Some(arg_spans), impl_trait_spans)
606                 }
607             } else {
608                 (trait_span.map(|s| vec![s]), vec![])
609             };
610
611             let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local());
612             let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
613             let impl_item_impl_trait_spans: Vec<Span> = impl_item
614                 .generics
615                 .params
616                 .iter()
617                 .filter_map(|p| match p.kind {
618                     GenericParamKind::Type {
619                         synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
620                         ..
621                     } => Some(p.span),
622                     _ => None,
623                 })
624                 .collect();
625             let spans = impl_item.generics.spans();
626             let span = spans.primary_span();
627
628             let mut err = tcx.sess.struct_span_err_with_code(
629                 spans,
630                 &format!(
631                     "{} `{}` has {} {kind} parameter{} but its trait \
632                      declaration has {} {kind} parameter{}",
633                     item_kind,
634                     trait_.ident,
635                     impl_count,
636                     pluralize!(impl_count),
637                     trait_count,
638                     pluralize!(trait_count),
639                     kind = kind,
640                 ),
641                 DiagnosticId::Error("E0049".into()),
642             );
643
644             let mut suffix = None;
645
646             if let Some(spans) = trait_spans {
647                 let mut spans = spans.iter();
648                 if let Some(span) = spans.next() {
649                     err.span_label(
650                         *span,
651                         format!(
652                             "expected {} {} parameter{}",
653                             trait_count,
654                             kind,
655                             pluralize!(trait_count),
656                         ),
657                     );
658                 }
659                 for span in spans {
660                     err.span_label(*span, "");
661                 }
662             } else {
663                 suffix = Some(format!(", expected {}", trait_count));
664             }
665
666             if let Some(span) = span {
667                 err.span_label(
668                     span,
669                     format!(
670                         "found {} {} parameter{}{}",
671                         impl_count,
672                         kind,
673                         pluralize!(impl_count),
674                         suffix.unwrap_or_else(String::new),
675                     ),
676                 );
677             }
678
679             for span in impl_trait_spans.iter().chain(impl_item_impl_trait_spans.iter()) {
680                 err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
681             }
682
683             err.emit();
684         }
685     }
686
687     if err_occurred { Err(ErrorReported) } else { Ok(()) }
688 }
689
690 fn compare_number_of_method_arguments<'tcx>(
691     tcx: TyCtxt<'tcx>,
692     impl_m: &ty::AssocItem,
693     impl_m_span: Span,
694     trait_m: &ty::AssocItem,
695     trait_item_span: Option<Span>,
696 ) -> Result<(), ErrorReported> {
697     let impl_m_fty = tcx.fn_sig(impl_m.def_id);
698     let trait_m_fty = tcx.fn_sig(trait_m.def_id);
699     let trait_number_args = trait_m_fty.inputs().skip_binder().len();
700     let impl_number_args = impl_m_fty.inputs().skip_binder().len();
701     if trait_number_args != impl_number_args {
702         let trait_span = if let Some(def_id) = trait_m.def_id.as_local() {
703             let trait_id = tcx.hir().local_def_id_to_hir_id(def_id);
704             match tcx.hir().expect_trait_item(trait_id).kind {
705                 TraitItemKind::Fn(ref trait_m_sig, _) => {
706                     let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
707                     if let Some(arg) = trait_m_sig.decl.inputs.get(pos) {
708                         Some(if pos == 0 {
709                             arg.span
710                         } else {
711                             arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())
712                         })
713                     } else {
714                         trait_item_span
715                     }
716                 }
717                 _ => bug!("{:?} is not a method", impl_m),
718             }
719         } else {
720             trait_item_span
721         };
722         let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
723         let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
724             ImplItemKind::Fn(ref impl_m_sig, _) => {
725                 let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
726                 if let Some(arg) = impl_m_sig.decl.inputs.get(pos) {
727                     if pos == 0 {
728                         arg.span
729                     } else {
730                         arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
731                     }
732                 } else {
733                     impl_m_span
734                 }
735             }
736             _ => bug!("{:?} is not a method", impl_m),
737         };
738         let mut err = struct_span_err!(
739             tcx.sess,
740             impl_span,
741             E0050,
742             "method `{}` has {} but the declaration in \
743                                         trait `{}` has {}",
744             trait_m.ident,
745             potentially_plural_count(impl_number_args, "parameter"),
746             tcx.def_path_str(trait_m.def_id),
747             trait_number_args
748         );
749         if let Some(trait_span) = trait_span {
750             err.span_label(
751                 trait_span,
752                 format!(
753                     "trait requires {}",
754                     potentially_plural_count(trait_number_args, "parameter")
755                 ),
756             );
757         } else {
758             err.note_trait_signature(trait_m.ident.to_string(), trait_m.signature(tcx));
759         }
760         err.span_label(
761             impl_span,
762             format!(
763                 "expected {}, found {}",
764                 potentially_plural_count(trait_number_args, "parameter"),
765                 impl_number_args
766             ),
767         );
768         err.emit();
769         return Err(ErrorReported);
770     }
771
772     Ok(())
773 }
774
775 fn compare_synthetic_generics<'tcx>(
776     tcx: TyCtxt<'tcx>,
777     impl_m: &ty::AssocItem,
778     trait_m: &ty::AssocItem,
779 ) -> Result<(), ErrorReported> {
780     // FIXME(chrisvittal) Clean up this function, list of FIXME items:
781     //     1. Better messages for the span labels
782     //     2. Explanation as to what is going on
783     // If we get here, we already have the same number of generics, so the zip will
784     // be okay.
785     let mut error_found = false;
786     let impl_m_generics = tcx.generics_of(impl_m.def_id);
787     let trait_m_generics = tcx.generics_of(trait_m.def_id);
788     let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
789         GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
790         GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
791     });
792     let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| match param.kind {
793         GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
794         GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
795     });
796     for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in
797         iter::zip(impl_m_type_params, trait_m_type_params)
798     {
799         if impl_synthetic != trait_synthetic {
800             let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id.expect_local());
801             let impl_span = tcx.hir().span(impl_hir_id);
802             let trait_span = tcx.def_span(trait_def_id);
803             let mut err = struct_span_err!(
804                 tcx.sess,
805                 impl_span,
806                 E0643,
807                 "method `{}` has incompatible signature for trait",
808                 trait_m.ident
809             );
810             err.span_label(trait_span, "declaration in trait here");
811             match (impl_synthetic, trait_synthetic) {
812                 // The case where the impl method uses `impl Trait` but the trait method uses
813                 // explicit generics
814                 (Some(hir::SyntheticTyParamKind::ImplTrait), None) => {
815                     err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
816                     (|| {
817                         // try taking the name from the trait impl
818                         // FIXME: this is obviously suboptimal since the name can already be used
819                         // as another generic argument
820                         let new_name = tcx.sess.source_map().span_to_snippet(trait_span).ok()?;
821                         let trait_m = trait_m.def_id.as_local()?;
822                         let trait_m = tcx.hir().trait_item(hir::TraitItemId { def_id: trait_m });
823
824                         let impl_m = impl_m.def_id.as_local()?;
825                         let impl_m = tcx.hir().impl_item(hir::ImplItemId { def_id: impl_m });
826
827                         // in case there are no generics, take the spot between the function name
828                         // and the opening paren of the argument list
829                         let new_generics_span =
830                             tcx.sess.source_map().generate_fn_name_span(impl_span)?.shrink_to_hi();
831                         // in case there are generics, just replace them
832                         let generics_span =
833                             impl_m.generics.span.substitute_dummy(new_generics_span);
834                         // replace with the generics from the trait
835                         let new_generics =
836                             tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?;
837
838                         err.multipart_suggestion(
839                             "try changing the `impl Trait` argument to a generic parameter",
840                             vec![
841                                 // replace `impl Trait` with `T`
842                                 (impl_span, new_name),
843                                 // replace impl method generics with trait method generics
844                                 // This isn't quite right, as users might have changed the names
845                                 // of the generics, but it works for the common case
846                                 (generics_span, new_generics),
847                             ],
848                             Applicability::MaybeIncorrect,
849                         );
850                         Some(())
851                     })();
852                 }
853                 // The case where the trait method uses `impl Trait`, but the impl method uses
854                 // explicit generics.
855                 (None, Some(hir::SyntheticTyParamKind::ImplTrait)) => {
856                     err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
857                     (|| {
858                         let impl_m = impl_m.def_id.as_local()?;
859                         let impl_m = tcx.hir().impl_item(hir::ImplItemId { def_id: impl_m });
860                         let input_tys = match impl_m.kind {
861                             hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
862                             _ => unreachable!(),
863                         };
864                         struct Visitor(Option<Span>, hir::def_id::DefId);
865                         impl<'v> intravisit::Visitor<'v> for Visitor {
866                             fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
867                                 intravisit::walk_ty(self, ty);
868                                 if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) =
869                                     ty.kind
870                                 {
871                                     if let Res::Def(DefKind::TyParam, def_id) = path.res {
872                                         if def_id == self.1 {
873                                             self.0 = Some(ty.span);
874                                         }
875                                     }
876                                 }
877                             }
878                             type Map = intravisit::ErasedMap<'v>;
879                             fn nested_visit_map(
880                                 &mut self,
881                             ) -> intravisit::NestedVisitorMap<Self::Map>
882                             {
883                                 intravisit::NestedVisitorMap::None
884                             }
885                         }
886                         let mut visitor = Visitor(None, impl_def_id);
887                         for ty in input_tys {
888                             intravisit::Visitor::visit_ty(&mut visitor, ty);
889                         }
890                         let span = visitor.0?;
891
892                         let bounds =
893                             impl_m.generics.params.iter().find_map(|param| match param.kind {
894                                 GenericParamKind::Lifetime { .. } => None,
895                                 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
896                                     if param.hir_id == impl_hir_id {
897                                         Some(&param.bounds)
898                                     } else {
899                                         None
900                                     }
901                                 }
902                             })?;
903                         let bounds = bounds.first()?.span().to(bounds.last()?.span());
904                         let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?;
905
906                         err.multipart_suggestion(
907                             "try removing the generic parameter and using `impl Trait` instead",
908                             vec![
909                                 // delete generic parameters
910                                 (impl_m.generics.span, String::new()),
911                                 // replace param usage with `impl Trait`
912                                 (span, format!("impl {}", bounds)),
913                             ],
914                             Applicability::MaybeIncorrect,
915                         );
916                         Some(())
917                     })();
918                 }
919                 _ => unreachable!(),
920             }
921             err.emit();
922             error_found = true;
923         }
924     }
925     if error_found { Err(ErrorReported) } else { Ok(()) }
926 }
927
928 fn compare_const_param_types<'tcx>(
929     tcx: TyCtxt<'tcx>,
930     impl_m: &ty::AssocItem,
931     trait_m: &ty::AssocItem,
932     trait_item_span: Option<Span>,
933 ) -> Result<(), ErrorReported> {
934     let const_params_of = |def_id| {
935         tcx.generics_of(def_id).params.iter().filter_map(|param| match param.kind {
936             GenericParamDefKind::Const { .. } => Some(param.def_id),
937             _ => None,
938         })
939     };
940     let const_params_impl = const_params_of(impl_m.def_id);
941     let const_params_trait = const_params_of(trait_m.def_id);
942
943     for (const_param_impl, const_param_trait) in iter::zip(const_params_impl, const_params_trait) {
944         let impl_ty = tcx.type_of(const_param_impl);
945         let trait_ty = tcx.type_of(const_param_trait);
946         if impl_ty != trait_ty {
947             let (impl_span, impl_ident) = match tcx.hir().get_if_local(const_param_impl) {
948                 Some(hir::Node::GenericParam(hir::GenericParam { span, name, .. })) => (
949                     span,
950                     match name {
951                         hir::ParamName::Plain(ident) => Some(ident),
952                         _ => None,
953                     },
954                 ),
955                 other => bug!(
956                     "expected GenericParam, found {:?}",
957                     other.map_or_else(|| "nothing".to_string(), |n| format!("{:?}", n))
958                 ),
959             };
960             let trait_span = match tcx.hir().get_if_local(const_param_trait) {
961                 Some(hir::Node::GenericParam(hir::GenericParam { span, .. })) => Some(span),
962                 _ => None,
963             };
964             let mut err = struct_span_err!(
965                 tcx.sess,
966                 *impl_span,
967                 E0053,
968                 "method `{}` has an incompatible const parameter type for trait",
969                 trait_m.ident
970             );
971             err.span_note(
972                 trait_span.map_or_else(|| trait_item_span.unwrap_or(*impl_span), |span| *span),
973                 &format!(
974                     "the const parameter{} has type `{}`, but the declaration \
975                               in trait `{}` has type `{}`",
976                     &impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{}`", ident)),
977                     impl_ty,
978                     tcx.def_path_str(trait_m.def_id),
979                     trait_ty
980                 ),
981             );
982             err.emit();
983             return Err(ErrorReported);
984         }
985     }
986
987     Ok(())
988 }
989
990 crate fn compare_const_impl<'tcx>(
991     tcx: TyCtxt<'tcx>,
992     impl_c: &ty::AssocItem,
993     impl_c_span: Span,
994     trait_c: &ty::AssocItem,
995     impl_trait_ref: ty::TraitRef<'tcx>,
996 ) {
997     debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
998
999     tcx.infer_ctxt().enter(|infcx| {
1000         let param_env = tcx.param_env(impl_c.def_id);
1001         let inh = Inherited::new(infcx, impl_c.def_id.expect_local());
1002         let infcx = &inh.infcx;
1003
1004         // The below is for the most part highly similar to the procedure
1005         // for methods above. It is simpler in many respects, especially
1006         // because we shouldn't really have to deal with lifetimes or
1007         // predicates. In fact some of this should probably be put into
1008         // shared functions because of DRY violations...
1009         let trait_to_impl_substs = impl_trait_ref.substs;
1010
1011         // Create a parameter environment that represents the implementation's
1012         // method.
1013         let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_c.def_id.expect_local());
1014
1015         // Compute placeholder form of impl and trait const tys.
1016         let impl_ty = tcx.type_of(impl_c.def_id);
1017         let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
1018         let mut cause = ObligationCause::new(
1019             impl_c_span,
1020             impl_c_hir_id,
1021             ObligationCauseCode::CompareImplConstObligation,
1022         );
1023
1024         // There is no "body" here, so just pass dummy id.
1025         let impl_ty =
1026             inh.normalize_associated_types_in(impl_c_span, impl_c_hir_id, param_env, impl_ty);
1027
1028         debug!("compare_const_impl: impl_ty={:?}", impl_ty);
1029
1030         let trait_ty =
1031             inh.normalize_associated_types_in(impl_c_span, impl_c_hir_id, param_env, trait_ty);
1032
1033         debug!("compare_const_impl: trait_ty={:?}", trait_ty);
1034
1035         let err = infcx
1036             .at(&cause, param_env)
1037             .sup(trait_ty, impl_ty)
1038             .map(|ok| inh.register_infer_ok_obligations(ok));
1039
1040         if let Err(terr) = err {
1041             debug!(
1042                 "checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
1043                 impl_ty, trait_ty
1044             );
1045
1046             // Locate the Span containing just the type of the offending impl
1047             match tcx.hir().expect_impl_item(impl_c_hir_id).kind {
1048                 ImplItemKind::Const(ref ty, _) => cause.make_mut().span = ty.span,
1049                 _ => bug!("{:?} is not a impl const", impl_c),
1050             }
1051
1052             let mut diag = struct_span_err!(
1053                 tcx.sess,
1054                 cause.span,
1055                 E0326,
1056                 "implemented const `{}` has an incompatible type for trait",
1057                 trait_c.ident
1058             );
1059
1060             let trait_c_hir_id =
1061                 trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
1062             let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| {
1063                 // Add a label to the Span containing just the type of the const
1064                 match tcx.hir().expect_trait_item(trait_c_hir_id).kind {
1065                     TraitItemKind::Const(ref ty, _) => ty.span,
1066                     _ => bug!("{:?} is not a trait const", trait_c),
1067                 }
1068             });
1069
1070             infcx.note_type_err(
1071                 &mut diag,
1072                 &cause,
1073                 trait_c_span.map(|span| (span, "type in trait".to_owned())),
1074                 Some(infer::ValuePairs::Types(ExpectedFound {
1075                     expected: trait_ty,
1076                     found: impl_ty,
1077                 })),
1078                 &terr,
1079             );
1080             diag.emit();
1081         }
1082
1083         // Check that all obligations are satisfied by the implementation's
1084         // version.
1085         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
1086             infcx.report_fulfillment_errors(errors, None, false);
1087             return;
1088         }
1089
1090         let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id);
1091         fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]);
1092     });
1093 }
1094
1095 crate fn compare_ty_impl<'tcx>(
1096     tcx: TyCtxt<'tcx>,
1097     impl_ty: &ty::AssocItem,
1098     impl_ty_span: Span,
1099     trait_ty: &ty::AssocItem,
1100     impl_trait_ref: ty::TraitRef<'tcx>,
1101     trait_item_span: Option<Span>,
1102 ) {
1103     debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
1104
1105     let _: Result<(), ErrorReported> = (|| {
1106         compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
1107
1108         compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
1109
1110         check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
1111     })();
1112 }
1113
1114 /// The equivalent of [compare_predicate_entailment], but for associated types
1115 /// instead of associated functions.
1116 fn compare_type_predicate_entailment<'tcx>(
1117     tcx: TyCtxt<'tcx>,
1118     impl_ty: &ty::AssocItem,
1119     impl_ty_span: Span,
1120     trait_ty: &ty::AssocItem,
1121     impl_trait_ref: ty::TraitRef<'tcx>,
1122 ) -> Result<(), ErrorReported> {
1123     let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
1124     let trait_to_impl_substs =
1125         impl_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
1126
1127     let impl_ty_generics = tcx.generics_of(impl_ty.def_id);
1128     let trait_ty_generics = tcx.generics_of(trait_ty.def_id);
1129     let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
1130     let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
1131
1132     check_region_bounds_on_impl_item(
1133         tcx,
1134         impl_ty_span,
1135         impl_ty,
1136         trait_ty,
1137         &trait_ty_generics,
1138         &impl_ty_generics,
1139     )?;
1140
1141     let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_substs);
1142
1143     if impl_ty_own_bounds.is_empty() {
1144         // Nothing to check.
1145         return Ok(());
1146     }
1147
1148     // This `HirId` should be used for the `body_id` field on each
1149     // `ObligationCause` (and the `FnCtxt`). This is what
1150     // `regionck_item` expects.
1151     let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
1152     let cause = ObligationCause::new(
1153         impl_ty_span,
1154         impl_ty_hir_id,
1155         ObligationCauseCode::CompareImplTypeObligation {
1156             item_name: impl_ty.ident.name,
1157             impl_item_def_id: impl_ty.def_id,
1158             trait_item_def_id: trait_ty.def_id,
1159         },
1160     );
1161
1162     debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
1163
1164     // The predicates declared by the impl definition, the trait and the
1165     // associated type in the trait are assumed.
1166     let impl_predicates = tcx.predicates_of(impl_ty_predicates.parent.unwrap());
1167     let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
1168     hybrid_preds
1169         .predicates
1170         .extend(trait_ty_predicates.instantiate_own(tcx, trait_to_impl_substs).predicates);
1171
1172     debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
1173
1174     let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
1175     let param_env =
1176         ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing);
1177     let param_env = traits::normalize_param_env_or_error(
1178         tcx,
1179         impl_ty.def_id,
1180         param_env,
1181         normalize_cause.clone(),
1182     );
1183     tcx.infer_ctxt().enter(|infcx| {
1184         let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
1185         let infcx = &inh.infcx;
1186
1187         debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
1188
1189         let mut selcx = traits::SelectionContext::new(&infcx);
1190
1191         for predicate in impl_ty_own_bounds.predicates {
1192             let traits::Normalized { value: predicate, obligations } =
1193                 traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
1194
1195             inh.register_predicates(obligations);
1196             inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate));
1197         }
1198
1199         // Check that all obligations are satisfied by the implementation's
1200         // version.
1201         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
1202             infcx.report_fulfillment_errors(errors, None, false);
1203             return Err(ErrorReported);
1204         }
1205
1206         // Finally, resolve all regions. This catches wily misuses of
1207         // lifetime parameters.
1208         let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
1209         fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
1210
1211         Ok(())
1212     })
1213 }
1214
1215 /// Validate that `ProjectionCandidate`s created for this associated type will
1216 /// be valid.
1217 ///
1218 /// Usually given
1219 ///
1220 /// trait X { type Y: Copy } impl X for T { type Y = S; }
1221 ///
1222 /// We are able to normalize `<T as X>::U` to `S`, and so when we check the
1223 /// impl is well-formed we have to prove `S: Copy`.
1224 ///
1225 /// For default associated types the normalization is not possible (the value
1226 /// from the impl could be overridden). We also can't normalize generic
1227 /// associated types (yet) because they contain bound parameters.
1228 #[tracing::instrument(level = "debug", skip(tcx))]
1229 pub fn check_type_bounds<'tcx>(
1230     tcx: TyCtxt<'tcx>,
1231     trait_ty: &ty::AssocItem,
1232     impl_ty: &ty::AssocItem,
1233     impl_ty_span: Span,
1234     impl_trait_ref: ty::TraitRef<'tcx>,
1235 ) -> Result<(), ErrorReported> {
1236     // Given
1237     //
1238     // impl<A, B> Foo<u32> for (A, B) {
1239     //     type Bar<C> =...
1240     // }
1241     //
1242     // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
1243     // - `impl_ty_substs` would be `[A, B, ^0.0]`
1244     // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
1245     //    the *trait* with the generic associated type parameters (as bound vars).
1246     let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id);
1247     let mut substs = smallvec::SmallVec::with_capacity(defs.count());
1248     if let Some(def_id) = defs.parent {
1249         let parent_defs = tcx.generics_of(def_id);
1250         InternalSubsts::fill_item(&mut substs, tcx, parent_defs, &mut |param, _| {
1251             tcx.mk_param_from_def(param)
1252         });
1253     }
1254     let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
1255         smallvec::SmallVec::with_capacity(defs.count());
1256     InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
1257         GenericParamDefKind::Type { .. } => {
1258             let kind = ty::BoundTyKind::Param(param.name);
1259             let bound_var = ty::BoundVariableKind::Ty(kind);
1260             bound_vars.push(bound_var);
1261             tcx.mk_ty(ty::Bound(
1262                 ty::INNERMOST,
1263                 ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
1264             ))
1265             .into()
1266         }
1267         GenericParamDefKind::Lifetime => {
1268             let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
1269             let bound_var = ty::BoundVariableKind::Region(kind);
1270             bound_vars.push(bound_var);
1271             tcx.mk_region(ty::ReLateBound(
1272                 ty::INNERMOST,
1273                 ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
1274             ))
1275             .into()
1276         }
1277         GenericParamDefKind::Const { .. } => {
1278             let bound_var = ty::BoundVariableKind::Const;
1279             bound_vars.push(bound_var);
1280             tcx.mk_const(ty::Const {
1281                 ty: tcx.type_of(param.def_id),
1282                 val: ty::ConstKind::Bound(
1283                     ty::INNERMOST,
1284                     ty::BoundVar::from_usize(bound_vars.len() - 1),
1285                 ),
1286             })
1287             .into()
1288         }
1289     });
1290     let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
1291     let impl_ty_substs = tcx.intern_substs(&substs);
1292
1293     let rebased_substs =
1294         impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
1295     let impl_ty_value = tcx.type_of(impl_ty.def_id);
1296
1297     let param_env = tcx.param_env(impl_ty.def_id);
1298
1299     // When checking something like
1300     //
1301     // trait X { type Y: PartialEq<<Self as X>::Y> }
1302     // impl X for T { default type Y = S; }
1303     //
1304     // We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
1305     // we want <T as X>::Y to normalize to S. This is valid because we are
1306     // checking the default value specifically here. Add this equality to the
1307     // ParamEnv for normalization specifically.
1308     let normalize_param_env = {
1309         let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
1310         match impl_ty_value.kind() {
1311             ty::Projection(proj)
1312                 if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs =>
1313             {
1314                 // Don't include this predicate if the projected type is
1315                 // exactly the same as the projection. This can occur in
1316                 // (somewhat dubious) code like this:
1317                 //
1318                 // impl<T> X for T where T: X { type Y = <T as X>::Y; }
1319             }
1320             _ => predicates.push(
1321                 ty::Binder::bind_with_vars(
1322                     ty::ProjectionPredicate {
1323                         projection_ty: ty::ProjectionTy {
1324                             item_def_id: trait_ty.def_id,
1325                             substs: rebased_substs,
1326                         },
1327                         ty: impl_ty_value,
1328                     },
1329                     bound_vars,
1330                 )
1331                 .to_predicate(tcx),
1332             ),
1333         };
1334         ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
1335     };
1336     debug!(?normalize_param_env);
1337
1338     let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
1339     let rebased_substs =
1340         impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
1341
1342     tcx.infer_ctxt().enter(move |infcx| {
1343         let constness = impl_ty
1344             .container
1345             .impl_def_id()
1346             .map(|did| tcx.impl_constness(did))
1347             .unwrap_or(hir::Constness::NotConst);
1348
1349         let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness);
1350         let infcx = &inh.infcx;
1351         let mut selcx = traits::SelectionContext::new(&infcx);
1352
1353         let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
1354         let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
1355         let mk_cause = |span| {
1356             ObligationCause::new(
1357                 impl_ty_span,
1358                 impl_ty_hir_id,
1359                 ObligationCauseCode::BindingObligation(trait_ty.def_id, span),
1360             )
1361         };
1362
1363         let obligations = tcx
1364             .explicit_item_bounds(trait_ty.def_id)
1365             .iter()
1366             .map(|&(bound, span)| {
1367                 debug!(?bound);
1368                 let concrete_ty_bound = bound.subst(tcx, rebased_substs);
1369                 debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
1370
1371                 traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
1372             })
1373             .collect();
1374         debug!("check_type_bounds: item_bounds={:?}", obligations);
1375
1376         for mut obligation in util::elaborate_obligations(tcx, obligations) {
1377             let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
1378                 &mut selcx,
1379                 normalize_param_env,
1380                 normalize_cause.clone(),
1381                 obligation.predicate,
1382             );
1383             debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
1384             obligation.predicate = normalized_predicate;
1385
1386             inh.register_predicates(obligations);
1387             inh.register_predicate(obligation);
1388         }
1389
1390         // Check that all obligations are satisfied by the implementation's
1391         // version.
1392         if let Err(ref errors) =
1393             inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
1394         {
1395             infcx.report_fulfillment_errors(errors, None, false);
1396             return Err(ErrorReported);
1397         }
1398
1399         // Finally, resolve all regions. This catches wily misuses of
1400         // lifetime parameters.
1401         let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
1402         let implied_bounds = match impl_ty.container {
1403             ty::TraitContainer(_) => vec![],
1404             ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
1405         };
1406         fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds);
1407
1408         Ok(())
1409     })
1410 }
1411
1412 fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
1413     match impl_item.kind {
1414         ty::AssocKind::Const => "const",
1415         ty::AssocKind::Fn => "method",
1416         ty::AssocKind::Type => "type",
1417     }
1418 }