提交 3045ffa5 编写于 作者: T Tristan Burgess

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 6f637da5
上级 b75b0471
......@@ -12,15 +12,15 @@
//! which folds deeply, invoking the underlying
//! `normalize_projection_ty` query when it encounters projections.
use infer::at::At;
use infer::{InferCtxt, InferOk};
use mir::interpret::{ConstValue, GlobalId};
use infer::at::At;
use mir::interpret::{GlobalId, ConstValue};
use rustc_data_structures::small_vec::SmallVec;
use traits::project::Normalized;
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use traits::project::Normalized;
use ty::{self, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
use ty::subst::{Subst, Substs};
use ty::{self, Ty, TyCtxt};
use super::NoSolution;
......@@ -121,36 +121,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
let concrete_ty = generic_ty.subst(self.tcx(), substs);
self.anon_depth += 1;
if concrete_ty == ty {
// The type in question can only be inferred in terms of itself. This
// is likely a user code issue, not a compiler issue. Thus, we will
// induce a cycle error by calling the parent query again on the type.
//
// FIXME: Perhaps a better solution would be to have fold_ty()
// itself be a query. Then, a type fold cycle would be detected
// and reported more naturally as part of the query system, rather
// than forcing it here.
//
// FIXME: Need a better span than just one pointing to the type def.
// Should point to a defining use of the type that results in this
// un-normalizable state.
if let Some(param_env_lifted) =
self.tcx().lift_to_global(&self.param_env)
{
if let Some(ty_lifted) = self.tcx().lift_to_global(&concrete_ty) {
let span = self.tcx().def_span(def_id);
self.tcx()
.global_tcx()
.at(span)
.normalize_ty_after_erasing_regions(
param_env_lifted.and(ty_lifted),
);
self.tcx().sess.abort_if_errors();
}
}
// If a cycle error can't be emitted, indicate a NoSolution error
// and let the caller handle it.
self.error = true;
return concrete_ty;
bug!("infinite recursion generic_ty: {:#?}, substs: {:#?}, \
concrete_ty: {:#?}, ty: {:#?}", generic_ty, substs, concrete_ty,
ty);
}
let folded_ty = self.fold_ty(concrete_ty);
self.anon_depth -= 1;
......@@ -176,8 +149,8 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
let gcx = self.infcx.tcx.global_tcx();
let mut orig_values = SmallVec::new();
let c_data = self.infcx
.canonicalize_query(&self.param_env.and(*data), &mut orig_values);
let c_data =
self.infcx.canonicalize_query(&self.param_env.and(*data), &mut orig_values);
debug!("QueryNormalizer: c_data = {:#?}", c_data);
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
match gcx.normalize_projection_ty(c_data) {
......
......@@ -492,6 +492,14 @@ fn visit_anon_types(&mut self, span: Span) {
})
};
if let ty::Anon(defin_ty_def_id, _substs) = definition_ty.sty {
if def_id == defin_ty_def_id {
// Concrete type resolved to the existential type itself
// Force a cycle error
self.tcx().at(span).type_of(defin_ty_def_id);
}
}
let old = self.tables.concrete_existential_types.insert(def_id, definition_ty);
if let Some(old) = old {
if old != definition_ty {
......
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(existential_type)]
// compile-pass
mod my_mod {
use std::fmt::Debug;
pub existential type Foo: Debug;
pub existential type Foot: Debug;
pub fn get_foo() -> Foo {
5i32
}
pub fn get_foot() -> Foot {
get_foo()
}
}
fn main() {
let _: my_mod::Foot = my_mod::get_foot();
}
error[E0391]: cycle detected when normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: Foo }`
error[E0391]: cycle detected when processing `Foo`
--> $DIR/no_inferrable_concrete_type.rs:16:1
|
LL | existential type Foo: Copy; //~ cycle detected
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: ...which again requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: Foo }`, completing the cycle
note: ...which requires processing `bar`...
--> $DIR/no_inferrable_concrete_type.rs:19:23
|
LL | fn bar(x: Foo) -> Foo { x }
| ^^^^^
= note: ...which again requires processing `Foo`, completing the cycle
error: aborting due to previous error
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册