1
1
use super :: potentially_plural_count;
2
2
use crate :: check:: regionck:: OutlivesEnvironmentExt ;
3
- use crate :: check:: wfcheck;
4
3
use crate :: errors:: LifetimesOrBoundsMismatchOnTrait ;
5
4
use rustc_data_structures:: fx:: FxHashSet ;
6
5
use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticId , ErrorGuaranteed } ;
@@ -71,6 +70,72 @@ pub(crate) fn compare_impl_method<'tcx>(
71
70
}
72
71
}
73
72
73
+ /// This function is best explained by example. Consider a trait:
74
+ ///
75
+ /// trait Trait<'t, T> {
76
+ /// // `trait_m`
77
+ /// fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
78
+ /// }
79
+ ///
80
+ /// And an impl:
81
+ ///
82
+ /// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
83
+ /// // `impl_m`
84
+ /// fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
85
+ /// }
86
+ ///
87
+ /// We wish to decide if those two method types are compatible.
88
+ /// For this we have to show that, assuming the bounds of the impl hold, the
89
+ /// bounds of `trait_m` imply the bounds of `impl_m`.
90
+ ///
91
+ /// We start out with `trait_to_impl_substs`, that maps the trait
92
+ /// type parameters to impl type parameters. This is taken from the
93
+ /// impl trait reference:
94
+ ///
95
+ /// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
96
+ ///
97
+ /// We create a mapping `dummy_substs` that maps from the impl type
98
+ /// parameters to fresh types and regions. For type parameters,
99
+ /// this is the identity transform, but we could as well use any
100
+ /// placeholder types. For regions, we convert from bound to free
101
+ /// regions (Note: but only early-bound regions, i.e., those
102
+ /// declared on the impl or used in type parameter bounds).
103
+ ///
104
+ /// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
105
+ ///
106
+ /// Now we can apply `placeholder_substs` to the type of the impl method
107
+ /// to yield a new function type in terms of our fresh, placeholder
108
+ /// types:
109
+ ///
110
+ /// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
111
+ ///
112
+ /// We now want to extract and substitute the type of the *trait*
113
+ /// method and compare it. To do so, we must create a compound
114
+ /// substitution by combining `trait_to_impl_substs` and
115
+ /// `impl_to_placeholder_substs`, and also adding a mapping for the method
116
+ /// type parameters. We extend the mapping to also include
117
+ /// the method parameters.
118
+ ///
119
+ /// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
120
+ ///
121
+ /// Applying this to the trait method type yields:
122
+ ///
123
+ /// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
124
+ ///
125
+ /// This type is also the same but the name of the bound region (`'a`
126
+ /// vs `'b`). However, the normal subtyping rules on fn types handle
127
+ /// this kind of equivalency just fine.
128
+ ///
129
+ /// We now use these substitutions to ensure that all declared bounds are
130
+ /// satisfied by the implementation's method.
131
+ ///
132
+ /// We do this by creating a parameter environment which contains a
133
+ /// substitution corresponding to `impl_to_placeholder_substs`. We then build
134
+ /// `trait_to_placeholder_substs` and use it to convert the predicates contained
135
+ /// in the `trait_m` generics to the placeholder form.
136
+ ///
137
+ /// Finally we register each of these predicates as an obligation and check that
138
+ /// they hold.
74
139
fn compare_predicate_entailment < ' tcx > (
75
140
tcx : TyCtxt < ' tcx > ,
76
141
impl_m : & ty:: AssocItem ,
@@ -97,69 +162,6 @@ fn compare_predicate_entailment<'tcx>(
97
162
} ,
98
163
) ;
99
164
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
165
// Create mapping from impl to placeholder.
164
166
let impl_to_placeholder_substs = InternalSubsts :: identity_for_item ( tcx, impl_m. def_id ) ;
165
167
@@ -1445,14 +1447,17 @@ pub fn check_type_bounds<'tcx>(
1445
1447
} ;
1446
1448
debug ! ( ?normalize_param_env) ;
1447
1449
1450
+ let impl_ty_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( impl_ty. def_id . expect_local ( ) ) ;
1448
1451
let impl_ty_substs = InternalSubsts :: identity_for_item ( tcx, impl_ty. def_id ) ;
1449
1452
let rebased_substs = impl_ty_substs. rebase_onto ( tcx, container_id, impl_trait_ref. substs ) ;
1450
1453
1451
1454
tcx. infer_ctxt ( ) . enter ( move |infcx| {
1452
1455
let ocx = ObligationCtxt :: new ( & infcx) ;
1453
1456
1457
+ let assumed_wf_types =
1458
+ ocx. assumed_wf_types ( param_env, impl_ty_span, impl_ty. def_id . expect_local ( ) ) ;
1459
+
1454
1460
let mut selcx = traits:: SelectionContext :: new ( & infcx) ;
1455
- let impl_ty_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( impl_ty. def_id . expect_local ( ) ) ;
1456
1461
let normalize_cause = ObligationCause :: new (
1457
1462
impl_ty_span,
1458
1463
impl_ty_hir_id,
@@ -1508,17 +1513,8 @@ pub fn check_type_bounds<'tcx>(
1508
1513
1509
1514
// Finally, resolve all regions. This catches wily misuses of
1510
1515
// lifetime parameters.
1511
- let implied_bounds = match impl_ty. container {
1512
- ty:: TraitContainer => FxHashSet :: default ( ) ,
1513
- ty:: ImplContainer => wfcheck:: impl_implied_bounds (
1514
- tcx,
1515
- param_env,
1516
- container_id. expect_local ( ) ,
1517
- impl_ty_span,
1518
- ) ,
1519
- } ;
1520
1516
let mut outlives_environment = OutlivesEnvironment :: new ( param_env) ;
1521
- outlives_environment. add_implied_bounds ( & infcx, implied_bounds , impl_ty_hir_id) ;
1517
+ outlives_environment. add_implied_bounds ( & infcx, assumed_wf_types , impl_ty_hir_id) ;
1522
1518
infcx. check_region_obligations_and_report_errors (
1523
1519
impl_ty. def_id . expect_local ( ) ,
1524
1520
& outlives_environment,
0 commit comments