Skip to content

Commit 8578fee

Browse files
committed
Don't use skolemized parameters but rather fresh variables in
coherence. Skolemized parameters wind up preventing unification. Surprised we had no test for this! Fixes #24241.
1 parent e326aa1 commit 8578fee

File tree

3 files changed

+49
-50
lines changed

3 files changed

+49
-50
lines changed

src/librustc/middle/traits/coherence.rs

+21-21
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use syntax::codemap::{DUMMY_SP, Span};
2626
use util::ppaux::Repr;
2727

2828
#[derive(Copy, Clone)]
29-
struct ParamIsLocal(bool);
29+
struct InferIsLocal(bool);
3030

3131
/// True if there exist types that satisfy both of the two given impls.
3232
pub fn overlapping_impls(infcx: &InferCtxt,
@@ -60,7 +60,7 @@ fn overlap(selcx: &mut SelectionContext,
6060

6161
let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx,
6262
a_def_id,
63-
util::free_substs_for_impl);
63+
util::fresh_type_vars_for_impl);
6464

6565
let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx,
6666
b_def_id,
@@ -104,7 +104,7 @@ pub fn trait_ref_is_knowable<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::TraitRe
104104

105105
// if the orphan rules pass, that means that no ancestor crate can
106106
// impl this, so it's up to us.
107-
if orphan_check_trait_ref(tcx, trait_ref, ParamIsLocal(false)).is_ok() {
107+
if orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(false)).is_ok() {
108108
debug!("trait_ref_is_knowable: orphan check passed");
109109
return true;
110110
}
@@ -126,7 +126,7 @@ pub fn trait_ref_is_knowable<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::TraitRe
126126
// implemented by an upstream crate, which means that the impl
127127
// must be visible to us, and -- since the trait is fundamental
128128
// -- we can test.
129-
orphan_check_trait_ref(tcx, trait_ref, ParamIsLocal(true)).is_err()
129+
orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(true)).is_err()
130130
}
131131

132132
type SubstsFn = for<'a,'tcx> fn(infcx: &InferCtxt<'a, 'tcx>,
@@ -196,16 +196,16 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
196196
return Ok(());
197197
}
198198

199-
orphan_check_trait_ref(tcx, &trait_ref, ParamIsLocal(false))
199+
orphan_check_trait_ref(tcx, &trait_ref, InferIsLocal(false))
200200
}
201201

202202
fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>,
203203
trait_ref: &ty::TraitRef<'tcx>,
204-
param_is_local: ParamIsLocal)
204+
infer_is_local: InferIsLocal)
205205
-> Result<(), OrphanCheckErr<'tcx>>
206206
{
207-
debug!("orphan_check_trait_ref(trait_ref={}, param_is_local={})",
208-
trait_ref.repr(tcx), param_is_local.0);
207+
debug!("orphan_check_trait_ref(trait_ref={}, infer_is_local={})",
208+
trait_ref.repr(tcx), infer_is_local.0);
209209

210210
// First, create an ordered iterator over all the type parameters to the trait, with the self
211211
// type appearing first.
@@ -215,12 +215,12 @@ fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>,
215215
// Find the first input type that either references a type parameter OR
216216
// some local type.
217217
for input_ty in input_tys {
218-
if ty_is_local(tcx, input_ty, param_is_local) {
218+
if ty_is_local(tcx, input_ty, infer_is_local) {
219219
debug!("orphan_check_trait_ref: ty_is_local `{}`", input_ty.repr(tcx));
220220

221221
// First local input type. Check that there are no
222222
// uncovered type parameters.
223-
let uncovered_tys = uncovered_tys(tcx, input_ty, param_is_local);
223+
let uncovered_tys = uncovered_tys(tcx, input_ty, infer_is_local);
224224
for uncovered_ty in uncovered_tys {
225225
if let Some(param) = uncovered_ty.walk().find(|t| is_type_parameter(t)) {
226226
debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx));
@@ -234,7 +234,7 @@ fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>,
234234

235235
// Otherwise, enforce invariant that there are no type
236236
// parameters reachable.
237-
if !param_is_local.0 {
237+
if !infer_is_local.0 {
238238
if let Some(param) = input_ty.walk().find(|t| is_type_parameter(t)) {
239239
debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx));
240240
return Err(OrphanCheckErr::UncoveredTy(param));
@@ -249,14 +249,14 @@ fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>,
249249

250250
fn uncovered_tys<'tcx>(tcx: &ty::ctxt<'tcx>,
251251
ty: Ty<'tcx>,
252-
param_is_local: ParamIsLocal)
252+
infer_is_local: InferIsLocal)
253253
-> Vec<Ty<'tcx>>
254254
{
255-
if ty_is_local_constructor(tcx, ty, param_is_local) {
255+
if ty_is_local_constructor(tcx, ty, infer_is_local) {
256256
vec![]
257257
} else if fundamental_ty(tcx, ty) {
258258
ty.walk_shallow()
259-
.flat_map(|t| uncovered_tys(tcx, t, param_is_local).into_iter())
259+
.flat_map(|t| uncovered_tys(tcx, t, infer_is_local).into_iter())
260260
.collect()
261261
} else {
262262
vec![ty]
@@ -271,10 +271,10 @@ fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool {
271271
}
272272
}
273273

274-
fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, param_is_local: ParamIsLocal) -> bool
274+
fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, infer_is_local: InferIsLocal) -> bool
275275
{
276-
ty_is_local_constructor(tcx, ty, param_is_local) ||
277-
fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, param_is_local))
276+
ty_is_local_constructor(tcx, ty, infer_is_local) ||
277+
fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, infer_is_local))
278278
}
279279

280280
fn fundamental_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool
@@ -293,7 +293,7 @@ fn fundamental_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool
293293

294294
fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
295295
ty: Ty<'tcx>,
296-
param_is_local: ParamIsLocal)
296+
infer_is_local: InferIsLocal)
297297
-> bool
298298
{
299299
debug!("ty_is_local_constructor({})", ty.repr(tcx));
@@ -310,13 +310,13 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
310310
ty::ty_ptr(..) |
311311
ty::ty_rptr(..) |
312312
ty::ty_tup(..) |
313-
ty::ty_infer(..) |
313+
ty::ty_param(..) |
314314
ty::ty_projection(..) => {
315315
false
316316
}
317317

318-
ty::ty_param(..) => {
319-
param_is_local.0
318+
ty::ty_infer(..) => {
319+
infer_is_local.0
320320
}
321321

322322
ty::ty_enum(def_id, _) |

src/librustc/middle/traits/util.rs

-29
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use middle::region;
1211
use middle::subst::{Substs, VecPerParamSpace};
1312
use middle::infer::InferCtxt;
1413
use middle::ty::{self, Ty, AsPredicate, ToPolyTraitRef};
@@ -304,34 +303,6 @@ pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
304303
infcx.fresh_substs_for_generics(span, &impl_generics)
305304
}
306305

307-
// determine the `self` type, using fresh variables for all variables
308-
// declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
309-
// would return ($0, $1) where $0 and $1 are freshly instantiated type
310-
// variables.
311-
pub fn free_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
312-
_span: Span,
313-
impl_def_id: ast::DefId)
314-
-> Substs<'tcx>
315-
{
316-
let tcx = infcx.tcx;
317-
let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
318-
319-
let some_types = impl_generics.types.map(|def| {
320-
ty::mk_param_from_def(tcx, def)
321-
});
322-
323-
let some_regions = impl_generics.regions.map(|def| {
324-
// FIXME. This destruction scope information is pretty darn
325-
// bogus; after all, the impl might not even be in this crate!
326-
// But given what we do in coherence, it is harmless enough
327-
// for now I think. -nmatsakis
328-
let extent = region::DestructionScopeData::new(ast::DUMMY_NODE_ID);
329-
ty::free_region_from_def(extent, def)
330-
});
331-
332-
Substs::new(some_types, some_regions)
333-
}
334-
335306
impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> {
336307
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
337308
write!(f, "VtableImpl({:?})", self.impl_def_id)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2015 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+
// Check that we detect an overlap here in the case where:
12+
//
13+
// for some type X:
14+
// T = (X,)
15+
// T11 = X, U11 = X
16+
//
17+
// Seems pretty basic, but then there was issue #24241. :)
18+
19+
trait From<U> {
20+
}
21+
22+
impl <T> From<T> for T { //~ ERROR E0119
23+
}
24+
25+
impl <T11, U11> From<(U11,)> for (T11,) {
26+
}
27+
28+
fn main() { }

0 commit comments

Comments
 (0)