Skip to content

Commit cddb41d

Browse files
nikomatsakisJorge Aparicio
authored and
Jorge Aparicio
committed
Do not ICE when projecting out of a value with type ty::ty_err
1 parent 64b7c22 commit cddb41d

File tree

3 files changed

+66
-15
lines changed

3 files changed

+66
-15
lines changed

src/librustc/middle/traits/project.rs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ use super::VtableImplData;
2121

2222
use middle::infer;
2323
use middle::subst::Subst;
24-
use middle::ty::{mod, AsPredicate, RegionEscape, HasProjectionTypes, ToPolyTraitRef, Ty};
24+
use middle::ty::{mod, AsPredicate, ReferencesError, RegionEscape,
25+
HasProjectionTypes, ToPolyTraitRef, Ty};
2526
use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
27+
use std::rc::Rc;
2628
use util::ppaux::Repr;
2729

2830
pub type PolyProjectionObligation<'tcx> =
@@ -372,22 +374,34 @@ fn project_type<'cx,'tcx>(
372374
return Err(ProjectionTyError::TraitSelectionError(Overflow));
373375
}
374376

377+
let obligation_trait_ref =
378+
selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
379+
380+
debug!("project: obligation_trait_ref={}", obligation_trait_ref.repr(selcx.tcx()));
381+
382+
if obligation_trait_ref.references_error() {
383+
return Ok(ProjectedTy::Progress(selcx.tcx().types.err, vec!()));
384+
}
385+
375386
let mut candidates = ProjectionTyCandidateSet {
376387
vec: Vec::new(),
377388
ambiguous: false,
378389
};
379390

380391
assemble_candidates_from_object_type(selcx,
381392
obligation,
393+
&obligation_trait_ref,
382394
&mut candidates);
383395

384396
if candidates.vec.is_empty() {
385397
assemble_candidates_from_param_env(selcx,
386398
obligation,
399+
&obligation_trait_ref,
387400
&mut candidates);
388401

389402
if let Err(e) = assemble_candidates_from_impls(selcx,
390403
obligation,
404+
&obligation_trait_ref,
391405
&mut candidates) {
392406
return Err(ProjectionTyError::TraitSelectionError(e));
393407
}
@@ -421,17 +435,20 @@ fn project_type<'cx,'tcx>(
421435
/// there that can answer this question.
422436
fn assemble_candidates_from_param_env<'cx,'tcx>(
423437
selcx: &mut SelectionContext<'cx,'tcx>,
424-
obligation: &ProjectionTyObligation<'tcx>,
438+
obligation: &ProjectionTyObligation<'tcx>,
439+
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
425440
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
426441
{
427442
let env_predicates = selcx.param_env().caller_bounds.predicates.clone();
428443
let env_predicates = env_predicates.iter().cloned().collect();
429-
assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates);
444+
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
445+
candidate_set, env_predicates);
430446
}
431447

432448
fn assemble_candidates_from_predicates<'cx,'tcx>(
433449
selcx: &mut SelectionContext<'cx,'tcx>,
434-
obligation: &ProjectionTyObligation<'tcx>,
450+
obligation: &ProjectionTyObligation<'tcx>,
451+
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
435452
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
436453
env_predicates: Vec<ty::Predicate<'tcx>>)
437454
{
@@ -445,7 +462,7 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
445462
let is_match = infcx.probe(|_| {
446463
let origin = infer::Misc(obligation.cause.span);
447464
let obligation_poly_trait_ref =
448-
obligation.predicate.trait_ref.to_poly_trait_ref();
465+
obligation_trait_ref.to_poly_trait_ref();
449466
let data_poly_trait_ref =
450467
data.to_poly_trait_ref();
451468
infcx.sub_poly_trait_refs(false,
@@ -466,14 +483,14 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
466483

467484
fn assemble_candidates_from_object_type<'cx,'tcx>(
468485
selcx: &mut SelectionContext<'cx,'tcx>,
469-
obligation: &ProjectionTyObligation<'tcx>,
486+
obligation: &ProjectionTyObligation<'tcx>,
487+
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
470488
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
471489
{
472490
let infcx = selcx.infcx();
473-
let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
474491
debug!("assemble_candidates_from_object_type(trait_ref={})",
475-
trait_ref.repr(infcx.tcx));
476-
let self_ty = trait_ref.self_ty();
492+
obligation_trait_ref.repr(infcx.tcx));
493+
let self_ty = obligation_trait_ref.self_ty();
477494
let data = match self_ty.sty {
478495
ty::ty_trait(ref data) => data,
479496
_ => { return; }
@@ -482,21 +499,21 @@ fn assemble_candidates_from_object_type<'cx,'tcx>(
482499
let env_predicates = projection_bounds.iter()
483500
.map(|p| p.as_predicate())
484501
.collect();
485-
assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates)
502+
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
503+
candidate_set, env_predicates)
486504
}
487505

488506
fn assemble_candidates_from_impls<'cx,'tcx>(
489507
selcx: &mut SelectionContext<'cx,'tcx>,
490508
obligation: &ProjectionTyObligation<'tcx>,
509+
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
491510
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
492511
-> Result<(), SelectionError<'tcx>>
493512
{
494513
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
495514
// start out by selecting the predicate `T as TraitRef<...>`:
496-
let trait_ref =
497-
obligation.predicate.trait_ref.to_poly_trait_ref();
498-
let trait_obligation =
499-
obligation.with(trait_ref.to_poly_trait_predicate());
515+
let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
516+
let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
500517
let vtable = match selcx.select(&trait_obligation) {
501518
Ok(Some(vtable)) => vtable,
502519
Ok(None) => {

src/librustc/middle/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7269,7 +7269,7 @@ impl<T:ReferencesError> ReferencesError for Binder<T> {
72697269

72707270
impl<T:ReferencesError> ReferencesError for Rc<T> {
72717271
fn references_error(&self) -> bool {
7272-
(&*self).references_error()
7272+
(&**self).references_error()
72737273
}
72747274
}
72757275

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2014 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+
// Test that we do not ICE when the self type is `ty::err`, but rather
12+
// just propagate the error.
13+
14+
#![crate_type = "lib"]
15+
#![feature(associated_types, default_type_params, lang_items)]
16+
#![no_std]
17+
18+
#[lang="sized"]
19+
pub trait Sized for Sized? {
20+
// Empty.
21+
}
22+
23+
#[lang = "add"]
24+
trait Add<RHS=Self> {
25+
type Output;
26+
27+
fn add(self, RHS) -> Self::Output;
28+
}
29+
30+
fn ice<A>(a: A) {
31+
let r = loop {};
32+
r = r + a; // here the type `r` is not yet inferred, hence `r+a` generates an error.
33+
//~^ ERROR type of this value must be known
34+
}

0 commit comments

Comments
 (0)