Skip to content

Commit 3045ffa

Browse files
52985: better cycle error for existential types
- Original cycle error diagnostics PR'd against this issue caught panic-causing error while resolving std::mem::transmute calls - Now, catch invalid use case of not providing a concrete sized type behind existential type in definining use case. - Update relevant test to reflect this new error 52985: revert normalize query changes - PR 53588 invalidates 53316, causing a correct cycle error to occur with a good span. - Don't need to revert the whole merge as the test files are still fine, just need to revert the normalize query changes. - It should now be correct that infinite recursion detected during normalize query type folding is a bug, should have been caught earlier (when resolving the existential type's defining use cases). 52985: code review impl - Only cause cycle error if anonymous type resolves to anonymous type that has the same def id (is the same type) as the original (parent) type. - Add test case to cover this case for existential types. 52985: remove Ty prefix from TyAnon - To align with changes per commit 6f637da
1 parent b75b047 commit 3045ffa

File tree

4 files changed

+55
-38
lines changed

4 files changed

+55
-38
lines changed

src/librustc/traits/query/normalize.rs

+9-36
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212
//! which folds deeply, invoking the underlying
1313
//! `normalize_projection_ty` query when it encounters projections.
1414
15-
use infer::at::At;
1615
use infer::{InferCtxt, InferOk};
17-
use mir::interpret::{ConstValue, GlobalId};
16+
use infer::at::At;
17+
use mir::interpret::{GlobalId, ConstValue};
1818
use rustc_data_structures::small_vec::SmallVec;
19-
use traits::project::Normalized;
2019
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
20+
use traits::project::Normalized;
21+
use ty::{self, Ty, TyCtxt};
2122
use ty::fold::{TypeFoldable, TypeFolder};
2223
use ty::subst::{Subst, Substs};
23-
use ty::{self, Ty, TyCtxt};
2424

2525
use super::NoSolution;
2626

@@ -121,36 +121,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
121121
let concrete_ty = generic_ty.subst(self.tcx(), substs);
122122
self.anon_depth += 1;
123123
if concrete_ty == ty {
124-
// The type in question can only be inferred in terms of itself. This
125-
// is likely a user code issue, not a compiler issue. Thus, we will
126-
// induce a cycle error by calling the parent query again on the type.
127-
//
128-
// FIXME: Perhaps a better solution would be to have fold_ty()
129-
// itself be a query. Then, a type fold cycle would be detected
130-
// and reported more naturally as part of the query system, rather
131-
// than forcing it here.
132-
//
133-
// FIXME: Need a better span than just one pointing to the type def.
134-
// Should point to a defining use of the type that results in this
135-
// un-normalizable state.
136-
if let Some(param_env_lifted) =
137-
self.tcx().lift_to_global(&self.param_env)
138-
{
139-
if let Some(ty_lifted) = self.tcx().lift_to_global(&concrete_ty) {
140-
let span = self.tcx().def_span(def_id);
141-
self.tcx()
142-
.global_tcx()
143-
.at(span)
144-
.normalize_ty_after_erasing_regions(
145-
param_env_lifted.and(ty_lifted),
146-
);
147-
self.tcx().sess.abort_if_errors();
148-
}
149-
}
150-
// If a cycle error can't be emitted, indicate a NoSolution error
151-
// and let the caller handle it.
152-
self.error = true;
153-
return concrete_ty;
124+
bug!("infinite recursion generic_ty: {:#?}, substs: {:#?}, \
125+
concrete_ty: {:#?}, ty: {:#?}", generic_ty, substs, concrete_ty,
126+
ty);
154127
}
155128
let folded_ty = self.fold_ty(concrete_ty);
156129
self.anon_depth -= 1;
@@ -176,8 +149,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
176149
let gcx = self.infcx.tcx.global_tcx();
177150

178151
let mut orig_values = SmallVec::new();
179-
let c_data = self.infcx
180-
.canonicalize_query(&self.param_env.and(*data), &mut orig_values);
152+
let c_data =
153+
self.infcx.canonicalize_query(&self.param_env.and(*data), &mut orig_values);
181154
debug!("QueryNormalizer: c_data = {:#?}", c_data);
182155
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
183156
match gcx.normalize_projection_ty(c_data) {

src/librustc_typeck/check/writeback.rs

+8
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,14 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
492492
})
493493
};
494494

495+
if let ty::Anon(defin_ty_def_id, _substs) = definition_ty.sty {
496+
if def_id == defin_ty_def_id {
497+
// Concrete type resolved to the existential type itself
498+
// Force a cycle error
499+
self.tcx().at(span).type_of(defin_ty_def_id);
500+
}
501+
}
502+
495503
let old = self.tables.concrete_existential_types.insert(def_id, definition_ty);
496504
if let Some(old) = old {
497505
if old != definition_ty {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2018 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+
#![feature(existential_type)]
12+
// compile-pass
13+
mod my_mod {
14+
use std::fmt::Debug;
15+
16+
pub existential type Foo: Debug;
17+
pub existential type Foot: Debug;
18+
19+
pub fn get_foo() -> Foo {
20+
5i32
21+
}
22+
23+
pub fn get_foot() -> Foot {
24+
get_foo()
25+
}
26+
}
27+
28+
fn main() {
29+
let _: my_mod::Foot = my_mod::get_foot();
30+
}
31+

src/test/ui/existential_types/no_inferrable_concrete_type.stderr

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
error[E0391]: cycle detected when normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: Foo }`
1+
error[E0391]: cycle detected when processing `Foo`
22
--> $DIR/no_inferrable_concrete_type.rs:16:1
33
|
44
LL | existential type Foo: Copy; //~ cycle detected
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: ...which again requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: Foo }`, completing the cycle
7+
note: ...which requires processing `bar`...
8+
--> $DIR/no_inferrable_concrete_type.rs:19:23
9+
|
10+
LL | fn bar(x: Foo) -> Foo { x }
11+
| ^^^^^
12+
= note: ...which again requires processing `Foo`, completing the cycle
813

914
error: aborting due to previous error
1015

0 commit comments

Comments
 (0)