Skip to content

Commit e40beb3

Browse files
committed
Auto merge of #41913 - nikomatsakis:issue-41849-variance-cycle, r=eddyb
do not fetch variance for items when equating Fixes #41849. Problem was that evaluating the constant expression required evaluating a trait, which would equate types, which would request variance information, which it would then discard. However, computing the variance information would require determining the type of a field, which would evaluate the constant expression. (This problem will potentially arise *later* as we move to more sophisticated constants, however, where we need to check subtyping. We can tackle that when we come to it.) r? @eddyb
2 parents 2cc3358 + d22d1fe commit e40beb3

File tree

3 files changed

+84
-23
lines changed

3 files changed

+84
-23
lines changed

src/librustc/infer/equate.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111
use super::combine::{CombineFields, RelationDir};
1212
use super::{Subtype};
1313

14+
use hir::def_id::DefId;
15+
1416
use ty::{self, Ty, TyCtxt};
1517
use ty::TyVar;
16-
use ty::relate::{Relate, RelateResult, TypeRelation};
18+
use ty::subst::Substs;
19+
use ty::relate::{self, Relate, RelateResult, TypeRelation};
1720

1821
/// Ensures `a` is made equal to `b`. Returns `a` on success.
1922
pub struct Equate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@@ -38,6 +41,22 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
3841

3942
fn a_is_expected(&self) -> bool { self.a_is_expected }
4043

44+
fn relate_item_substs(&mut self,
45+
_item_def_id: DefId,
46+
a_subst: &'tcx Substs<'tcx>,
47+
b_subst: &'tcx Substs<'tcx>)
48+
-> RelateResult<'tcx, &'tcx Substs<'tcx>>
49+
{
50+
// NB: Once we are equating types, we don't care about
51+
// variance, so don't try to lookup the variance here. This
52+
// also avoids some cycles (e.g. #41849) since looking up
53+
// variance requires computing types which can require
54+
// performing trait matching (which then performs equality
55+
// unification).
56+
57+
relate::relate_substs(self, None, a_subst, b_subst)
58+
}
59+
4160
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
4261
_: ty::Variance,
4362
a: &T,

src/librustc/ty/relate.rs

+21-22
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,24 @@ pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized {
5151
Relate::relate(self, a, b)
5252
}
5353

54+
/// Relate the two substitutions for the given item. The default
55+
/// is to look up the variance for the item and proceed
56+
/// accordingly.
57+
fn relate_item_substs(&mut self,
58+
item_def_id: DefId,
59+
a_subst: &'tcx Substs<'tcx>,
60+
b_subst: &'tcx Substs<'tcx>)
61+
-> RelateResult<'tcx, &'tcx Substs<'tcx>>
62+
{
63+
debug!("relate_item_substs(item_def_id={:?}, a_subst={:?}, b_subst={:?})",
64+
item_def_id,
65+
a_subst,
66+
b_subst);
67+
68+
let opt_variances = self.tcx().variances_of(item_def_id);
69+
relate_substs(self, Some(&opt_variances), a_subst, b_subst)
70+
}
71+
5472
/// Switch variance for the purpose of relating `a` and `b`.
5573
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
5674
variance: ty::Variance,
@@ -109,25 +127,6 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
109127
}
110128
}
111129

112-
// substitutions are not themselves relatable without more context,
113-
// but they is an important subroutine for things that ARE relatable,
114-
// like traits etc.
115-
fn relate_item_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
116-
item_def_id: DefId,
117-
a_subst: &'tcx Substs<'tcx>,
118-
b_subst: &'tcx Substs<'tcx>)
119-
-> RelateResult<'tcx, &'tcx Substs<'tcx>>
120-
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
121-
{
122-
debug!("substs: item_def_id={:?} a_subst={:?} b_subst={:?}",
123-
item_def_id,
124-
a_subst,
125-
b_subst);
126-
127-
let opt_variances = relation.tcx().variances_of(item_def_id);
128-
relate_substs(relation, Some(&opt_variances), a_subst, b_subst)
129-
}
130-
131130
pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
132131
variances: Option<&Vec<ty::Variance>>,
133132
a_subst: &'tcx Substs<'tcx>,
@@ -291,7 +290,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
291290
if a.def_id != b.def_id {
292291
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
293292
} else {
294-
let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?;
293+
let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
295294
Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
296295
}
297296
}
@@ -308,7 +307,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
308307
if a.def_id != b.def_id {
309308
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
310309
} else {
311-
let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?;
310+
let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
312311
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
313312
}
314313
}
@@ -372,7 +371,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
372371
(&ty::TyAdt(a_def, a_substs), &ty::TyAdt(b_def, b_substs))
373372
if a_def == b_def =>
374373
{
375-
let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?;
374+
let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?;
376375
Ok(tcx.mk_adt(a_def, substs))
377376
}
378377

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Regression test for #41849.
12+
13+
use std::ops::Mul;
14+
15+
const C: usize = 1;
16+
const CAPACITY: usize = 1 * C;
17+
18+
struct A<X> {
19+
f: [X; CAPACITY],
20+
}
21+
22+
struct B<T> {
23+
f: T,
24+
}
25+
26+
impl<T> Mul for B<T> {
27+
type Output = Self;
28+
fn mul(self, _rhs: B<T>) -> Self::Output {
29+
self
30+
}
31+
}
32+
33+
impl<T> Mul<usize> for B<T> {
34+
type Output = Self;
35+
fn mul(self, _rhs: usize) -> Self::Output {
36+
self
37+
}
38+
}
39+
40+
fn main() {
41+
let a = A { f: [1] };
42+
let _ = B { f: a };
43+
}

0 commit comments

Comments
 (0)