mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Emit an error rather than ICEing for a missing built-in bound lang item.
closes #17392
This commit is contained in:
parent
1f3cda8bd8
commit
1c36d1c71d
@ -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<Obligation>;
|
||||
|
||||
pub type Selection = Vtable<Obligation>;
|
||||
@ -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<Obligation, ErrorReported>
|
||||
{
|
||||
util::obligation_for_builtin_bound(tcx, cause, builtin_bound, 0, source_ty)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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<ty::TraitRef>
|
||||
-> Option<Rc<ty::TraitRef>>
|
||||
{
|
||||
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<Obligation, ErrorReported>
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
21
src/test/compile-fail/lang-item-missing.rs
Normal file
21
src/test/compile-fail/lang-item-missing.rs
Normal file
@ -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 <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 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user