diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-01-02 04:20:34 -0500 |
|---|---|---|
| committer | Jorge Aparicio <japaricious@gmail.com> | 2015-01-02 12:20:29 -0500 |
| commit | cddb41dd1fd7ace99fbc653b8aca48a0feba9c48 (patch) | |
| tree | dfcd83a8c79f3678e36cfd30c724bf4700e5f68a /src | |
| parent | 64b7c22c46b204520a6fae1c5cd750a3d3c6a66a (diff) | |
| download | rust-cddb41dd1fd7ace99fbc653b8aca48a0feba9c48.tar.gz rust-cddb41dd1fd7ace99fbc653b8aca48a0feba9c48.zip | |
Do not ICE when projecting out of a value with type `ty::ty_err`
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/middle/traits/project.rs | 45 | ||||
| -rw-r--r-- | src/librustc/middle/ty.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs | 34 |
3 files changed, 66 insertions, 15 deletions
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index c84f31bf6c3..125f39b1a43 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -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) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7bc5d3d0708..399d537088c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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() } } diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs new file mode 100644 index 00000000000..5743216b6ca --- /dev/null +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -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 +} |
