Do not ICE when projecting out of a value with type ty::ty_err
This commit is contained in:
parent
64b7c22c46
commit
cddb41dd1f
@ -21,8 +21,10 @@ use super::VtableImplData;
|
||||
|
||||
use middle::infer;
|
||||
use middle::subst::Subst;
|
||||
use middle::ty::{mod, AsPredicate, RegionEscape, HasProjectionTypes, ToPolyTraitRef, Ty};
|
||||
use middle::ty::{mod, AsPredicate, ReferencesError, RegionEscape,
|
||||
HasProjectionTypes, ToPolyTraitRef, Ty};
|
||||
use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
|
||||
use std::rc::Rc;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
pub type PolyProjectionObligation<'tcx> =
|
||||
@ -372,6 +374,15 @@ fn project_type<'cx,'tcx>(
|
||||
return Err(ProjectionTyError::TraitSelectionError(Overflow));
|
||||
}
|
||||
|
||||
let obligation_trait_ref =
|
||||
selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
|
||||
|
||||
debug!("project: obligation_trait_ref={}", obligation_trait_ref.repr(selcx.tcx()));
|
||||
|
||||
if obligation_trait_ref.references_error() {
|
||||
return Ok(ProjectedTy::Progress(selcx.tcx().types.err, vec!()));
|
||||
}
|
||||
|
||||
let mut candidates = ProjectionTyCandidateSet {
|
||||
vec: Vec::new(),
|
||||
ambiguous: false,
|
||||
@ -379,15 +390,18 @@ fn project_type<'cx,'tcx>(
|
||||
|
||||
assemble_candidates_from_object_type(selcx,
|
||||
obligation,
|
||||
&obligation_trait_ref,
|
||||
&mut candidates);
|
||||
|
||||
if candidates.vec.is_empty() {
|
||||
assemble_candidates_from_param_env(selcx,
|
||||
obligation,
|
||||
&obligation_trait_ref,
|
||||
&mut candidates);
|
||||
|
||||
if let Err(e) = assemble_candidates_from_impls(selcx,
|
||||
obligation,
|
||||
&obligation_trait_ref,
|
||||
&mut candidates) {
|
||||
return Err(ProjectionTyError::TraitSelectionError(e));
|
||||
}
|
||||
@ -421,17 +435,20 @@ fn project_type<'cx,'tcx>(
|
||||
/// there that can answer this question.
|
||||
fn assemble_candidates_from_param_env<'cx,'tcx>(
|
||||
selcx: &mut SelectionContext<'cx,'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
|
||||
{
|
||||
let env_predicates = selcx.param_env().caller_bounds.predicates.clone();
|
||||
let env_predicates = env_predicates.iter().cloned().collect();
|
||||
assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates);
|
||||
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
|
||||
candidate_set, env_predicates);
|
||||
}
|
||||
|
||||
fn assemble_candidates_from_predicates<'cx,'tcx>(
|
||||
selcx: &mut SelectionContext<'cx,'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||
env_predicates: Vec<ty::Predicate<'tcx>>)
|
||||
{
|
||||
@ -445,7 +462,7 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
|
||||
let is_match = infcx.probe(|_| {
|
||||
let origin = infer::Misc(obligation.cause.span);
|
||||
let obligation_poly_trait_ref =
|
||||
obligation.predicate.trait_ref.to_poly_trait_ref();
|
||||
obligation_trait_ref.to_poly_trait_ref();
|
||||
let data_poly_trait_ref =
|
||||
data.to_poly_trait_ref();
|
||||
infcx.sub_poly_trait_refs(false,
|
||||
@ -466,14 +483,14 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
|
||||
|
||||
fn assemble_candidates_from_object_type<'cx,'tcx>(
|
||||
selcx: &mut SelectionContext<'cx,'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
|
||||
{
|
||||
let infcx = selcx.infcx();
|
||||
let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
|
||||
debug!("assemble_candidates_from_object_type(trait_ref={})",
|
||||
trait_ref.repr(infcx.tcx));
|
||||
let self_ty = trait_ref.self_ty();
|
||||
obligation_trait_ref.repr(infcx.tcx));
|
||||
let self_ty = obligation_trait_ref.self_ty();
|
||||
let data = match self_ty.sty {
|
||||
ty::ty_trait(ref data) => data,
|
||||
_ => { return; }
|
||||
@ -482,21 +499,21 @@ fn assemble_candidates_from_object_type<'cx,'tcx>(
|
||||
let env_predicates = projection_bounds.iter()
|
||||
.map(|p| p.as_predicate())
|
||||
.collect();
|
||||
assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates)
|
||||
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
|
||||
candidate_set, env_predicates)
|
||||
}
|
||||
|
||||
fn assemble_candidates_from_impls<'cx,'tcx>(
|
||||
selcx: &mut SelectionContext<'cx,'tcx>,
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
|
||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
|
||||
-> Result<(), SelectionError<'tcx>>
|
||||
{
|
||||
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
||||
// start out by selecting the predicate `T as TraitRef<...>`:
|
||||
let trait_ref =
|
||||
obligation.predicate.trait_ref.to_poly_trait_ref();
|
||||
let trait_obligation =
|
||||
obligation.with(trait_ref.to_poly_trait_predicate());
|
||||
let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
|
||||
let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
|
||||
let vtable = match selcx.select(&trait_obligation) {
|
||||
Ok(Some(vtable)) => vtable,
|
||||
Ok(None) => {
|
||||
|
@ -7269,7 +7269,7 @@ impl<T:ReferencesError> ReferencesError for Binder<T> {
|
||||
|
||||
impl<T:ReferencesError> ReferencesError for Rc<T> {
|
||||
fn references_error(&self) -> bool {
|
||||
(&*self).references_error()
|
||||
(&**self).references_error()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test that we do not ICE when the self type is `ty::err`, but rather
|
||||
// just propagate the error.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(associated_types, default_type_params, lang_items)]
|
||||
#![no_std]
|
||||
|
||||
#[lang="sized"]
|
||||
pub trait Sized for Sized? {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#[lang = "add"]
|
||||
trait Add<RHS=Self> {
|
||||
type Output;
|
||||
|
||||
fn add(self, RHS) -> Self::Output;
|
||||
}
|
||||
|
||||
fn ice<A>(a: A) {
|
||||
let r = loop {};
|
||||
r = r + a; // here the type `r` is not yet inferred, hence `r+a` generates an error.
|
||||
//~^ ERROR type of this value must be known
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user