Skip to content

Commit 822a5d3

Browse files
committed
In trait selection, before we create inference variables, try to figure
out what types/regions we should use just by matching up the trait reference from the impl with the trait reference we need. Fixes rust-lang#29844.
1 parent f0264a0 commit 822a5d3

File tree

7 files changed

+361
-21
lines changed

7 files changed

+361
-21
lines changed

src/librustc/middle/infer/error_reporting.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,18 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
655655
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
656656
self.report_and_explain_type_error(trace, &terr);
657657
}
658+
infer::TraitMatch(span) => {
659+
// TODO oh dear god the terribleness
660+
self.tcx.sess.span_err(span, "lifetime mismatch during trait processing");
661+
self.tcx.note_and_explain_region(
662+
"...the impl or where clause references the lifetime",
663+
sub,
664+
"...");
665+
self.tcx.note_and_explain_region(
666+
"...but the lifetime is required",
667+
sup,
668+
"");
669+
}
658670
infer::Reborrow(span) => {
659671
span_err!(self.tcx.sess, span, E0312,
660672
"lifetime of reference outlines \
@@ -1611,12 +1623,9 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
16111623
infer::ExprAssignable(_) => {
16121624
"expression is assignable"
16131625
}
1614-
infer::RelateTraitRefs(_) => {
1626+
infer::TraitMatchTypes(_) => {
16151627
"traits are compatible"
16161628
}
1617-
infer::RelateSelfType(_) => {
1618-
"self type matches impl self type"
1619-
}
16201629
infer::RelateOutputImplTypes(_) => {
16211630
"trait type parameters matches those \
16221631
specified on the impl"
@@ -1656,6 +1665,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
16561665
}
16571666
}
16581667
}
1668+
infer::TraitMatch(span) => {
1669+
self.tcx.sess.span_note(
1670+
span,
1671+
"...so that the required trait is satisfied");
1672+
}
16591673
infer::Reborrow(span) => {
16601674
self.tcx.sess.span_note(
16611675
span,

src/librustc/middle/infer/mod.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,8 @@ pub enum TypeOrigin {
125125
// FIXME(eddyb) #11161 is the original Expr required?
126126
ExprAssignable(Span),
127127

128-
// Relating trait refs when resolving vtables
129-
RelateTraitRefs(Span),
130-
131-
// Relating self types when resolving vtables
132-
RelateSelfType(Span),
128+
// Relating types in an impl
129+
TraitMatchTypes(Span),
133130

134131
// Relating trait type parameters to those found in impl etc
135132
RelateOutputImplTypes(Span),
@@ -154,10 +151,9 @@ impl TypeOrigin {
154151
fn as_str(&self) -> &'static str {
155152
match self {
156153
&TypeOrigin::Misc(_) |
157-
&TypeOrigin::RelateSelfType(_) |
154+
&TypeOrigin::TraitMatchTypes(_) |
158155
&TypeOrigin::RelateOutputImplTypes(_) |
159156
&TypeOrigin::ExprAssignable(_) => "mismatched types",
160-
&TypeOrigin::RelateTraitRefs(_) => "mismatched traits",
161157
&TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait",
162158
&TypeOrigin::MatchExpressionArm(_, _, source) => match source {
163159
hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
@@ -205,6 +201,9 @@ pub enum SubregionOrigin<'tcx> {
205201
// error.
206202
RFC1214Subregion(Rc<SubregionOrigin<'tcx>>),
207203

204+
// Arose as part of trait matching
205+
TraitMatch(Span),
206+
208207
// Arose from a subtyping relation
209208
Subtype(TypeTrace<'tcx>),
210209

@@ -842,6 +841,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
842841
self.region_vars.add_given(sub, sup);
843842
}
844843

844+
pub fn equate_regions(&self,
845+
origin: SubregionOrigin<'tcx>,
846+
a: ty::Region,
847+
b: ty::Region)
848+
{
849+
self.region_vars.make_eqregion(origin, a, b)
850+
}
851+
845852
pub fn sub_types(&self,
846853
a_is_expected: bool,
847854
origin: TypeOrigin,
@@ -1546,8 +1553,7 @@ impl TypeOrigin {
15461553
MethodCompatCheck(span) => span,
15471554
ExprAssignable(span) => span,
15481555
Misc(span) => span,
1549-
RelateTraitRefs(span) => span,
1550-
RelateSelfType(span) => span,
1556+
TraitMatchTypes(span) => span,
15511557
RelateOutputImplTypes(span) => span,
15521558
MatchExpressionArm(match_span, _, _) => match_span,
15531559
IfExpression(span) => span,
@@ -1563,6 +1569,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
15631569
match *self {
15641570
RFC1214Subregion(ref a) => a.span(),
15651571
Subtype(ref a) => a.span(),
1572+
TraitMatch(a) => a,
15661573
InfStackClosure(a) => a,
15671574
InvokeClosure(a) => a,
15681575
DerefPointer(a) => a,

src/librustc/middle/subst.rs

+4
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,10 @@ impl<T> VecPerParamSpace<T> {
385385
&self.get_slice(space)[index]
386386
}
387387

388+
pub fn get_mut(&mut self, space: ParamSpace, index: usize) -> &mut T {
389+
&mut self.get_mut_slice(space)[index]
390+
}
391+
388392
pub fn iter<'a>(&'a self) -> Iter<'a,T> {
389393
self.content.iter()
390394
}

src/librustc/middle/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ mod project;
6767
mod object_safety;
6868
mod select;
6969
mod structural_impls;
70+
mod ty_match;
7071
mod ty_recur;
7172
mod util;
7273

src/librustc/middle/traits/select.rs

+23-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use super::TraitNotObjectSafe;
2929
use super::RFC1214Warning;
3030
use super::Selection;
3131
use super::SelectionResult;
32+
use super::ty_match;
3233
use super::ty_recur;
3334
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
3435
VtableFnPointer, VtableObject, VtableDefaultImpl};
@@ -2675,12 +2676,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
26752676
snapshot);
26762677
let skol_obligation_trait_ref = skol_obligation.trait_ref;
26772678

2678-
let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
2679-
obligation.cause.span,
2680-
impl_def_id);
2679+
let impl_generics = self.tcx().lookup_item_type(impl_def_id).generics;
2680+
let impl_substs =
2681+
match ty_match::perform_match(self.infcx,
2682+
&impl_generics,
2683+
obligation.cause.span,
2684+
&impl_trait_ref,
2685+
&skol_obligation_trait_ref) {
2686+
Ok(substs) => substs,
2687+
Err(e) => {
2688+
debug!("match_impl: perform_match failed due to `{}`", e);
2689+
return Err(());
2690+
}
2691+
};
2692+
2693+
// TODO Match computation creates a set of substitions, but
2694+
// doesn't guarantee that all necessary relations are
2695+
// established, particularly with regard to
2696+
// projections. Therefore, we also do the subtyping check here
2697+
// a second time. Obviously inefficient and suboptimal.
2698+
//
2699+
// TODO question: is the leak check sufficient now?
26812700

2682-
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
2683-
&impl_substs);
2701+
let impl_trait_ref = impl_trait_ref.subst(self.tcx(), &impl_substs);
26842702

26852703
let impl_trait_ref =
26862704
project::normalize_with_depth(self,

0 commit comments

Comments
 (0)