diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 9d66108cfc9..88685101b31 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -86,6 +86,10 @@ pub enum ObligationCauseCode { FieldSized, } +// An error has already been reported to the user, so no need to continue checking. +#[deriving(Clone,Show)] +pub struct ErrorReported; + pub type Obligations = subst::VecPerParamSpace; pub type Selection = Vtable; @@ -332,7 +336,7 @@ pub fn obligation_for_builtin_bound(tcx: &ty::ctxt, cause: ObligationCause, source_ty: ty::t, builtin_bound: ty::BuiltinBound) - -> Obligation + -> Result { util::obligation_for_builtin_bound(tcx, cause, builtin_bound, 0, source_ty) } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 63fbeb797c4..61477fdeed5 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -228,6 +228,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bound, previous_stack.obligation.recursion_depth + 1, ty); + let obligation = match obligation { + Ok(ob) => ob, + _ => return EvaluatedToMatch + }; + self.evaluate_obligation_recursively(previous_stack, &obligation) } diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index cad86003ce9..ab5bbf4363f 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -20,7 +20,8 @@ use syntax::ast; use syntax::codemap::Span; use util::ppaux::Repr; -use super::{Obligation, ObligationCause, VtableImpl, VtableParam, VtableParamData, VtableImplData}; +use super::{ErrorReported, Obligation, ObligationCause, VtableImpl, + VtableParam, VtableParamData, VtableImplData}; /////////////////////////////////////////////////////////////////////////// // Supertrait iterator @@ -82,7 +83,7 @@ impl<'cx, 'tcx> Supertraits<'cx, 'tcx> { let bound_trait_ref = trait_ref_for_builtin_bound(self.tcx, builtin_bound, trait_ref.self_ty()); - trait_bounds.push(bound_trait_ref); + bound_trait_ref.map(|trait_ref| trait_bounds.push(trait_ref)); } // Only keep those bounds that we haven't already seen. This @@ -213,13 +214,15 @@ fn push_obligations_for_param_bounds( let param_ty = *param_substs.types.get(space, index); for builtin_bound in param_bounds.builtin_bounds.iter() { - obligations.push( - space, - obligation_for_builtin_bound(tcx, - cause, - builtin_bound, - recursion_depth, - param_ty)); + let obligation = obligation_for_builtin_bound(tcx, + cause, + builtin_bound, + recursion_depth, + param_ty); + match obligation { + Ok(ob) => obligations.push(space, ob), + _ => {} + } } for bound_trait_ref in param_bounds.trait_bounds.iter() { @@ -236,17 +239,18 @@ pub fn trait_ref_for_builtin_bound( tcx: &ty::ctxt, builtin_bound: ty::BuiltinBound, param_ty: ty::t) - -> Rc + -> Option> { match tcx.lang_items.from_builtin_kind(builtin_bound) { Ok(def_id) => { - Rc::new(ty::TraitRef { + Some(Rc::new(ty::TraitRef { def_id: def_id, substs: Substs::empty().with_self_ty(param_ty) - }) + })) } Err(e) => { - tcx.sess.bug(e.as_slice()); + tcx.sess.err(e.as_slice()); + None } } } @@ -257,13 +261,16 @@ pub fn obligation_for_builtin_bound( builtin_bound: ty::BuiltinBound, recursion_depth: uint, param_ty: ty::t) - -> Obligation + -> Result { let trait_ref = trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty); - Obligation { - cause: cause, - recursion_depth: recursion_depth, - trait_ref: trait_ref + match trait_ref { + Some(trait_ref) => Ok(Obligation { + cause: cause, + recursion_depth: recursion_depth, + trait_ref: trait_ref + }), + None => Err(ErrorReported) } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d4c38d48a8c..0bf22d97345 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1795,12 +1795,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { code: traits::ObligationCauseCode, bound: ty::BuiltinBound) { - self.register_obligation( - traits::obligation_for_builtin_bound( - self.tcx(), - traits::ObligationCause::new(span, code), - ty, - bound)); + let obligation = traits::obligation_for_builtin_bound( + self.tcx(), + traits::ObligationCause::new(span, code), + ty, + bound); + match obligation { + Ok(ob) => self.register_obligation(ob), + _ => {} + } } pub fn require_type_is_sized(&self, diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index d45155c2ccd..b853616991f 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -945,7 +945,13 @@ fn check_expr_fn_block(rcx: &mut Rcx, let cause = traits::ObligationCause::new(freevar.span, code); let obligation = traits::obligation_for_builtin_bound(rcx.tcx(), cause, var_ty, builtin_bound); - rcx.fcx.inh.fulfillment_cx.borrow_mut().register_obligation(rcx.tcx(), obligation); + match obligation { + Ok(obligation) => { + rcx.fcx.inh.fulfillment_cx.borrow_mut().register_obligation(rcx.tcx(), + obligation) + } + _ => {} + } } type_must_outlive( rcx, infer::RelateProcBound(expr.span, var_node_id, var_ty), diff --git a/src/librustc/middle/typeck/check/vtable2.rs b/src/librustc/middle/typeck/check/vtable2.rs index bcbcebc3f59..bdcf4d73c3b 100644 --- a/src/librustc/middle/typeck/check/vtable2.rs +++ b/src/librustc/middle/typeck/check/vtable2.rs @@ -170,13 +170,16 @@ pub fn register_object_cast_obligations(fcx: &FnCtxt, // object type is Foo+Send, this would create an obligation // for the Send check.) for builtin_bound in object_trait.bounds.builtin_bounds.iter() { - fcx.register_obligation( - obligation_for_builtin_bound( + let obligation = obligation_for_builtin_bound( fcx.tcx(), ObligationCause::new(span, traits::ObjectCastObligation(object_trait_ty)), referent_ty, - builtin_bound)); + builtin_bound); + match obligation { + Ok(obligation) => fcx.register_obligation(obligation), + _ => {} + } } object_trait_ref diff --git a/src/librustc/middle/typeck/check/wf.rs b/src/librustc/middle/typeck/check/wf.rs index 67f93feae41..587aa072fa8 100644 --- a/src/librustc/middle/typeck/check/wf.rs +++ b/src/librustc/middle/typeck/check/wf.rs @@ -124,11 +124,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { if variant.fields.len() > 0 { for field in variant.fields.init().iter() { let cause = traits::ObligationCause::new(field.span, traits::FieldSized); - fcx.register_obligation( - traits::obligation_for_builtin_bound(fcx.tcx(), - cause, - field.ty, - ty::BoundSized)); + let obligation = traits::obligation_for_builtin_bound(fcx.tcx(), + cause, + field.ty, + ty::BoundSized); + match obligation { + Ok(obligation) => fcx.register_obligation(obligation), + _ => {} + } } } } @@ -213,11 +216,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &trait_def.bounds, trait_ref.self_ty()); for builtin_bound in trait_def.bounds.builtin_bounds.iter() { - fcx.register_obligation( - traits::obligation_for_builtin_bound(fcx.tcx(), - cause, - trait_ref.self_ty(), - builtin_bound)); + let obligation = traits::obligation_for_builtin_bound(fcx.tcx(), + cause, + trait_ref.self_ty(), + builtin_bound); + match obligation { + Ok (obligation) => fcx.register_obligation(obligation), + _ => {} + } } for trait_bound in trait_def.bounds.trait_bounds.iter() { let trait_bound = trait_bound.subst(fcx.tcx(), &trait_ref.substs); @@ -453,12 +459,14 @@ fn check_struct_safe_for_destructor(fcx: &FnCtxt, && !struct_tpt.generics.has_region_params(subst::TypeSpace) { let cause = traits::ObligationCause::new(span, traits::DropTrait); - fcx.register_obligation( - traits::obligation_for_builtin_bound( - fcx.tcx(), - cause, - self_ty, - ty::BoundSend)); + let obligation = traits::obligation_for_builtin_bound(fcx.tcx(), + cause, + self_ty, + ty::BoundSend); + match obligation { + Ok(obligation) => fcx.register_obligation(obligation), + _ => {} + } } else { span_err!(fcx.tcx().sess, span, E0141, "cannot implement a destructor on a structure \ diff --git a/src/test/compile-fail/lang-item-missing.rs b/src/test/compile-fail/lang-item-missing.rs new file mode 100644 index 00000000000..bcde10a0b22 --- /dev/null +++ b/src/test/compile-fail/lang-item-missing.rs @@ -0,0 +1,21 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that a missing lang item (in this case `sized`) does not cause an ICE, +// see #17392. + +// error-pattern: requires `sized` lang_item + +#![no_std] + +#[start] +fn start(argc: int, argv: *const *const u8) -> int { + 0 +}