From eb84141ef5b79fab4f5f98c91f115e572c52e660 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 20 Nov 2015 15:44:39 +0200 Subject: [PATCH 1/2] select: treat ErrorCandidate as a real error Otherwise, projection can result in type errors that are unified into the trait inputs. We should probably refactor the `normalize_to_error` mess. --- src/librustc/middle/traits/select.rs | 6 +++--- src/test/run-pass/issue-29857.rs | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/issue-29857.rs diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index cd08c4feb8d6f..57e943555ae1b 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -628,9 +628,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match self.candidate_from_obligation(stack) { - Ok(Some(c)) => self.evaluate_candidate(stack, &c), + Err(..) | Ok(Some(ErrorCandidate)) => EvaluatedToErr, Ok(None) => EvaluatedToAmbig, - Err(..) => EvaluatedToErr + Ok(Some(c)) => self.evaluate_candidate(stack, &c), } } @@ -754,7 +754,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { - if stack.obligation.predicate.0.self_ty().references_error() { + if stack.obligation.predicate.references_error() { return Ok(Some(ErrorCandidate)); } diff --git a/src/test/run-pass/issue-29857.rs b/src/test/run-pass/issue-29857.rs new file mode 100644 index 0000000000000..9b75a5ab0c53c --- /dev/null +++ b/src/test/run-pass/issue-29857.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that we don't go mad when there are errors in trait evaluation + +use std::marker::PhantomData; + +pub trait Foo { type Output: 'static; } +pub trait Bar

{} +pub trait Baz

{} +pub struct Qux(PhantomData<*mut T>); + +impl> Bar

for Option {} +impl Bar<*mut T> for Option> {} + +impl> Baz<*mut T> for W {} + +fn main() {} From fd0bd3995b98d74484d901eb99f55b3a35ed24ea Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 25 Nov 2015 18:17:16 +0200 Subject: [PATCH 2/2] improve cast handling - this fixes test failures the problem is that now "type_is_known_to_be_sized" now returns false when called on a type with ty_err inside - this prevents spurious errors (we may want to move the check to check::cast anyway - see #12894). --- src/librustc_typeck/check/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bac85e4b7001e..f503ec2bf01f6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3507,9 +3507,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let t_cast = structurally_resolved_type(fcx, expr.span, t_cast); check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast)); let t_expr = fcx.expr_ty(e); + let t_cast = fcx.infcx().resolve_type_vars_if_possible(&t_cast); // Eagerly check for some obvious errors. - if t_expr.references_error() { + if t_expr.references_error() || t_cast.references_error() { fcx.write_error(id); } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) { report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);