Skip to content

Commit 7409050

Browse files
committed
auto merge of #17468 : nick29581/rust/dst-bug-nostd, r=nikomatsakis
closes #17392 r? @nikomatsakis Kind of a first draft because I'm not sure if this is the right approach. I believe the general idea of giving an error rather than an ICE in obligation_for_builtin_bound is right, but not sure about returning an Option, etc. Also, could probably have a better error message.
2 parents 0c66796 + 1c36d1c commit 7409050

File tree

8 files changed

+102
-45
lines changed

8 files changed

+102
-45
lines changed

src/librustc/middle/traits/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ pub enum ObligationCauseCode {
8686
FieldSized,
8787
}
8888

89+
// An error has already been reported to the user, so no need to continue checking.
90+
#[deriving(Clone,Show)]
91+
pub struct ErrorReported;
92+
8993
pub type Obligations = subst::VecPerParamSpace<Obligation>;
9094

9195
pub type Selection = Vtable<Obligation>;
@@ -332,7 +336,7 @@ pub fn obligation_for_builtin_bound(tcx: &ty::ctxt,
332336
cause: ObligationCause,
333337
source_ty: ty::t,
334338
builtin_bound: ty::BuiltinBound)
335-
-> Obligation
339+
-> Result<Obligation, ErrorReported>
336340
{
337341
util::obligation_for_builtin_bound(tcx, cause, builtin_bound, 0, source_ty)
338342
}

src/librustc/middle/traits/select.rs

+5
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
228228
bound,
229229
previous_stack.obligation.recursion_depth + 1,
230230
ty);
231+
let obligation = match obligation {
232+
Ok(ob) => ob,
233+
_ => return EvaluatedToMatch
234+
};
235+
231236
self.evaluate_obligation_recursively(previous_stack, &obligation)
232237
}
233238

src/librustc/middle/traits/util.rs

+25-18
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use syntax::ast;
2020
use syntax::codemap::Span;
2121
use util::ppaux::Repr;
2222

23-
use super::{Obligation, ObligationCause, VtableImpl, VtableParam, VtableParamData, VtableImplData};
23+
use super::{ErrorReported, Obligation, ObligationCause, VtableImpl,
24+
VtableParam, VtableParamData, VtableImplData};
2425

2526
///////////////////////////////////////////////////////////////////////////
2627
// Supertrait iterator
@@ -82,7 +83,7 @@ impl<'cx, 'tcx> Supertraits<'cx, 'tcx> {
8283
let bound_trait_ref = trait_ref_for_builtin_bound(self.tcx,
8384
builtin_bound,
8485
trait_ref.self_ty());
85-
trait_bounds.push(bound_trait_ref);
86+
bound_trait_ref.map(|trait_ref| trait_bounds.push(trait_ref));
8687
}
8788

8889
// Only keep those bounds that we haven't already seen. This
@@ -213,13 +214,15 @@ fn push_obligations_for_param_bounds(
213214
let param_ty = *param_substs.types.get(space, index);
214215

215216
for builtin_bound in param_bounds.builtin_bounds.iter() {
216-
obligations.push(
217-
space,
218-
obligation_for_builtin_bound(tcx,
219-
cause,
220-
builtin_bound,
221-
recursion_depth,
222-
param_ty));
217+
let obligation = obligation_for_builtin_bound(tcx,
218+
cause,
219+
builtin_bound,
220+
recursion_depth,
221+
param_ty);
222+
match obligation {
223+
Ok(ob) => obligations.push(space, ob),
224+
_ => {}
225+
}
223226
}
224227

225228
for bound_trait_ref in param_bounds.trait_bounds.iter() {
@@ -236,17 +239,18 @@ pub fn trait_ref_for_builtin_bound(
236239
tcx: &ty::ctxt,
237240
builtin_bound: ty::BuiltinBound,
238241
param_ty: ty::t)
239-
-> Rc<ty::TraitRef>
242+
-> Option<Rc<ty::TraitRef>>
240243
{
241244
match tcx.lang_items.from_builtin_kind(builtin_bound) {
242245
Ok(def_id) => {
243-
Rc::new(ty::TraitRef {
246+
Some(Rc::new(ty::TraitRef {
244247
def_id: def_id,
245248
substs: Substs::empty().with_self_ty(param_ty)
246-
})
249+
}))
247250
}
248251
Err(e) => {
249-
tcx.sess.bug(e.as_slice());
252+
tcx.sess.err(e.as_slice());
253+
None
250254
}
251255
}
252256
}
@@ -257,13 +261,16 @@ pub fn obligation_for_builtin_bound(
257261
builtin_bound: ty::BuiltinBound,
258262
recursion_depth: uint,
259263
param_ty: ty::t)
260-
-> Obligation
264+
-> Result<Obligation, ErrorReported>
261265
{
262266
let trait_ref = trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty);
263-
Obligation {
264-
cause: cause,
265-
recursion_depth: recursion_depth,
266-
trait_ref: trait_ref
267+
match trait_ref {
268+
Some(trait_ref) => Ok(Obligation {
269+
cause: cause,
270+
recursion_depth: recursion_depth,
271+
trait_ref: trait_ref
272+
}),
273+
None => Err(ErrorReported)
267274
}
268275
}
269276

src/librustc/middle/typeck/check/mod.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -1795,12 +1795,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17951795
code: traits::ObligationCauseCode,
17961796
bound: ty::BuiltinBound)
17971797
{
1798-
self.register_obligation(
1799-
traits::obligation_for_builtin_bound(
1800-
self.tcx(),
1801-
traits::ObligationCause::new(span, code),
1802-
ty,
1803-
bound));
1798+
let obligation = traits::obligation_for_builtin_bound(
1799+
self.tcx(),
1800+
traits::ObligationCause::new(span, code),
1801+
ty,
1802+
bound);
1803+
match obligation {
1804+
Ok(ob) => self.register_obligation(ob),
1805+
_ => {}
1806+
}
18041807
}
18051808

18061809
pub fn require_type_is_sized(&self,

src/librustc/middle/typeck/check/regionck.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,13 @@ fn check_expr_fn_block(rcx: &mut Rcx,
945945
let cause = traits::ObligationCause::new(freevar.span, code);
946946
let obligation = traits::obligation_for_builtin_bound(rcx.tcx(), cause,
947947
var_ty, builtin_bound);
948-
rcx.fcx.inh.fulfillment_cx.borrow_mut().register_obligation(rcx.tcx(), obligation);
948+
match obligation {
949+
Ok(obligation) => {
950+
rcx.fcx.inh.fulfillment_cx.borrow_mut().register_obligation(rcx.tcx(),
951+
obligation)
952+
}
953+
_ => {}
954+
}
949955
}
950956
type_must_outlive(
951957
rcx, infer::RelateProcBound(expr.span, var_node_id, var_ty),

src/librustc/middle/typeck/check/vtable2.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,16 @@ pub fn register_object_cast_obligations(fcx: &FnCtxt,
170170
// object type is Foo+Send, this would create an obligation
171171
// for the Send check.)
172172
for builtin_bound in object_trait.bounds.builtin_bounds.iter() {
173-
fcx.register_obligation(
174-
obligation_for_builtin_bound(
173+
let obligation = obligation_for_builtin_bound(
175174
fcx.tcx(),
176175
ObligationCause::new(span,
177176
traits::ObjectCastObligation(object_trait_ty)),
178177
referent_ty,
179-
builtin_bound));
178+
builtin_bound);
179+
match obligation {
180+
Ok(obligation) => fcx.register_obligation(obligation),
181+
_ => {}
182+
}
180183
}
181184

182185
object_trait_ref

src/librustc/middle/typeck/check/wf.rs

+24-16
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
124124
if variant.fields.len() > 0 {
125125
for field in variant.fields.init().iter() {
126126
let cause = traits::ObligationCause::new(field.span, traits::FieldSized);
127-
fcx.register_obligation(
128-
traits::obligation_for_builtin_bound(fcx.tcx(),
129-
cause,
130-
field.ty,
131-
ty::BoundSized));
127+
let obligation = traits::obligation_for_builtin_bound(fcx.tcx(),
128+
cause,
129+
field.ty,
130+
ty::BoundSized);
131+
match obligation {
132+
Ok(obligation) => fcx.register_obligation(obligation),
133+
_ => {}
134+
}
132135
}
133136
}
134137
}
@@ -213,11 +216,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
213216
&trait_def.bounds,
214217
trait_ref.self_ty());
215218
for builtin_bound in trait_def.bounds.builtin_bounds.iter() {
216-
fcx.register_obligation(
217-
traits::obligation_for_builtin_bound(fcx.tcx(),
218-
cause,
219-
trait_ref.self_ty(),
220-
builtin_bound));
219+
let obligation = traits::obligation_for_builtin_bound(fcx.tcx(),
220+
cause,
221+
trait_ref.self_ty(),
222+
builtin_bound);
223+
match obligation {
224+
Ok (obligation) => fcx.register_obligation(obligation),
225+
_ => {}
226+
}
221227
}
222228
for trait_bound in trait_def.bounds.trait_bounds.iter() {
223229
let trait_bound = trait_bound.subst(fcx.tcx(), &trait_ref.substs);
@@ -453,12 +459,14 @@ fn check_struct_safe_for_destructor(fcx: &FnCtxt,
453459
&& !struct_tpt.generics.has_region_params(subst::TypeSpace)
454460
{
455461
let cause = traits::ObligationCause::new(span, traits::DropTrait);
456-
fcx.register_obligation(
457-
traits::obligation_for_builtin_bound(
458-
fcx.tcx(),
459-
cause,
460-
self_ty,
461-
ty::BoundSend));
462+
let obligation = traits::obligation_for_builtin_bound(fcx.tcx(),
463+
cause,
464+
self_ty,
465+
ty::BoundSend);
466+
match obligation {
467+
Ok(obligation) => fcx.register_obligation(obligation),
468+
_ => {}
469+
}
462470
} else {
463471
span_err!(fcx.tcx().sess, span, E0141,
464472
"cannot implement a destructor on a structure \
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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 a missing lang item (in this case `sized`) does not cause an ICE,
12+
// see #17392.
13+
14+
// error-pattern: requires `sized` lang_item
15+
16+
#![no_std]
17+
18+
#[start]
19+
fn start(argc: int, argv: *const *const u8) -> int {
20+
0
21+
}

0 commit comments

Comments
 (0)