mod.rs 45.1 KB
Newer Older
1
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
2
use rustc::mir;
3
use rustc::ty::{self, TypeVariants, Ty};
O
Oliver Schneider 已提交
4
use rustc::ty::layout::Layout;
5 6
use syntax::codemap::Span;
use syntax::attr;
7
use syntax::abi::Abi;
8 9

use error::{EvalError, EvalResult};
R
Ralf Jung 已提交
10
use eval_context::{EvalContext, IntegerExt, StackPopCleanup, TyAndPacked, is_inhabited, self};
11
use lvalue::Lvalue;
12
use memory::{MemoryPointer, TlsKey, Kind, HasMemory};
13
use value::{PrimVal, Value};
O
Oliver Schneider 已提交
14
use rustc_data_structures::indexed_vec::Idx;
15
use const_eval;
16

17 18
use std::mem;

19
mod drop;
20
mod intrinsic;
O
Oliver Schneider 已提交
21

22
impl<'a, 'tcx> EvalContext<'a, 'tcx> {
23 24 25 26 27
    pub(super) fn goto_block(&mut self, target: mir::BasicBlock) {
        self.frame_mut().block = target;
        self.frame_mut().stmt = 0;
    }

28 29 30
    pub(super) fn eval_terminator(
        &mut self,
        terminator: &mir::Terminator<'tcx>,
31
    ) -> EvalResult<'tcx> {
32
        use rustc::mir::TerminatorKind::*;
33
        match terminator.kind {
S
Scott Olson 已提交
34
            Return => {
O
Oliver Schneider 已提交
35
                self.dump_local(self.frame().return_lvalue);
S
Scott Olson 已提交
36 37
                self.pop_stack_frame()?
            }
38

39
            Goto { target } => self.goto_block(target),
40 41

            SwitchInt { ref discr, ref values, ref targets, .. } => {
O
Oliver Schneider 已提交
42
                if self.const_env() {
43 44
                    return Err(EvalError::NeedsRfc("branching (if, match, loop, ...)".to_string()));
                }
O
rustup  
Oliver Schneider 已提交
45 46
                let discr_val = self.eval_operand(discr)?;
                let discr_ty = self.operand_ty(discr);
O
Oliver Schneider 已提交
47
                let discr_prim = self.value_to_primval(discr_val, discr_ty)?;
48 49 50 51

                // Branch to the `otherwise` case by default, if no match is found.
                let mut target_block = targets[targets.len() - 1];

O
rustup  
Oliver Schneider 已提交
52 53
                for (index, const_int) in values.iter().enumerate() {
                    let prim = PrimVal::Bytes(const_int.to_u128_unchecked());
54
                    if discr_prim.to_bytes()? == prim.to_bytes()? {
55 56 57 58 59
                        target_block = targets[index];
                        break;
                    }
                }

60
                self.goto_block(target_block);
61 62 63
            }

            Call { ref func, ref args, ref destination, .. } => {
64
                let destination = match *destination {
65
                    Some((ref lv, target)) => Some((self.eval_lvalue(lv)?, target)),
66 67
                    None => None,
                };
68 69

                let func_ty = self.operand_ty(func);
O
Oliver Schneider 已提交
70
                let (fn_def, sig) = match func_ty.sty {
O
Oliver Schneider 已提交
71
                    ty::TyFnPtr(sig) => {
72
                        let fn_ptr = self.eval_operand_to_primval(func)?.to_ptr()?;
73
                        let instance = self.memory.get_fn(fn_ptr)?;
74 75 76
                        let instance_ty = instance.def.def_ty(self.tcx);
                        let instance_ty = self.monomorphize(instance_ty, instance.substs);
                        match instance_ty.sty {
77 78
                            ty::TyFnDef(..) => {
                                let real_sig = instance_ty.fn_sig(self.tcx);
79 80
                                let sig = self.erase_lifetimes(&sig);
                                let real_sig = self.erase_lifetimes(&real_sig);
81
                                let real_sig = self.tcx.normalize_associated_type(&real_sig);
82 83
                                if !self.check_sig_compat(sig, real_sig)? {
                                    return Err(EvalError::FunctionPointerTyMismatch(real_sig, sig));
84 85 86 87 88
                                }
                            },
                            ref other => bug!("instance def ty: {:?}", other),
                        }
                        (instance, sig)
89
                    },
90
                    ty::TyFnDef(def_id, substs) => (eval_context::resolve(self.tcx, def_id, substs), func_ty.fn_sig(self.tcx)),
91 92 93 94
                    _ => {
                        let msg = format!("can't handle callee of type {:?}", func_ty);
                        return Err(EvalError::Unimplemented(msg));
                    }
95
                };
O
Oliver Schneider 已提交
96 97
                let sig = self.erase_lifetimes(&sig);
                self.eval_fn_call(fn_def, destination, args, terminator.source_info.span, sig)?;
98 99
            }

O
Oliver Schneider 已提交
100
            Drop { ref location, target, .. } => {
O
Oliver Schneider 已提交
101
                trace!("TerminatorKind::drop: {:?}, {:?}", location, self.substs());
O
Oliver Schneider 已提交
102
                if self.const_env() {
103 104
                    return Err(EvalError::NeedsRfc("invoking `Drop::drop`".to_string()));
                }
O
Oliver Schneider 已提交
105 106
                let lval = self.eval_lvalue(location)?;
                let ty = self.lvalue_ty(location);
O
Oliver Schneider 已提交
107
                self.goto_block(target);
108
                let ty = eval_context::apply_param_substs(self.tcx, self.substs(), &ty);
O
Oliver Schneider 已提交
109

110
                let instance = eval_context::resolve_drop_in_place(self.tcx, ty);
111
                self.drop_lvalue(lval, instance, ty, terminator.source_info.span)?;
O
Oliver Schneider 已提交
112
            }
113 114

            Assert { ref cond, expected, ref msg, target, .. } => {
115
                let cond_val = self.eval_operand_to_primval(cond)?.to_bool()?;
116
                if expected == cond_val {
117
                    self.goto_block(target);
118 119 120
                } else {
                    return match *msg {
                        mir::AssertMessage::BoundsCheck { ref len, ref index } => {
121
                            let span = terminator.source_info.span;
122 123
                            let len = self.eval_operand_to_primval(len)
                                .expect("can't eval len")
124
                                .to_u64()?;
125 126
                            let index = self.eval_operand_to_primval(index)
                                .expect("can't eval index")
127
                                .to_u64()?;
128
                            Err(EvalError::ArrayIndexOutOfBounds(span, len, index))
129
                        },
130 131
                        mir::AssertMessage::Math(ref err) =>
                            Err(EvalError::Math(terminator.source_info.span, err.clone())),
132 133 134 135 136 137
                    }
                }
            },

            DropAndReplace { .. } => unimplemented!(),
            Resume => unimplemented!(),
138
            Unreachable => return Err(EvalError::Unreachable),
139 140 141 142 143
        }

        Ok(())
    }

R
Ralf Jung 已提交
144 145
    /// Decides whether it is okay to call the method with signature `real_sig` using signature `sig`.
    /// FIXME: This should take into account the platform-dependent ABI description.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
    fn check_sig_compat(
        &mut self,
        sig: ty::FnSig<'tcx>,
        real_sig: ty::FnSig<'tcx>,
    ) -> EvalResult<'tcx, bool> {
        fn check_ty_compat<'tcx>(
            ty: ty::Ty<'tcx>,
            real_ty: ty::Ty<'tcx>,
        ) -> bool {
            if ty == real_ty { return true; } // This is actually a fast pointer comparison
            return match (&ty.sty, &real_ty.sty) {
                // Permit changing the pointer type of raw pointers and references as well as
                // mutability of raw pointers.
                // TODO: Should not be allowed when fat pointers are involved.
                (&TypeVariants::TyRawPtr(_), &TypeVariants::TyRawPtr(_)) => true,
                (&TypeVariants::TyRef(_, _), &TypeVariants::TyRef(_, _)) =>
                    ty.is_mutable_pointer() == real_ty.is_mutable_pointer(),
                // rule out everything else
                _ => false
            }
        }

        if sig.abi == real_sig.abi &&
            sig.variadic == real_sig.variadic &&
            sig.inputs_and_output.len() == real_sig.inputs_and_output.len() &&
            sig.inputs_and_output.iter().zip(real_sig.inputs_and_output).all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) {
            // Definitely good.
            return Ok(true);
        }

        if sig.variadic || real_sig.variadic {
            // We're not touching this
            return Ok(false);
        }

        // We need to allow what comes up when a non-capturing closure is cast to a fn().
        match (sig.abi, real_sig.abi) {
            (Abi::Rust, Abi::RustCall) // check the ABIs.  This makes the test here non-symmetric.
                if check_ty_compat(sig.output(), real_sig.output()) && real_sig.inputs_and_output.len() == 3 => {
                // First argument of real_sig must be a ZST
                let fst_ty = real_sig.inputs_and_output[0];
                let layout = self.type_layout(fst_ty)?;
                let size = layout.size(&self.tcx.data_layout).bytes();
                if size == 0 {
                    // Second argument must be a tuple matching the argument list of sig
                    let snd_ty = real_sig.inputs_and_output[1];
                    match snd_ty.sty {
                        TypeVariants::TyTuple(tys, _) if sig.inputs().len() == tys.len() =>
                            if sig.inputs().iter().zip(tys).all(|(ty, real_ty)| check_ty_compat(ty, real_ty)) {
                                return Ok(true)
                            },
                        _ => {}
                    }
                }
            }
            _ => {}
        };

        // Nope, this doesn't work.
        return Ok(false);
    }

208 209
    fn eval_fn_call(
        &mut self,
O
Oliver Schneider 已提交
210
        instance: ty::Instance<'tcx>,
211
        destination: Option<(Lvalue<'tcx>, mir::BasicBlock)>,
S
Scott Olson 已提交
212
        arg_operands: &[mir::Operand<'tcx>],
213
        span: Span,
O
Oliver Schneider 已提交
214
        sig: ty::FnSig<'tcx>,
215
    ) -> EvalResult<'tcx> {
O
Oliver Schneider 已提交
216 217 218
        trace!("eval_fn_call: {:#?}", instance);
        match instance.def {
            ty::InstanceDef::Intrinsic(..) => {
219
                let (ret, target) = match destination {
O
Oliver Schneider 已提交
220
                    Some(dest) => dest,
221
                    _ => return Err(EvalError::Unreachable),
222
                };
O
Oliver Schneider 已提交
223 224 225 226 227
                let ty = sig.output();
                if !is_inhabited(self.tcx, ty) {
                    return Err(EvalError::Unreachable);
                }
                let layout = self.type_layout(ty)?;
O
Oliver Schneider 已提交
228
                self.call_intrinsic(instance, arg_operands, ret, ty, layout, target)?;
229
                self.dump_local(ret);
O
Oliver Schneider 已提交
230
                Ok(())
231
            },
O
Oliver Schneider 已提交
232
            ty::InstanceDef::ClosureOnceShim{..} => {
S
Scott Olson 已提交
233 234 235 236 237
                let mut args = Vec::new();
                for arg in arg_operands {
                    let arg_val = self.eval_operand(arg)?;
                    let arg_ty = self.operand_ty(arg);
                    args.push((arg_val, arg_ty));
238
                }
239
                if self.eval_fn_call_inner(
O
Oliver Schneider 已提交
240 241
                    instance,
                    destination,
242
                    arg_operands,
O
Oliver Schneider 已提交
243
                    span,
244
                    sig,
245 246 247
                )? {
                    return Ok(());
                }
O
Oliver Schneider 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
                let mut arg_locals = self.frame().mir.args_iter();
                match sig.abi {
                    // closure as closure once
                    Abi::RustCall => {
                        for (arg_local, (arg_val, arg_ty)) in arg_locals.zip(args) {
                            let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
                            self.write_value(arg_val, dest, arg_ty)?;
                        }
                    },
                    // non capture closure as fn ptr
                    // need to inject zst ptr for closure object (aka do nothing)
                    // and need to pack arguments
                    Abi::Rust => {
                        trace!("arg_locals: {:?}", self.frame().mir.args_iter().collect::<Vec<_>>());
                        trace!("arg_operands: {:?}", arg_operands);
                        let local = arg_locals.nth(1).unwrap();
                        for (i, (arg_val, arg_ty)) in args.into_iter().enumerate() {
                            let dest = self.eval_lvalue(&mir::Lvalue::Local(local).field(mir::Field::new(i), arg_ty))?;
                            self.write_value(arg_val, dest, arg_ty)?;
                        }
                    },
                    _ => bug!("bad ABI for ClosureOnceShim: {:?}", sig.abi),
                }
                Ok(())
O
Oliver Schneider 已提交
272 273
            }
            ty::InstanceDef::Item(_) => {
O
Oliver Schneider 已提交
274 275 276 277 278 279 280
                let mut args = Vec::new();
                for arg in arg_operands {
                    let arg_val = self.eval_operand(arg)?;
                    let arg_ty = self.operand_ty(arg);
                    args.push((arg_val, arg_ty));
                }

R
Ralf Jung 已提交
281
                // Push the stack frame, and potentially be entirely done if the call got hooked
282
                if self.eval_fn_call_inner(
O
Oliver Schneider 已提交
283
                    instance,
284
                    destination,
285
                    arg_operands,
286
                    span,
287
                    sig,
288 289 290
                )? {
                    return Ok(());
                }
O
Oliver Schneider 已提交
291

R
Ralf Jung 已提交
292
                // Pass the arguments
O
Oliver Schneider 已提交
293
                let mut arg_locals = self.frame().mir.args_iter();
294 295 296
                trace!("ABI: {:?}", sig.abi);
                trace!("arg_locals: {:?}", self.frame().mir.args_iter().collect::<Vec<_>>());
                trace!("arg_operands: {:?}", arg_operands);
O
Oliver Schneider 已提交
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
                match sig.abi {
                    Abi::RustCall => {
                        assert_eq!(args.len(), 2);

                        {   // write first argument
                            let first_local = arg_locals.next().unwrap();
                            let dest = self.eval_lvalue(&mir::Lvalue::Local(first_local))?;
                            let (arg_val, arg_ty) = args.remove(0);
                            self.write_value(arg_val, dest, arg_ty)?;
                        }

                        // unpack and write all other args
                        let (arg_val, arg_ty) = args.remove(0);
                        let layout = self.type_layout(arg_ty)?;
                        if let (&ty::TyTuple(fields, _), &Layout::Univariant { ref variant, .. }) = (&arg_ty.sty, layout) {
312
                            trace!("fields: {:?}", fields);
O
Oliver Schneider 已提交
313 314
                            if self.frame().mir.args_iter().count() == fields.len() + 1 {
                                let offsets = variant.offsets.iter().map(|s| s.bytes());
315
                                match arg_val {
R
Ralf Jung 已提交
316
                                    Value::ByRef { ptr, aligned } => {
317
                                        assert!(aligned, "Unaligned ByRef-values cannot occur as function arguments");
318
                                        for ((offset, ty), arg_local) in offsets.zip(fields).zip(arg_locals) {
R
Ralf Jung 已提交
319
                                            let arg = Value::ByRef { ptr: ptr.offset(offset, &self)?, aligned: true};
320 321 322 323 324 325 326 327 328 329
                                            let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
                                            trace!("writing arg {:?} to {:?} (type: {})", arg, dest, ty);
                                            self.write_value(arg, dest, ty)?;
                                        }
                                    },
                                    Value::ByVal(PrimVal::Undef) => {},
                                    other => {
                                        assert_eq!(fields.len(), 1);
                                        let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_locals.next().unwrap()))?;
                                        self.write_value(other, dest, fields[0])?;
O
Oliver Schneider 已提交
330
                                    }
O
Oliver Schneider 已提交
331
                                }
O
Oliver Schneider 已提交
332
                            } else {
333
                                trace!("manual impl of rust-call ABI");
O
Oliver Schneider 已提交
334 335 336
                                // called a manual impl of a rust-call function
                                let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_locals.next().unwrap()))?;
                                self.write_value(arg_val, dest, arg_ty)?;
O
Oliver Schneider 已提交
337 338 339 340
                            }
                        } else {
                            bug!("rust-call ABI tuple argument was {:?}, {:?}", arg_ty, layout);
                        }
R
Ralf Jung 已提交
341 342 343 344 345 346
                    },
                    _ => {
                        for (arg_local, (arg_val, arg_ty)) in arg_locals.zip(args) {
                            let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
                            self.write_value(arg_val, dest, arg_ty)?;
                        }
O
Oliver Schneider 已提交
347 348 349
                    }
                }
                Ok(())
350
            },
351 352 353 354 355 356 357 358 359 360 361
            ty::InstanceDef::DropGlue(..) => {
                assert_eq!(arg_operands.len(), 1);
                assert_eq!(sig.abi, Abi::Rust);
                let val = self.eval_operand(&arg_operands[0])?;
                let ty = self.operand_ty(&arg_operands[0]);
                let (_, target) = destination.expect("diverging drop glue");
                self.goto_block(target);
                // FIXME: deduplicate these matches
                let pointee_type = match ty.sty {
                    ty::TyRawPtr(ref tam) |
                    ty::TyRef(_, ref tam) => tam.ty,
O
Oliver Schneider 已提交
362
                    ty::TyAdt(def, _) if def.is_box() => ty.boxed_ty(),
363 364 365
                    _ => bug!("can only deref pointer types"),
                };
                self.drop(val, instance, pointee_type, span)
O
Oliver Schneider 已提交
366 367
            },
            ty::InstanceDef::FnPtrShim(..) => {
O
Oliver Schneider 已提交
368
                trace!("ABI: {}", sig.abi);
O
Oliver Schneider 已提交
369 370 371 372 373 374
                let mut args = Vec::new();
                for arg in arg_operands {
                    let arg_val = self.eval_operand(arg)?;
                    let arg_ty = self.operand_ty(arg);
                    args.push((arg_val, arg_ty));
                }
375
                if self.eval_fn_call_inner(
O
Oliver Schneider 已提交
376 377
                    instance,
                    destination,
378
                    arg_operands,
O
Oliver Schneider 已提交
379
                    span,
380
                    sig,
381 382 383
                )? {
                    return Ok(());
                }
O
Oliver Schneider 已提交
384
                let arg_locals = self.frame().mir.args_iter();
O
Oliver Schneider 已提交
385 386 387 388 389 390
                match sig.abi {
                    Abi::Rust => {
                        args.remove(0);
                    },
                    Abi::RustCall => {},
                    _ => unimplemented!(),
O
Oliver Schneider 已提交
391 392 393 394
                };
                for (arg_local, (arg_val, arg_ty)) in arg_locals.zip(args) {
                    let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
                    self.write_value(arg_val, dest, arg_ty)?;
O
Oliver Schneider 已提交
395
                }
O
Oliver Schneider 已提交
396
                Ok(())
O
Oliver Schneider 已提交
397 398 399
            },
            ty::InstanceDef::Virtual(_, idx) => {
                let ptr_size = self.memory.pointer_size();
400
                let (_, vtable) = self.eval_operand(&arg_operands[0])?.into_ptr_vtable_pair(&self.memory)?;
401
                let fn_ptr = self.memory.read_ptr(vtable.offset(ptr_size * (idx as u64 + 3), &self)?)?;
402
                let instance = self.memory.get_fn(fn_ptr.to_ptr()?)?;
403 404
                let mut arg_operands = arg_operands.to_vec();
                let ty = self.operand_ty(&arg_operands[0]);
R
Ralf Jung 已提交
405
                let ty = self.get_field_ty(ty, 0)?.ty; // TODO: packed flag is ignored
406 407 408 409
                match arg_operands[0] {
                    mir::Operand::Consume(ref mut lval) => *lval = lval.clone().field(mir::Field::new(0), ty),
                    _ => bug!("virtual call first arg cannot be a constant"),
                }
O
Oliver Schneider 已提交
410 411
                // recurse with concrete function
                self.eval_fn_call(
O
Oliver Schneider 已提交
412 413
                    instance,
                    destination,
414
                    &arg_operands,
O
Oliver Schneider 已提交
415
                    span,
O
Oliver Schneider 已提交
416 417
                    sig,
                )
O
Oliver Schneider 已提交
418
            },
419 420
        }
    }
421

422
    /// Returns Ok(true) when the function was handled completely due to mir not being available
423 424
    fn eval_fn_call_inner(
        &mut self,
O
Oliver Schneider 已提交
425
        instance: ty::Instance<'tcx>,
426
        destination: Option<(Lvalue<'tcx>, mir::BasicBlock)>,
427
        arg_operands: &[mir::Operand<'tcx>],
428
        span: Span,
429
        sig: ty::FnSig<'tcx>,
430
    ) -> EvalResult<'tcx, bool> {
O
Oliver Schneider 已提交
431
        trace!("eval_fn_call_inner: {:#?}, {:#?}", instance, destination);
O
Oliver Schneider 已提交
432 433

        // Only trait methods can have a Self parameter.
434

O
Oliver Schneider 已提交
435
        let mir = match self.load_mir(instance.def) {
436 437
            Ok(mir) => mir,
            Err(EvalError::NoMirFor(path)) => {
O
Oliver Schneider 已提交
438
                if self.const_env() {
439 440
                    return Err(EvalError::NeedsRfc(format!("calling extern function `{}`", path)));
                }
441 442
                self.call_missing_fn(instance, destination, arg_operands, sig, path)?;
                return Ok(true);
443 444 445
            },
            Err(other) => return Err(other),
        };
446

O
Oliver Schneider 已提交
447
        if self.const_env() && !self.tcx.is_const_fn(instance.def_id()) {
448 449 450
            return Err(EvalError::NotConst(format!("calling non-const fn `{}`", instance)));
        }
        
451
        let (return_lvalue, return_to_block) = match destination {
O
Oliver Schneider 已提交
452 453
            Some((lvalue, block)) => (lvalue, StackPopCleanup::Goto(block)),
            None => (Lvalue::undef(), StackPopCleanup::None),
454 455 456
        };

        self.push_stack_frame(
O
Oliver Schneider 已提交
457
            instance,
458 459 460 461 462 463
            span,
            mir,
            return_lvalue,
            return_to_block,
        )?;

464
        Ok(false)
465 466
    }

467
    pub fn read_discriminant_value(&self, adt_ptr: MemoryPointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
468
        use rustc::ty::layout::Layout::*;
469
        let adt_layout = self.type_layout(adt_ty)?;
470
        //trace!("read_discriminant_value {:#?}", adt_layout);
471 472

        let discr_val = match *adt_layout {
473
            General { discr, .. } | CEnum { discr, signed: false, .. } => {
474
                let discr_size = discr.size().bytes();
475
                self.memory.read_uint(adt_ptr, discr_size)?
476 477
            }

478 479
            CEnum { discr, signed: true, .. } => {
                let discr_size = discr.size().bytes();
O
Oliver Schneider 已提交
480
                self.memory.read_int(adt_ptr, discr_size)? as u128
481 482
            }

483
            RawNullablePointer { nndiscr, value } => {
484
                let discr_size = value.size(&self.tcx.data_layout).bytes();
485
                trace!("rawnullablepointer with size {}", discr_size);
O
Oliver Schneider 已提交
486
                self.read_nonnull_discriminant_value(adt_ptr, nndiscr as u128, discr_size)?
487 488 489
            }

            StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
R
Ralf Jung 已提交
490
                let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty(adt_ty, nndiscr, discrfield)?;
491
                let nonnull = adt_ptr.offset(offset.bytes(), &*self)?;
492
                trace!("struct wrapped nullable pointer type: {}", ty);
493
                // only the pointer part of a fat pointer is used for this space optimization
494
                let discr_size = self.type_size(ty)?.expect("bad StructWrappedNullablePointer discrfield");
495 496
                self.read_maybe_aligned(!packed,
                    |ectx| ectx.read_nonnull_discriminant_value(nonnull, nndiscr as u128, discr_size))?
497 498 499 500
            }

            // The discriminant_value intrinsic returns 0 for non-sum types.
            Array { .. } | FatPointer { .. } | Scalar { .. } | Univariant { .. } |
O
Oliver Schneider 已提交
501
            Vector { .. } | UntaggedUnion { .. } => 0,
502 503 504 505 506
        };

        Ok(discr_val)
    }

507
    fn read_nonnull_discriminant_value(&self, ptr: MemoryPointer, nndiscr: u128, discr_size: u64) -> EvalResult<'tcx, u128> {
508
        trace!("read_nonnull_discriminant_value: {:?}, {}, {}", ptr, nndiscr, discr_size);
509
        let not_null = match self.memory.read_uint(ptr, discr_size) {
510 511 512 513 514 515 516
            Ok(0) => false,
            Ok(_) | Err(EvalError::ReadPointerAsBytes) => true,
            Err(e) => return Err(e),
        };
        assert!(nndiscr == 0 || nndiscr == 1);
        Ok(if not_null { nndiscr } else { 1 - nndiscr })
    }
517 518 519 520 521 522 523 524 525 526
    
    /// Returns Ok() when the function was handled, fail otherwise
    fn call_missing_fn(
        &mut self,
        instance: ty::Instance<'tcx>,
        destination: Option<(Lvalue<'tcx>, mir::BasicBlock)>,
        arg_operands: &[mir::Operand<'tcx>],
        sig: ty::FnSig<'tcx>,
        path: String,
    ) -> EvalResult<'tcx> {
R
Ralf Jung 已提交
527 528 529 530 531 532 533 534 535 536
        // In some cases in non-MIR libstd-mode, not having a destination is legit.  Handle these early.
        match &path[..] {
            "std::panicking::rust_panic_with_hook" |
            "std::rt::begin_panic_fmt" => return Err(EvalError::Panic),
            _ => {},
        }

        let dest_ty = sig.output();
        let (dest, dest_block) = destination.ok_or_else(|| EvalError::NoMirFor(path.clone()))?;

537 538
        if sig.abi == Abi::C {
            // An external C function
R
Ralf Jung 已提交
539 540 541
            // TODO: That functions actually has a similar preamble to what follows here.  May make sense to
            // unify these two mechanisms for "hooking into missing functions".
            self.call_c_abi(instance.def_id(), arg_operands, dest, dest_ty, dest_block)?;
542 543
            return Ok(());
        }
R
Ralf Jung 已提交
544 545 546 547 548 549 550

        let args_res: EvalResult<Vec<Value>> = arg_operands.iter()
            .map(|arg| self.eval_operand(arg))
            .collect();
        let args = args_res?;

        let usize = self.tcx.types.usize;
551 552
    
        match &path[..] {
R
Ralf Jung 已提交
553 554 555 556 557 558 559 560 561 562
            // Allocators are magic.  They have no MIR, even when the rest of libstd does.
            "alloc::heap::::__rust_alloc" => {
                let size = self.value_to_primval(args[0], usize)?.to_u64()?;
                let align = self.value_to_primval(args[1], usize)?.to_u64()?;
                if size == 0 {
                    return Err(EvalError::HeapAllocZeroBytes);
                }
                if !align.is_power_of_two() {
                    return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
                }
563
                let ptr = self.memory.allocate(size, align, Kind::Rust)?;
R
Ralf Jung 已提交
564 565 566 567 568 569 570 571 572 573 574
                self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
            }
            "alloc::heap::::__rust_alloc_zeroed" => {
                let size = self.value_to_primval(args[0], usize)?.to_u64()?;
                let align = self.value_to_primval(args[1], usize)?.to_u64()?;
                if size == 0 {
                    return Err(EvalError::HeapAllocZeroBytes);
                }
                if !align.is_power_of_two() {
                    return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
                }
575
                let ptr = self.memory.allocate(size, align, Kind::Rust)?;
576
                self.memory.write_repeat(ptr.into(), 0, size)?;
R
Ralf Jung 已提交
577 578 579
                self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
            }
            "alloc::heap::::__rust_dealloc" => {
580
                let ptr = args[0].into_ptr(&self.memory)?.to_ptr()?;
R
Ralf Jung 已提交
581 582 583 584 585 586 587 588
                let old_size = self.value_to_primval(args[1], usize)?.to_u64()?;
                let align = self.value_to_primval(args[2], usize)?.to_u64()?;
                if old_size == 0 {
                    return Err(EvalError::HeapAllocZeroBytes);
                }
                if !align.is_power_of_two() {
                    return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
                }
589
                self.memory.deallocate(ptr, Some((old_size, align)), Kind::Rust)?;
R
Ralf Jung 已提交
590 591
            }
            "alloc::heap::::__rust_realloc" => {
592
                let ptr = args[0].into_ptr(&self.memory)?.to_ptr()?;
R
Ralf Jung 已提交
593 594 595 596 597 598 599 600 601 602 603 604 605
                let old_size = self.value_to_primval(args[1], usize)?.to_u64()?;
                let old_align = self.value_to_primval(args[2], usize)?.to_u64()?;
                let new_size = self.value_to_primval(args[3], usize)?.to_u64()?;
                let new_align = self.value_to_primval(args[4], usize)?.to_u64()?;
                if old_size == 0 || new_size == 0 {
                    return Err(EvalError::HeapAllocZeroBytes);
                }
                if !old_align.is_power_of_two() {
                    return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(old_align));
                }
                if !new_align.is_power_of_two() {
                    return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(new_align));
                }
606
                let new_ptr = self.memory.reallocate(ptr, old_size, old_align, new_size, new_align, Kind::Rust)?;
R
Ralf Jung 已提交
607 608 609 610 611
                self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
            }

            // A Rust function is missing, which means we are running with MIR missing for libstd (or other dependencies).
            // Still, we can make many things mostly work by "emulating" or ignoring some functions.
612
            "std::io::_print" => {
R
Ralf Jung 已提交
613
                trace!("Ignoring output.  To run programs that print, make sure you have a libstd with full MIR.");
R
Ralf Jung 已提交
614 615 616
            }
            "std::thread::Builder::new" => return Err(EvalError::Unimplemented("miri does not support threading".to_owned())),
            "std::env::args" => return Err(EvalError::Unimplemented("miri does not support program arguments".to_owned())),
617 618 619 620
            "std::panicking::panicking" |
            "std::rt::panicking" => {
                // we abort on panic -> `std::rt::panicking` always returns false
                let bool = self.tcx.types.bool;
R
Ralf Jung 已提交
621
                self.write_primval(dest, PrimVal::from_bool(false), bool)?;
622
            }
R
Ralf Jung 已提交
623
            _ => return Err(EvalError::NoMirFor(path)),
624
        }
R
Ralf Jung 已提交
625 626 627 628 629 630 631

        // Since we pushed no stack frame, the main loop will act
        // as if the call just completed and it's returning to the
        // current frame.
        self.dump_local(dest);
        self.goto_block(dest_block);
        return Ok(());
632
    }
633 634 635 636

    fn call_c_abi(
        &mut self,
        def_id: DefId,
R
Ralf Jung 已提交
637
        arg_operands: &[mir::Operand<'tcx>],
638
        dest: Lvalue<'tcx>,
639
        dest_ty: Ty<'tcx>,
R
Ralf Jung 已提交
640
        dest_block: mir::BasicBlock,
641
    ) -> EvalResult<'tcx> {
642 643
        let name = self.tcx.item_name(def_id);
        let attrs = self.tcx.get_attrs(def_id);
644 645 646
        let link_name = attr::first_attr_value_str_by_name(&attrs, "link_name")
            .unwrap_or(name)
            .as_str();
647

R
Ralf Jung 已提交
648
        let args_res: EvalResult<Vec<Value>> = arg_operands.iter()
649
            .map(|arg| self.eval_operand(arg))
650 651 652
            .collect();
        let args = args_res?;

653 654
        let usize = self.tcx.types.usize;

655
        match &link_name[..] {
O
Oliver Schneider 已提交
656 657
            "malloc" => {
                let size = self.value_to_primval(args[0], usize)?.to_u64()?;
658
                if size == 0 {
659
                    self.write_null(dest, dest_ty)?;
660 661
                } else {
                    let align = self.memory.pointer_size();
662
                    let ptr = self.memory.allocate(size, align, Kind::C)?;
663 664
                    self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
                }
O
Oliver Schneider 已提交
665 666 667
            }

            "free" => {
668
                let ptr = args[0].into_ptr(&self.memory)?;
O
Oliver Schneider 已提交
669
                if !ptr.is_null()? {
670
                    self.memory.deallocate(ptr.to_ptr()?, None, Kind::C)?;
671
                }
O
Oliver Schneider 已提交
672 673
            }

674 675 676 677 678 679 680 681
            "syscall" => {
                match self.value_to_primval(args[0], usize)?.to_u64()? {
                    511 => return Err(EvalError::Unimplemented("miri does not support random number generators".to_owned())),
                    id => return Err(EvalError::Unimplemented(format!("miri does not support syscall id {}", id))),
                }
            }

            "dlsym" => {
682 683
                let _handle = args[0].into_ptr(&self.memory)?;
                let symbol = args[1].into_ptr(&self.memory)?.to_ptr()?;
R
Ralf Jung 已提交
684 685 686 687
                let symbol_name = self.memory.read_c_str(symbol)?;
                let err = format!("bad c unicode symbol: {:?}", symbol_name);
                let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
                return Err(EvalError::Unimplemented(format!("miri does not support dynamically loading libraries (requested symbol: {})", symbol_name)));
688 689
            }

R
Ralf Jung 已提交
690
            "__rust_maybe_catch_panic" => {
R
Ralf Jung 已提交
691
                // fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8, data_ptr: *mut usize, vtable_ptr: *mut usize) -> u32
R
Ralf Jung 已提交
692 693
                // We abort on panic, so not much is going on here, but we still have to call the closure
                let u8_ptr_ty = self.tcx.mk_mut_ptr(self.tcx.types.u8);
694 695
                let f = args[0].into_ptr(&self.memory)?.to_ptr()?;
                let data = args[1].into_ptr(&self.memory)?;
696
                let f_instance = self.memory.get_fn(f)?;
697
                self.write_null(dest, dest_ty)?;
R
Ralf Jung 已提交
698

R
Ralf Jung 已提交
699 700
                // Now we make a function call.  TODO: Consider making this re-usable?  EvalContext::step does sth. similar for the TLS dtors,
                // and of course eval_main.
R
Ralf Jung 已提交
701 702 703 704 705
                let mir = self.load_mir(f_instance.def)?;
                self.push_stack_frame(
                    f_instance,
                    mir.span,
                    mir,
O
Oliver Schneider 已提交
706
                    Lvalue::undef(),
R
Ralf Jung 已提交
707 708 709 710
                    StackPopCleanup::Goto(dest_block),
                )?;

                let arg_local = self.frame().mir.args_iter().next().ok_or(EvalError::AbiViolation("Argument to __rust_maybe_catch_panic does not take enough arguments.".to_owned()))?;
R
Ralf Jung 已提交
711
                let arg_dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
712
                self.write_ptr(arg_dest, data, u8_ptr_ty)?;
R
Ralf Jung 已提交
713

714
                // We ourselves return 0
715
                self.write_null(dest, dest_ty)?;
R
Ralf Jung 已提交
716 717 718 719 720

                // Don't fall through
                return Ok(());
            }

721 722 723 724
            "__rust_start_panic" => {
                return Err(EvalError::Panic);
            }

725
            "memcmp" => {
726 727
                let left = args[0].into_ptr(&self.memory)?;
                let right = args[1].into_ptr(&self.memory)?;
728
                let n = self.value_to_primval(args[2], usize)?.to_u64()?;
729 730 731 732 733 734 735

                let result = {
                    let left_bytes = self.memory.read_bytes(left, n)?;
                    let right_bytes = self.memory.read_bytes(right, n)?;

                    use std::cmp::Ordering::*;
                    match left_bytes.cmp(right_bytes) {
O
Oliver Schneider 已提交
736
                        Less => -1i8,
737 738 739 740 741
                        Equal => 0,
                        Greater => 1,
                    }
                };

O
Oliver Schneider 已提交
742
                self.write_primval(dest, PrimVal::Bytes(result as u128), dest_ty)?;
743 744
            }

O
Oliver Schneider 已提交
745
            "memrchr" => {
746
                let ptr = args[0].into_ptr(&self.memory)?;
O
Oliver Schneider 已提交
747 748
                let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8;
                let num = self.value_to_primval(args[2], usize)?.to_u64()?;
O
Oliver Schneider 已提交
749
                if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) {
750
                    let new_ptr = ptr.offset(num - idx as u64 - 1, &self)?;
751
                    self.write_ptr(dest, new_ptr, dest_ty)?;
O
Oliver Schneider 已提交
752
                } else {
753
                    self.write_null(dest, dest_ty)?;
O
Oliver Schneider 已提交
754 755 756
                }
            }

757
            "memchr" => {
758
                let ptr = args[0].into_ptr(&self.memory)?;
759 760
                let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8;
                let num = self.value_to_primval(args[2], usize)?.to_u64()?;
761
                if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(|&c| c == val) {
762
                    let new_ptr = ptr.offset(idx as u64, &self)?;
763
                    self.write_ptr(dest, new_ptr, dest_ty)?;
764
                } else {
765
                    self.write_null(dest, dest_ty)?;
766 767 768 769
                }
            }

            "getenv" => {
770
                let result = {
771
                    let name_ptr = args[0].into_ptr(&self.memory)?.to_ptr()?;
772
                    let name = self.memory.read_c_str(name_ptr)?;
773 774 775 776 777 778 779 780 781 782 783
                    match self.env_vars.get(name) {
                        Some(&var) => PrimVal::Ptr(var),
                        None => PrimVal::Bytes(0),
                    }
                };
                self.write_primval(dest, result, dest_ty)?;
            }

            "unsetenv" => {
                let mut success = None;
                {
784
                    let name_ptr = args[0].into_ptr(&self.memory)?;
785 786 787 788 789 790 791 792 793
                    if !name_ptr.is_null()? {
                        let name = self.memory.read_c_str(name_ptr.to_ptr()?)?;
                        if !name.is_empty() && !name.contains(&b'=') {
                            success = Some(self.env_vars.remove(name));
                        }
                    }
                }
                if let Some(old) = success {
                    if let Some(var) = old {
794
                        self.memory.deallocate(var, None, Kind::Env)?;
795
                    }
796
                    self.write_null(dest, dest_ty)?;
797 798 799 800 801 802 803 804
                } else {
                    self.write_primval(dest, PrimVal::from_i128(-1), dest_ty)?;
                }
            }

            "setenv" => {
                let mut new = None;
                {
805 806
                    let name_ptr = args[0].into_ptr(&self.memory)?;
                    let value_ptr = args[1].into_ptr(&self.memory)?.to_ptr()?;
807 808 809 810 811 812 813 814 815 816
                    let value = self.memory.read_c_str(value_ptr)?;
                    if !name_ptr.is_null()? {
                        let name = self.memory.read_c_str(name_ptr.to_ptr()?)?;
                        if !name.is_empty() && !name.contains(&b'=') {
                            new = Some((name.to_owned(), value.to_owned()));
                        }
                    }
                }
                if let Some((name, value)) = new {
                    // +1 for the null terminator
817
                    let value_copy = self.memory.allocate((value.len() + 1) as u64, 1, Kind::Env)?;
R
Ralf Jung 已提交
818
                    self.memory.write_bytes(value_copy.into(), &value)?;
819 820
                    let trailing_null = value_copy.offset(value.len() as u64, &self)?.into();
                    self.memory.write_bytes(trailing_null, &[0])?;
821
                    if let Some(var) = self.env_vars.insert(name.to_owned(), value_copy) {
822
                        self.memory.deallocate(var, None, Kind::Env)?;
823
                    }
824
                    self.write_null(dest, dest_ty)?;
825 826
                } else {
                    self.write_primval(dest, PrimVal::from_i128(-1), dest_ty)?;
827 828
                }
            }
R
Ralf Jung 已提交
829

R
Ralf Jung 已提交
830 831
            "write" => {
                let fd = self.value_to_primval(args[0], usize)?.to_u64()?;
832
                let buf = args[1].into_ptr(&self.memory)?;
R
Ralf Jung 已提交
833 834
                let n = self.value_to_primval(args[2], usize)?.to_u64()?;
                trace!("Called write({:?}, {:?}, {:?})", fd, buf, n);
R
Ralf Jung 已提交
835
                let result = if fd == 1 || fd == 2 { // stdout/stderr
R
Ralf Jung 已提交
836 837 838
                    use std::io::{self, Write};
                
                    let buf_cont = self.memory.read_bytes(buf, n)?;
R
Ralf Jung 已提交
839
                    let res = if fd == 1 { io::stdout().write(buf_cont) } else { io::stderr().write(buf_cont) };
R
Ralf Jung 已提交
840 841 842 843 844 845 846
                    match res { Ok(n) => n as isize, Err(_) => -1 }
                } else {
                    info!("Ignored output to FD {}", fd);
                    n as isize // pretend it all went well
                }; // now result is the value we return back to the program
                self.write_primval(dest, PrimVal::Bytes(result as u128), dest_ty)?;
            }
847

848
            "strlen" => {
849
                let ptr = args[0].into_ptr(&self.memory)?.to_ptr()?;
850 851 852 853
                let n = self.memory.read_c_str(ptr)?.len();
                self.write_primval(dest, PrimVal::Bytes(n as u128), dest_ty)?;
            }

854 855
            // Some things needed for sys::thread initialization to go through
            "signal" | "sigaction" | "sigaltstack" => {
856
                self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
857 858
            }

859 860 861
            "sysconf" => {
                let name = self.value_to_primval(args[0], usize)?.to_u64()?;
                trace!("sysconf() called with name {}", name);
862
                // cache the sysconf integers via miri's global cache
863 864 865 866 867 868 869
                let paths = &[
                    (&["libc", "_SC_PAGESIZE"], PrimVal::Bytes(4096)),
                    (&["libc", "_SC_GETPW_R_SIZE_MAX"], PrimVal::from_i128(-1)),
                ];
                let mut result = None;
                for &(path, path_value) in paths {
                    if let Ok(instance) = self.resolve_path(path) {
870
                        use lvalue::GlobalId;
871
                        let cid = GlobalId { instance, promoted: None };
872
                        // compute global if not cached
873
                        let val = match self.globals.get(&cid).map(|glob| glob.value) {
874
                            Some(value) => self.value_to_primval(value, usize)?.to_u64()?,
875
                            None => const_eval::eval_body_as_primval(self.tcx, instance)?.0.to_u64()?,
876 877 878 879 880 881 882 883 884 885 886 887
                        };
                        if val == name {
                            result = Some(path_value);
                            break;
                        }
                    }
                }
                if let Some(result) = result {
                    self.write_primval(dest, result, dest_ty)?;
                } else {
                    return Err(EvalError::Unimplemented(format!("Unimplemented sysconf name: {}", name)));
                }
888 889
            }

R
Ralf Jung 已提交
890 891
            // Hook pthread calls that go to the thread-local storage memory subsystem
            "pthread_key_create" => {
892
                let key_ptr = args[0].into_ptr(&self.memory)?;
893

R
Ralf Jung 已提交
894
                // Extract the function type out of the signature (that seems easier than constructing it ourselves...)
895
                let dtor = match args[1].into_ptr(&self.memory)?.into_inner_primval() {
896
                    PrimVal::Ptr(dtor_ptr) => Some(self.memory.get_fn(dtor_ptr)?),
897 898 899 900
                    PrimVal::Bytes(0) => None,
                    PrimVal::Bytes(_) => return Err(EvalError::ReadBytesAsPointer),
                    PrimVal::Undef => return Err(EvalError::ReadUndefBytes),
                };
901

R
Ralf Jung 已提交
902
                // Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t.
903 904 905 906 907
                let key_type = self.operand_ty(&arg_operands[0]).builtin_deref(true, ty::LvaluePreference::NoPreference)
                                   .ok_or(EvalError::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
                let key_size = {
                    let layout = self.type_layout(key_type)?;
                    layout.size(&self.tcx.data_layout)
R
Ralf Jung 已提交
908
                };
909

R
Ralf Jung 已提交
910
                // Create key and write it into the memory where key_ptr wants it
911 912
                let key = self.memory.create_tls_key(dtor) as u128;
                if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
R
Ralf Jung 已提交
913 914
                    return Err(EvalError::OutOfTls);
                }
915
                // TODO: Does this need checking for alignment?
916
                self.memory.write_uint(key_ptr.to_ptr()?, key, key_size.bytes())?;
917

R
Ralf Jung 已提交
918
                // Return success (0)
919
                self.write_null(dest, dest_ty)?;
R
Ralf Jung 已提交
920 921 922 923 924 925
            }
            "pthread_key_delete" => {
                // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
                let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey;
                self.memory.delete_tls_key(key)?;
                // Return success (0)
926
                self.write_null(dest, dest_ty)?;
R
Ralf Jung 已提交
927 928 929 930 931
            }
            "pthread_getspecific" => {
                // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
                let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey;
                let ptr = self.memory.load_tls(key)?;
932
                self.write_ptr(dest, ptr, dest_ty)?;
R
Ralf Jung 已提交
933 934 935 936
            }
            "pthread_setspecific" => {
                // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t
                let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey;
937
                let new_ptr = args[1].into_ptr(&self.memory)?;
R
Ralf Jung 已提交
938 939 940
                self.memory.store_tls(key, new_ptr)?;
                
                // Return success (0)
941
                self.write_null(dest, dest_ty)?;
R
Ralf Jung 已提交
942 943
            }

944
            // Stub out all the other pthread calls to just return 0
945 946
            link_name if link_name.starts_with("pthread_") => {
                warn!("ignoring C ABI call: {}", link_name);
947
                self.write_null(dest, dest_ty)?;
948 949
            },

950 951 952 953 954 955 956 957
            _ => {
                return Err(EvalError::Unimplemented(format!("can't call C ABI function: {}", link_name)));
            }
        }

        // Since we pushed no stack frame, the main loop will act
        // as if the call just completed and it's returning to the
        // current frame.
R
Ralf Jung 已提交
958 959
        self.dump_local(dest);
        self.goto_block(dest_block);
960
        Ok(())
R
Ralf Jung 已提交
961
    }
962 963 964

    /// Get an instance for a path.
    fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
        let cstore = &self.tcx.sess.cstore;

        let crates = cstore.crates();
        crates.iter()
            .find(|&&krate| cstore.crate_name(krate) == path[0])
            .and_then(|krate| {
                let krate = DefId {
                    krate: *krate,
                    index: CRATE_DEF_INDEX,
                };
                let mut items = cstore.item_children(krate, self.tcx.sess);
                let mut path_it = path.iter().skip(1).peekable();

                while let Some(segment) = path_it.next() {
                    for item in &mem::replace(&mut items, vec![]) {
                        if item.ident.name == *segment {
                            if path_it.peek().is_none() {
982
                                return Some(ty::Instance::mono(self.tcx, item.def.def_id()));
983 984 985 986 987 988 989 990 991
                            }

                            items = cstore.item_children(item.def.def_id(), self.tcx.sess);
                            break;
                        }
                    }
                }
                None
            })
992 993 994 995 996 997
            .ok_or_else(|| {
                let path = path.iter()
                    .map(|&s| s.to_owned())
                    .collect();
                EvalError::PathNotFound(path)
            })
998
    }
O
Oliver Schneider 已提交
999
}