Skip to content

Commit

Permalink
Stop well-formedness checking unreachable code.
Browse files Browse the repository at this point in the history
This commit stops well-formedness checking applying to unreachable code
and therefore stops some of the ICEs that the intended solution taken by
this PR causes.

By disabling these checks, we can land the other fixes and larger
refactors that this PR includes.
  • Loading branch information
davidtwco committed Dec 30, 2018
1 parent 95c1838 commit 28fd1b0
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 245 deletions.
4 changes: 1 addition & 3 deletions src/librustc/dep_graph/dep_node.rs
Expand Up @@ -62,8 +62,7 @@ use syntax_pos::symbol::InternedString;
use traits;
use traits::query::{
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal,
CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
};
use ty::{TyCtxt, FnSig, Instance, InstanceDef,
Expand Down Expand Up @@ -651,7 +650,6 @@ define_dep_nodes!( <'tcx>
[] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
[] EvaluateGoal(traits::ChalkCanonicalGoal<'tcx>),
[] TypeOpAscribeUserType(CanonicalTypeOpAscribeUserTypeGoal<'tcx>),
[] TypeOpAscribeUserTypeWellFormed(CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>),
[] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
[] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
[] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>),
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/traits/query/mod.rs
Expand Up @@ -28,10 +28,6 @@ pub type CanonicalPredicateGoal<'tcx> =
pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>;

pub type CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx,
type_op::ascribe_user_type::AscribeUserTypeWellFormed<'tcx>>>;

pub type CanonicalTypeOpEqGoal<'tcx> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>;

Expand Down
58 changes: 1 addition & 57 deletions src/librustc/traits/query/type_op/ascribe_user_type.rs
Expand Up @@ -2,7 +2,7 @@ use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, Que
use traits::query::Fallible;
use hir::def_id::DefId;
use mir::ProjectionKind;
use ty::{self, ParamEnvAnd, Ty, TyCtxt, UserTypeAnnotation};
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
use ty::subst::UserSubsts;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -68,59 +68,3 @@ impl_stable_hash_for! {
mir_ty, variance, def_id, user_substs, projs
}
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct AscribeUserTypeWellFormed<'tcx> {
pub user_type_annotation: UserTypeAnnotation<'tcx>,
}

impl<'tcx> AscribeUserTypeWellFormed<'tcx> {
pub fn new(
user_type_annotation: UserTypeAnnotation<'tcx>,
) -> Self {
Self { user_type_annotation, }
}
}

impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserTypeWellFormed<'tcx> {
type QueryResponse = ();

fn try_fast_path(
_tcx: TyCtxt<'_, 'gcx, 'tcx>,
_key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
None
}

fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> {
tcx.type_op_ascribe_user_type_well_formed(canonicalized)
}

fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResponse<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> {
v
}
}

BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for AscribeUserTypeWellFormed<'tcx> {
user_type_annotation
}
}

BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for AscribeUserTypeWellFormed<'a> {
type Lifted = AscribeUserTypeWellFormed<'tcx>;
user_type_annotation
}
}

impl_stable_hash_for! {
struct AscribeUserTypeWellFormed<'tcx> {
user_type_annotation
}
}
12 changes: 1 addition & 11 deletions src/librustc/ty/query/config.rs
Expand Up @@ -5,8 +5,7 @@ use mir::interpret::GlobalId;
use traits;
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpAscribeUserTypeWellFormedGoal,
CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
};
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
Expand Down Expand Up @@ -125,15 +124,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type_well_formed<'tcx> {
fn describe(
_tcx: TyCtxt<'_, '_, '_>,
goal: CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>,
) -> Cow<'static, str> {
format!("evaluating `type_op_ascribe_user_type_well_formed` `{:?}`", goal).into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> {
format!("evaluating `type_op_eq` `{:?}`", goal).into()
Expand Down
11 changes: 1 addition & 10 deletions src/librustc/ty/query/mod.rs
Expand Up @@ -27,8 +27,7 @@ use traits::{self, Vtable};
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal,
CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal,
CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
CanonicalTypeOpNormalizeGoal, NoSolution,
};
use traits::query::method_autoderef::MethodAutoderefStepsResult;
Expand Down Expand Up @@ -610,14 +609,6 @@ define_queries! { <'tcx>
NoSolution,
>,

/// Do not call this query directly: part of the `Eq` type-op
[] fn type_op_ascribe_user_type_well_formed: TypeOpAscribeUserTypeWellFormed(
CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
NoSolution,
>,

/// Do not call this query directly: part of the `Eq` type-op
[] fn type_op_eq: TypeOpEq(
CanonicalTypeOpEqGoal<'tcx>
Expand Down
1 change: 0 additions & 1 deletion src/librustc/ty/query/plumbing.rs
Expand Up @@ -1208,7 +1208,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::EvaluateObligation |
DepKind::EvaluateGoal |
DepKind::TypeOpAscribeUserType |
DepKind::TypeOpAscribeUserTypeWellFormed |
DepKind::TypeOpEq |
DepKind::TypeOpSubtype |
DepKind::TypeOpProvePredicate |
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/ty/wf.rs
Expand Up @@ -289,6 +289,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
self.out.extend(obligations);
}

ty::FnDef(did, substs) => {
let obligations = self.nominal_obligations(did, substs);
self.out.extend(obligations);
}

ty::Ref(r, rty, _) => {
// WfReference
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
Expand Down Expand Up @@ -349,7 +354,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
}
}

ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnPtr(_) => {
// let the loop iterate into the argument/return
// types appearing in the fn signature
}
Expand Down
53 changes: 0 additions & 53 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Expand Up @@ -928,37 +928,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
);
}

/// Check that user type annotations are well formed.
fn check_user_type_annotations_are_well_formed(&mut self) {
for index in self.mir.user_type_annotations.indices() {
let (span, _) = &self.mir.user_type_annotations[index];
let type_annotation = self.instantiated_type_annotations[&index];
match type_annotation {
// We can't check the well-formedness of a `UserTypeAnnotation::Ty` here, it will
// cause ICEs (see comment in `relate_type_and_user_type`).
UserTypeAnnotation::TypeOf(..) => {
if let Err(terr) = self.fully_perform_op(
Locations::All(*span),
ConstraintCategory::Assignment,
self.param_env.and(
type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
type_annotation,
)
),
) {
span_mirbug!(
self,
type_annotation,
"bad user type annotation: {:?}",
terr,
);
}
},
_ => {},
}
}
}

/// Given some operation `op` that manipulates types, proves
/// predicates, or otherwise uses the inference context, executes
/// `op` and then executes all the further obligations that `op`
Expand Down Expand Up @@ -1127,27 +1096,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
if let Ok(projected_ty) = curr_projected_ty {
let ty = projected_ty.to_ty(tcx);
self.relate_types(ty, v1, a, locations, category)?;

// We'll get an ICE if we check for well-formedness of a
// `UserTypeAnnotation::Ty` that hasn't had types related.
//
// Doing this without the types having been related will result in
// `probe_ty_var` failing in the canonicalizer - in practice, this
// results in three run-pass tests failing. You can work around that
// by keeping an vec of projections instead of annotations and performing
// the projections before storing into `instantiated_type_annotations`
// but that still fails in dead code.
self.fully_perform_op(
locations,
category,
self.param_env.and(
type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
UserTypeAnnotation::Ty(ty),
)
),
)?;
}

}
UserTypeAnnotation::TypeOf(def_id, user_substs) => {
let projs = self.infcx.tcx.intern_projs(&user_ty.projs);
Expand Down Expand Up @@ -2453,8 +2402,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
self.check_terminator(mir, block_data.terminator(), location);
self.check_iscleanup(mir, block_data);
}

self.check_user_type_annotations_are_well_formed();
}

fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
Expand Down

0 comments on commit 28fd1b0

Please sign in to comment.