Skip to content

Instantly share code, notes, and snippets.

@eddyb eddyb/get_stats.rs Secret
Last active Dec 9, 2015

Embed
What would you like to do?
#![feature(rustc_private, time2)]
extern crate syntax;
use std::path::PathBuf;
use std::time::Instant;
use syntax::codemap::CodeMap;
use syntax::diagnostic::{ColorConfig, Handler, SpanHandler};
use syntax::parse::lexer::{self, Reader};
fn main() {
let sh = SpanHandler::new(Handler::new(ColorConfig::Auto, None, false), CodeMap::new());
let codemap = &sh.cm;
let file = PathBuf::from(std::env::args().nth(1).expect("file name required"));
let filemap = codemap.load_file(&file).unwrap();
let mut reader = lexer::StringReader::new(&sh, filemap);
let mut tokens_u64_x11: Vec<[u64; 11]> = vec![];
let mut tokens_u8: Vec<u8> = vec![];
loop {
use syntax::parse::token::Token::*;
let tag = match reader.next_token().tok {
// Simple tokens (no metadata).
Eq | Lt | Le | EqEq | Ne | Ge | Gt |
AndAnd | OrOr | Not | Tilde |
BinOp(_) | BinOpEq(_) |
At | Dot | DotDot | DotDotDot |
Comma | Semi | Colon | ModSep |
RArrow | LArrow | FatArrow |
Pound | Dollar | Question | Underscore => 0,
// Tokens that carry some extra data.
OpenDelim(_) | CloseDelim(_) => 1,
tok @ Ident(..) => {
if tok.is_any_keyword() {
2
} else {
3
}
}
Lifetime(_) => 3,
Literal(..) => 4,
// Macro-related tokens (shouldn't occur in our pre-expanded code).
Interpolated(_) => unreachable!("Interpolated"),
SpecialVarNt(_) => unreachable!("SpecialVarNt"),
MatchNt(..) => unreachable!("MatchNt"),
SubstNt(..) => unreachable!("SubstNt"),
// Whitespace.
DocComment(_) | Comment |
Shebang(_) | Whitespace => continue,
Eof => break
};
tokens_u64_x11.push([tag, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
tokens_u8.push(tag as u8);
}
for &compact in &[false, true] {
let start = Instant::now();
let mut last_meta = 0;
let mut max_meta_dist = 0;
let (mut count, mut delimiters, mut idents, mut keywords, mut literals) = (0, 0, 0, 0, 0);
if compact {
for &tok in &tokens_u8 {
let mut has_meta = false;
match tok {
// Simple tokens (no metadata).
0 => {},
// Tokens that carry some extra data.
1 => {
delimiters += 1;
has_meta = true;
}
2 => {
idents += 1;
keywords += 1;
}
3 => {
idents += 1;
has_meta = true;
}
4 => {
literals += 1;
has_meta = true;
}
_ => unreachable!()
}
if has_meta {
let dist = count - last_meta;
if dist > max_meta_dist {
max_meta_dist = dist;
}
last_meta = count;
}
count += 1;
}
} else {
for a in &tokens_u64_x11 {
let tok = a[0];
let mut has_meta = false;
match tok {
// Simple tokens (no metadata).
0 => {},
// Tokens that carry some extra data.
1 => {
delimiters += 1;
has_meta = true;
}
2 => {
idents += 1;
keywords += 1;
}
3 => {
idents += 1;
has_meta = true;
}
4 => {
literals += 1;
has_meta = true;
}
_ => unreachable!()
}
if has_meta {
let dist = count - last_meta;
if dist > max_meta_dist {
max_meta_dist = dist;
}
last_meta = count;
}
count += 1;
}
}
let dur = start.elapsed();
const NANOS_PER_SEC: f64 = 1_000_000_000.0;
let secs = dur.as_secs() as f64;
let secs = secs + dur.subsec_nanos() as f64 / NANOS_PER_SEC;
println!("\nStats with {} per token:",
if compact { "one byte" } else { "88 bytes" });
println!("size: {:.1}kB",
if compact {
tokens_u8.len()
} else {
tokens_u64_x11.len() * 88
} as f64 / 1024.0);
println!("time to iterate tokens: {:.3}s", secs);
println!("total: {}", count);
println!("delimiters: {}", delimiters);
println!("idents: {}", idents);
println!("keywords: {}", keywords);
println!("literals: {}", literals);
println!("non-keyword idents: {}", idents - keywords);
let with_meta = delimiters + (idents - keywords) + literals;
println!("tokens w/ metadata: {}", with_meta);
println!("largest distance between tokens w/ metadata: {}", max_meta_dist);
if compact {
println!("variable-sized encoding: {:.1}kB", (count + with_meta * 4) as f64 / 1024.0);
}
}
}
Stats with 88 bytes per token:
size: 59297.6kB
time to iterate tokens: 0.007s
total: 690009
delimiters: 167188
idents: 261909
keywords: 51115
literals: 9858
non-keyword idents: 210794
tokens w/ metadata: 387840
largest distance between tokens w/ metadata: 12
Stats with one byte per token:
size: 673.8kB
time to iterate tokens: 0.005s
total: 690009
delimiters: 167188
idents: 261909
keywords: 51115
literals: 9858
non-keyword idents: 210794
tokens w/ metadata: 387840
largest distance between tokens w/ metadata: 12
variable-sized encoding: 2188.8kB
This file has been truncated, but you can view the full file.
#![feature(no_std, prelude_import)]
#![no_std]
// Copyright 2012-2013 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.
//! The Rust compiler.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![feature(custom_attribute)]
#![crate_name = "rustc"]
#![unstable(feature = "rustc_private", issue = "27812")]
#![staged_api]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url =
"https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cell_extras)]
#![feature(clone_from_slice)]
#![feature(collections)]
#![feature(const_fn)]
#![feature(enumset)]
#![feature(hashmap_hasher)]
#![feature(into_cow)]
#![feature(iter_arith)]
#![feature(libc)]
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(scoped_tls)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(str_char)]
#![feature(time2)]
#![feature(wrapping)]
#![allow(trivial_casts)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std as std;
extern crate arena;
extern crate core;
extern crate flate;
extern crate fmt_macros;
extern crate getopts;
extern crate graphviz;
extern crate libc;
extern crate rustc_llvm;
extern crate rustc_back;
extern crate rustc_front;
extern crate rustc_data_structures;
extern crate serialize;
extern crate collections;
#[macro_use]
extern crate log;
#[macro_use]
extern crate syntax;
#[macro_use]
#[no_link]
extern crate rustc_bitflags;
extern crate serialize as rustc_serialize;
// used by deriving
pub use rustc_llvm as llvm;
#[macro_use]
mod macros {
#[prelude_import]
use std::prelude::v1::*;
}
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics {
// STAGE0: increase glitch immunity
// A private module so that macro-expanded idents like
// `::rustc::lint::Lint` will also work in `rustc` itself.
//
// `libstd` uses the same trick.
// FIXME(#27438): right now the unit tests of librustc don't refer to any actual
// functions generated in librustc_data_structures (all
// references are through generic functions), but statics are
// referenced from time to time. Due to this bug we won't
// actually correctly link in the statics unless we also
// reference a function, so be sure to reference a dummy
// function.
// Build the diagnostics array at the end so that the metadata includes error use sites.
#![allow(non_snake_case)]
#[prelude_import]
use std::prelude::v1::*;
mod __register_diagnostic_E0001 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0002 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0003 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0004 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0005 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0007 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0008 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0009 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0010 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0011 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0013 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0014 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0015 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0016 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0017 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0018 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0019 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0020 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0022 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0030 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0038 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0109 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0110 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0133 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0136 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0137 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0138 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0139 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0152 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0158 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0161 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0162 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0165 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0170 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0261 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0262 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0263 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0265 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0267 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0268 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0269 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0270 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0271 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0272 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0273 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0274 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0275 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0276 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0277 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0281 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0282 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0296 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0297 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0301 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0302 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0303 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0306 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0307 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0308 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0309 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0310 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0378 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0394 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0395 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0396 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0397 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0398 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0400 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0492 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0493 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0494 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0496 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0497 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0517 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0518 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0229 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0264 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0278 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0279 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0280 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0283 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0284 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0285 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0298 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0299 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0300 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0304 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0305 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0311 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0312 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0313 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0314 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0315 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0316 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0452 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0453 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0471 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0472 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0473 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0474 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0475 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0476 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0477 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0478 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0479 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0480 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0481 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0482 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0483 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0484 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0485 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0486 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0487 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0488 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0489 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0490 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0491 {
#[prelude_import]
use std::prelude::v1::*;
}
mod __register_diagnostic_E0495 {
#[prelude_import]
use std::prelude::v1::*;
}
}
pub mod back {
#[prelude_import]
use std::prelude::v1::*;
pub use rustc_back::abi;
pub use rustc_back::rpath;
pub use rustc_back::svh;
}
pub mod front {
#[prelude_import]
use std::prelude::v1::*;
pub mod check_attr {
#[prelude_import]
use std::prelude::v1::*;
use session::Session;
use syntax::ast;
use syntax::attr::AttrMetaMethods;
use syntax::visit;
use syntax::visit::Visitor;
enum Target { Fn, Struct, Enum, Other, }
#[automatically_derived]
impl ::std::cmp::PartialEq for Target {
#[inline]
fn eq(&self, __arg_0: &Target) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Target::Fn, &Target::Fn) => true,
(&Target::Struct, &Target::Struct) => true,
(&Target::Enum, &Target::Enum) => true,
(&Target::Other, &Target::Other) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &Target) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Target::Fn, &Target::Fn) => false,
(&Target::Struct, &Target::Struct) => false,
(&Target::Enum, &Target::Enum) => false,
(&Target::Other, &Target::Other) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for Target {
#[inline]
fn clone(&self) -> Target {
match (&*self,) {
(&Target::Fn,) => Target::Fn,
(&Target::Struct,) => Target::Struct,
(&Target::Enum,) => Target::Enum,
(&Target::Other,) => Target::Other,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for Target { }
impl Target {
fn from_item(item: &ast::Item) -> Target {
match item.node {
ast::ItemFn(..) => Target::Fn,
ast::ItemStruct(..) => Target::Struct,
ast::ItemEnum(..) => Target::Enum,
_ => Target::Other,
}
}
}
struct CheckAttrVisitor<'a> {
sess: &'a Session,
}
impl <'a> CheckAttrVisitor<'a> {
fn check_inline(&self, attr: &ast::Attribute, target: Target) {
if target != Target::Fn {
{
();
self.sess.span_err_with_code(attr.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["attribute should be applied to function"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0518")
};
}
}
fn check_repr(&self, attr: &ast::Attribute, target: Target) {
let words =
match attr.meta_item_list() {
Some(words) => words,
None => { return; }
};
{
let result =
match ::std::iter::IntoIterator::into_iter(words) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(word) => {
let word: &str = &word.name();
let message =
match word {
"C" => {
if target !=
Target::Struct &&
target !=
Target::Enum {
"attribute should be applied to struct or enum"
} else { continue }
}
"packed" | "simd" => {
if target !=
Target::Struct {
"attribute should be applied to struct"
} else { continue }
}
"i8" | "u8" | "i16" | "u16" |
"i32" | "u32" | "i64" | "u64"
| "isize" | "usize" => {
if target != Target::Enum
{
"attribute should be applied to enum"
} else { continue }
}
_ => continue ,
};
{
();
self.sess.span_err_with_code(attr.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[""];
__STATIC_FMTSTR
},
&match (&message,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0517")
};
}
::std::option::Option::None => break ,
}
},
};
result
}
}
fn check_attribute(&self, attr: &ast::Attribute, target: Target) {
let name: &str = &attr.name();
match name {
"inline" => self.check_inline(attr, target),
"repr" => self.check_repr(attr, target),
_ => (),
}
}
}
impl <'a, 'v> Visitor<'v> for CheckAttrVisitor<'a> {
fn visit_item(&mut self, item: &ast::Item) {
let target = Target::from_item(item);
{
let result =
match ::std::iter::IntoIterator::into_iter(&item.attrs)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(attr) => {
self.check_attribute(attr, target);
}
::std::option::Option::None => break ,
}
},
};
result
}
}
}
pub fn check_crate(sess: &Session, krate: &ast::Crate) {
visit::walk_crate(&mut CheckAttrVisitor{sess: sess,}, krate);
}
}
pub mod map {
#[prelude_import]
use std::prelude::v1::*;
pub use self::Node::*;
pub use self::PathElem::*;
use self::MapEntry::*;
use self::collector::NodeCollector;
pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
DisambiguatedDefPathData};
use middle::cstore::InlinedItem;
use middle::cstore::InlinedItem as II;
use middle::def_id::DefId;
use syntax::abi;
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID};
use syntax::codemap::{Span, Spanned};
use syntax::parse::token;
use rustc_front::hir::*;
use rustc_front::fold::Folder;
use rustc_front::intravisit;
use rustc_front::print::pprust;
use arena::TypedArena;
use std::cell::RefCell;
use std::fmt;
use std::io;
use std::iter;
use std::mem;
use std::slice;
pub mod blocks {
//! This module provides a simplified abstraction for working with
//! code blocks identified by their integer node-id. In particular,
//! it captures a common set of attributes that all "function-like
//! things" (represented by `FnLike` instances) share. For example,
//! all `FnLike` instances have a type signature (be it explicit or
//! inferred). And all `FnLike` instances have a body, i.e. the code
//! that is run when the function-like thing it represents is invoked.
//!
//! With the above abstraction in place, one can treat the program
//! text as a collection of blocks of code (and most such blocks are
//! nested within a uniquely determined `FnLike`), and users can ask
//! for the `Code` associated with a particular NodeId.
#[prelude_import]
use std::prelude::v1::*;
pub use self::Code::*;
use front::map::{self, Node};
use syntax::abi;
use rustc_front::hir::{Block, FnDecl};
use syntax::ast::{Name, NodeId};
use rustc_front::hir as ast;
use syntax::codemap::Span;
use rustc_front::intravisit::FnKind;
/// An FnLikeNode is a Node that is like a fn, in that it has a decl
/// and a body (as well as a NodeId, a span, etc).
///
/// More specifically, it is one of either:
/// - A function item,
/// - A closure expr (i.e. an ExprClosure), or
/// - The default implementation for a trait method.
///
/// To construct one, use the `Code::from_node` function.
pub struct FnLikeNode<'a> {
node: map::Node<'a>,
}
#[automatically_derived]
impl <'a> ::std::clone::Clone for FnLikeNode<'a> {
#[inline]
fn clone(&self) -> FnLikeNode<'a> {
match *self {
FnLikeNode { node: ref __self_0_0 } =>
FnLikeNode{node:
::std::clone::Clone::clone(&(*__self_0_0)),},
}
}
}
#[automatically_derived]
impl <'a> ::std::marker::Copy for FnLikeNode<'a> { }
/// MaybeFnLike wraps a method that indicates if an object
/// corresponds to some FnLikeNode.
pub trait MaybeFnLike {
fn is_fn_like(&self)
-> bool;
}
/// Components shared by fn-like things (fn items, methods, closures).
pub struct FnParts<'a> {
pub decl: &'a FnDecl,
pub body: &'a Block,
pub kind: FnKind<'a>,
pub span: Span,
pub id: NodeId,
}
impl MaybeFnLike for ast::Item {
fn is_fn_like(&self) -> bool {
match self.node { ast::ItemFn(..) => true, _ => false, }
}
}
impl MaybeFnLike for ast::TraitItem {
fn is_fn_like(&self) -> bool {
match self.node {
ast::MethodTraitItem(_, Some(_)) => true,
_ => false,
}
}
}
impl MaybeFnLike for ast::Expr {
fn is_fn_like(&self) -> bool {
match self.node {
ast::ExprClosure(..) => true,
_ => false,
}
}
}
/// Carries either an FnLikeNode or a Block, as these are the two
/// constructs that correspond to "code" (as in, something from which
/// we can construct a control-flow graph).
pub enum Code<'a> {
FnLikeCode(FnLikeNode<'a>),
BlockCode(&'a Block),
}
#[automatically_derived]
impl <'a> ::std::clone::Clone for Code<'a> {
#[inline]
fn clone(&self) -> Code<'a> {
match (&*self,) {
(&Code::FnLikeCode(ref __self_0),) =>
Code::FnLikeCode(::std::clone::Clone::clone(&(*__self_0))),
(&Code::BlockCode(ref __self_0),) =>
Code::BlockCode(::std::clone::Clone::clone(&(*__self_0))),
}
}
}
#[automatically_derived]
impl <'a> ::std::marker::Copy for Code<'a> { }
impl <'a> Code<'a> {
pub fn id(&self) -> NodeId {
match *self {
FnLikeCode(node) => node.id(),
BlockCode(block) => block.id,
}
}
/// Attempts to construct a Code from presumed FnLike or Block node input.
pub fn from_node(node: Node) -> Option<Code> {
match node {
map::NodeBlock(block) => { Some(BlockCode(block)) }
_ => {
FnLikeNode::from_node(node).map(|fn_like|
FnLikeCode(fn_like))
}
}
}
}
/// These are all the components one can extract from a fn item for
/// use when implementing FnLikeNode operations.
struct ItemFnParts<'a> {
name: Name,
decl: &'a ast::FnDecl,
unsafety: ast::Unsafety,
constness: ast::Constness,
abi: abi::Abi,
vis: ast::Visibility,
generics: &'a ast::Generics,
body: &'a Block,
id: NodeId,
span: Span,
}
/// These are all the components one can extract from a closure expr
/// for use when implementing FnLikeNode operations.
struct ClosureParts<'a> {
decl: &'a FnDecl,
body: &'a Block,
id: NodeId,
span: Span,
}
impl <'a> ClosureParts<'a> {
fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span)
-> ClosureParts<'a> {
ClosureParts{decl: d, body: b, id: id, span: s,}
}
}
impl <'a> FnLikeNode<'a> {
/// Attempts to construct a FnLikeNode from presumed FnLike node input.
pub fn from_node(node: Node) -> Option<FnLikeNode> {
let fn_like =
match node {
map::NodeItem(item) => item.is_fn_like(),
map::NodeTraitItem(tm) => tm.is_fn_like(),
map::NodeImplItem(_) => true,
map::NodeExpr(e) => e.is_fn_like(),
_ => false,
};
if fn_like { Some(FnLikeNode{node: node,}) } else { None }
}
pub fn to_fn_parts(self) -> FnParts<'a> {
FnParts{decl: self.decl(),
body: self.body(),
kind: self.kind(),
span: self.span(),
id: self.id(),}
}
pub fn body(self) -> &'a Block {
self.handle(|i: ItemFnParts<'a>| &*i.body,
|_, _, _: &'a ast::MethodSig, _,
body: &'a ast::Block, _| body,
|c: ClosureParts<'a>| c.body)
}
pub fn decl(self) -> &'a FnDecl {
self.handle(|i: ItemFnParts<'a>| &*i.decl,
|_, _, sig: &'a ast::MethodSig, _, _, _|
&sig.decl, |c: ClosureParts<'a>| c.decl)
}
pub fn span(self) -> Span {
self.handle(|i: ItemFnParts| i.span,
|_, _, _: &'a ast::MethodSig, _, _, span|
span, |c: ClosureParts| c.span)
}
pub fn id(self) -> NodeId {
self.handle(|i: ItemFnParts| i.id,
|id, _, _: &'a ast::MethodSig, _, _, _| id,
|c: ClosureParts| c.id)
}
pub fn kind(self) -> FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
FnKind::ItemFn(p.name, p.generics, p.unsafety,
p.constness, p.abi, p.vis) };
let closure = |_: ClosureParts| { FnKind::Closure };
let method =
|_, name: Name, sig: &'a ast::MethodSig, vis, _, _| {
FnKind::Method(name, sig, vis) };
self.handle(item, method, closure)
}
fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C)
-> A where I: FnOnce(ItemFnParts<'a>) -> A,
M: FnOnce(NodeId, Name, &'a ast::MethodSig,
Option<ast::Visibility>, &'a ast::Block, Span) ->
A, C: FnOnce(ClosureParts<'a>) -> A {
match self.node {
map::NodeItem(i) =>
match i.node {
ast::ItemFn(ref decl, unsafety, constness, abi,
ref generics, ref block) =>
item_fn(ItemFnParts{id: i.id,
name: i.name,
decl: &**decl,
unsafety: unsafety,
body: &**block,
generics: generics,
abi: abi,
vis: i.vis,
constness: constness,
span: i.span,}),
_ => {
::std::rt::begin_unwind("item FnLikeNode that is not fn-like",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/blocks.rs",
229u32);
&_FILE_LINE
})
}
},
map::NodeTraitItem(ti) =>
match ti.node {
ast::MethodTraitItem(ref sig, Some(ref body)) => {
method(ti.id, ti.name, sig, None, body,
ti.span)
}
_ => {
::std::rt::begin_unwind("trait method FnLikeNode that is not fn-like",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/blocks.rs",
235u32);
&_FILE_LINE
})
}
},
map::NodeImplItem(ii) => {
match ii.node {
ast::ImplItemKind::Method(ref sig, ref body)
=> {
method(ii.id, ii.name, sig, Some(ii.vis),
body, ii.span)
}
_ => {
{
::std::rt::begin_unwind("impl method FnLikeNode that is not fn-like",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/front/map/blocks.rs",
243u32);
&_FILE_LINE
})
}
}
}
}
map::NodeExpr(e) =>
match e.node {
ast::ExprClosure(_, ref decl, ref block) =>
closure(ClosureParts::new(&**decl, &**block, e.id,
e.span)),
_ => {
::std::rt::begin_unwind("expr FnLikeNode that is not fn-like",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/blocks.rs",
250u32);
&_FILE_LINE
})
}
},
_ => {
::std::rt::begin_unwind("other FnLikeNode that is not fn-like",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/blocks.rs",
252u32);
&_FILE_LINE
})
}
}
}
}
}
mod collector {
#[prelude_import]
use std::prelude::v1::*;
use super::*;
use super::MapEntry::*;
use rustc_front::hir::*;
use rustc_front::util;
use rustc_front::intravisit::{self, Visitor};
use middle::def_id::{CRATE_DEF_INDEX, DefIndex};
use std::iter::repeat;
use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
use syntax::codemap::Span;
/// A Visitor that walks over an AST and collects Node's into an AST
/// Map.
pub struct NodeCollector<'ast> {
pub krate: &'ast Crate,
pub map: Vec<MapEntry<'ast>>,
pub definitions: Definitions,
pub parent_node: NodeId,
}
impl <'ast> NodeCollector<'ast> {
pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> {
let mut collector =
NodeCollector{krate: krate,
map:
<[_]>::into_vec(::std::boxed::Box::new([])),
definitions: Definitions::new(),
parent_node: CRATE_NODE_ID,};
collector.insert_entry(CRATE_NODE_ID, RootCrate);
let result =
collector.create_def_with_parent(None, CRATE_NODE_ID,
DefPathData::CrateRoot);
{
match (&(result), &(CRATE_DEF_INDEX)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/front/map/collector.rs",
42u32);
&_FILE_LINE
})
}
}
}
}
};
collector.create_def_with_parent(Some(CRATE_DEF_INDEX),
DUMMY_NODE_ID,
DefPathData::Misc);
collector
}
pub fn extend(krate: &'ast Crate, parent: &'ast InlinedParent,
parent_node: NodeId, parent_def_path: DefPath,
map: Vec<MapEntry<'ast>>,
definitions: Definitions)
-> NodeCollector<'ast> {
let mut collector =
NodeCollector{krate: krate,
map: map,
parent_node: parent_node,
definitions: definitions,};
collector.insert_entry(parent_node,
RootInlinedParent(parent));
collector.create_def(parent_node,
DefPathData::InlinedRoot(parent_def_path));
collector
}
fn parent_def(&self) -> Option<DefIndex> {
let mut parent_node = Some(self.parent_node);
loop {
match parent_node {
Some(p) => {
match self.definitions.opt_def_index(p) {
Some(q) => { return Some(q); }
_ => (),
}
parent_node =
self.map[p as usize].parent_node();
}
_ => break ,
}
}
None
}
fn create_def(&mut self, node_id: NodeId, data: DefPathData)
-> DefIndex {
let parent_def = self.parent_def();
self.definitions.create_def_with_parent(parent_def,
node_id, data)
}
fn create_def_with_parent(&mut self, parent: Option<DefIndex>,
node_id: NodeId, data: DefPathData)
-> DefIndex {
self.definitions.create_def_with_parent(parent, node_id,
data)
}
fn insert_entry(&mut self, id: NodeId,
entry: MapEntry<'ast>) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 94u32,
file:
"src/librustc/front/map/collector.rs",
module_path:
"rustc::front::map::collector",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::front::map::collector")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["ast_map: ",
" => "];
__STATIC_FMTSTR
},
&match (&id,
&entry)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
let len = self.map.len();
if id as usize >= len {
self.map.extend(repeat(NotPresent).take(id as usize -
len + 1));
}
self.map[id as usize] = entry;
}
fn insert_def(&mut self, id: NodeId, node: Node<'ast>,
data: DefPathData) -> DefIndex {
self.insert(id, node);
self.create_def(id, data)
}
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
let entry = MapEntry::from_node(self.parent_node, node);
self.insert_entry(id, entry);
}
}
impl <'ast> Visitor<'ast> for NodeCollector<'ast> {
/// Because we want to track parent items and so forth, enable
/// deep walking so that we walk nested items in the context of
/// their outer items.
fn visit_nested_item(&mut self, item: ItemId) {
self.visit_item(self.krate.item(item.id))
}
fn visit_item(&mut self, i: &'ast Item) {
let def_data =
match i.node {
ItemDefaultImpl(..) | ItemImpl(..) =>
DefPathData::Impl,
ItemEnum(..) | ItemStruct(..) | ItemTrait(..) =>
DefPathData::Type(i.name),
ItemExternCrate(..) | ItemMod(..) =>
DefPathData::Mod(i.name),
ItemStatic(..) | ItemConst(..) | ItemFn(..) =>
DefPathData::Value(i.name),
_ => DefPathData::Misc,
};
self.insert_def(i.id, NodeItem(i), def_data);
let parent_node = self.parent_node;
self.parent_node = i.id;
match i.node {
ItemImpl(..) => { }
ItemEnum(ref enum_definition, _) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(&enum_definition.variants)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(v)
=> {
let variant_def_index =
self.insert_def(v.node.data.id(),
NodeVariant(&**v),
DefPathData::EnumVariant(v.node.name));
{
let result =
match ::std::iter::IntoIterator::into_iter(v.node.data.fields())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(field)
=> {
self.create_def_with_parent(Some(variant_def_index),
field.node.id,
DefPathData::Field(field.node.kind));
}
::std::option::Option::None
=>
break
,
}
},
};
result
}
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
ItemForeignMod(..) => { }
ItemStruct(ref struct_def, _) => {
if !struct_def.is_struct() {
self.insert_def(struct_def.id(),
NodeStructCtor(struct_def),
DefPathData::StructCtor);
}
{
let result =
match ::std::iter::IntoIterator::into_iter(struct_def.fields())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(field)
=> {
self.create_def(field.node.id,
DefPathData::Field(field.node.kind));
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
ItemTrait(_, _, ref bounds, _) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(bounds.iter())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(b)
=> {
match *b {
TraitTyParamBound(ref t,
TraitBoundModifier::None)
=> {
self.insert(t.trait_ref.ref_id,
NodeItem(i));
}
_ => (),
}
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
ItemUse(ref view_path) => {
match view_path.node {
ViewPathList(_, ref paths) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(paths)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(path)
=> {
self.insert(path.node.id(),
NodeItem(i));
}
::std::option::Option::None
=> break ,
}
},
};
result
}
}
_ => (),
}
}
_ => { }
}
intravisit::walk_item(self, i);
self.parent_node = parent_node;
}
fn visit_foreign_item(&mut self,
foreign_item: &'ast ForeignItem) {
self.insert_def(foreign_item.id,
NodeForeignItem(foreign_item),
DefPathData::Value(foreign_item.name));
let parent_node = self.parent_node;
self.parent_node = foreign_item.id;
intravisit::walk_foreign_item(self, foreign_item);
self.parent_node = parent_node;
}
fn visit_generics(&mut self, generics: &'ast Generics) {
{
let result =
match ::std::iter::IntoIterator::into_iter(generics.ty_params.iter())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(ty_param)
=> {
self.insert_def(ty_param.id,
NodeTyParam(ty_param),
DefPathData::TypeParam(ty_param.name));
}
::std::option::Option::None => break ,
}
},
};
result
}
intravisit::walk_generics(self, generics);
}
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
let def_data =
match ti.node {
MethodTraitItem(..) | ConstTraitItem(..) =>
DefPathData::Value(ti.name),
TypeTraitItem(..) => DefPathData::Type(ti.name),
};
self.insert(ti.id, NodeTraitItem(ti));
self.create_def(ti.id, def_data);
let parent_node = self.parent_node;
self.parent_node = ti.id;
match ti.node {
ConstTraitItem(_, Some(ref expr)) => {
self.create_def(expr.id,
DefPathData::Initializer);
}
_ => { }
}
intravisit::walk_trait_item(self, ti);
self.parent_node = parent_node;
}
fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
let def_data =
match ii.node {
ImplItemKind::Method(..) | ImplItemKind::Const(..)
=> DefPathData::Value(ii.name),
ImplItemKind::Type(..) =>
DefPathData::Type(ii.name),
};
self.insert_def(ii.id, NodeImplItem(ii), def_data);
let parent_node = self.parent_node;
self.parent_node = ii.id;
match ii.node {
ImplItemKind::Const(_, ref expr) => {
self.create_def(expr.id,
DefPathData::Initializer);
}
_ => { }
}
intravisit::walk_impl_item(self, ii);
self.parent_node = parent_node;
}
fn visit_pat(&mut self, pat: &'ast Pat) {
let maybe_binding =
match pat.node {
PatIdent(_, id, _) => Some(id.node),
_ => None,
};
match maybe_binding {
Some(id) => {
self.insert_def(pat.id, NodeLocal(pat),
DefPathData::Binding(id.name));
}
_ => { self.insert(pat.id, NodePat(pat)); }
}
let parent_node = self.parent_node;
self.parent_node = pat.id;
intravisit::walk_pat(self, pat);
self.parent_node = parent_node;
}
fn visit_expr(&mut self, expr: &'ast Expr) {
self.insert(expr.id, NodeExpr(expr));
match expr.node {
ExprClosure(..) => {
self.create_def(expr.id,
DefPathData::ClosureExpr);
}
_ => { }
}
let parent_node = self.parent_node;
self.parent_node = expr.id;
intravisit::walk_expr(self, expr);
self.parent_node = parent_node;
}
fn visit_stmt(&mut self, stmt: &'ast Stmt) {
let id = util::stmt_id(stmt);
self.insert(id, NodeStmt(stmt));
let parent_node = self.parent_node;
self.parent_node = id;
intravisit::walk_stmt(self, stmt);
self.parent_node = parent_node;
}
fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>,
fd: &'ast FnDecl, b: &'ast Block, s: Span,
id: NodeId) {
{
match (&(self.parent_node), &(id)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/front/map/collector.rs",
302u32);
&_FILE_LINE
})
}
}
}
}
};
intravisit::walk_fn(self, fk, fd, b, s);
}
fn visit_block(&mut self, block: &'ast Block) {
self.insert(block.id, NodeBlock(block));
let parent_node = self.parent_node;
self.parent_node = block.id;
intravisit::walk_block(self, block);
self.parent_node = parent_node;
}
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
self.insert(lifetime.id, NodeLifetime(lifetime));
}
fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
self.create_def(def.lifetime.id,
DefPathData::LifetimeDef(def.lifetime.name));
self.visit_lifetime(&def.lifetime);
}
fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
self.create_def(macro_def.id,
DefPathData::MacroDef(macro_def.name));
}
}
}
pub mod definitions {
#[prelude_import]
use std::prelude::v1::*;
use middle::cstore::LOCAL_CRATE;
use middle::def_id::{DefId, DefIndex};
use rustc_data_structures::fnv::FnvHashMap;
use rustc_front::hir;
use syntax::ast;
use syntax::parse::token::InternedString;
use util::nodemap::NodeMap;
pub struct Definitions {
data: Vec<DefData>,
key_map: FnvHashMap<DefKey, DefIndex>,
node_map: NodeMap<DefIndex>,
}
#[automatically_derived]
impl ::std::clone::Clone for Definitions {
#[inline]
fn clone(&self) -> Definitions {
match *self {
Definitions {
data: ref __self_0_0,
key_map: ref __self_0_1,
node_map: ref __self_0_2 } =>
Definitions{data:
::std::clone::Clone::clone(&(*__self_0_0)),
key_map:
::std::clone::Clone::clone(&(*__self_0_1)),
node_map:
::std::clone::Clone::clone(&(*__self_0_2)),},
}
}
}
/// A unique identifier that we can use to lookup a definition
/// precisely. It combines the index of the definition's parent (if
/// any) with a `DisambiguatedDefPathData`.
pub struct DefKey {
/// Parent path.
pub parent: Option<DefIndex>,
/// Identifier of this node.
pub disambiguated_data: DisambiguatedDefPathData,
}
#[automatically_derived]
impl ::rustc_serialize::Decodable for DefKey {
fn decode<__D: ::rustc_serialize::Decoder>(__arg_0: &mut __D)
-> ::std::result::Result<DefKey, __D::Error> {
__arg_0.read_struct("DefKey", 2usize, |_d| -> _ {
::std::result::Result::Ok(DefKey{parent:
match _d.read_struct_field("parent",
0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
},
disambiguated_data:
match _d.read_struct_field("disambiguated_data",
1usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
},})
})
}
}
#[automatically_derived]
impl ::rustc_serialize::Encodable for DefKey {
fn encode<__S: ::rustc_serialize::Encoder>(&self,
__arg_0: &mut __S)
-> ::std::result::Result<(), __S::Error> {
match *self {
DefKey {
parent: ref __self_0_0,
disambiguated_data: ref __self_0_1 } =>
__arg_0.emit_struct("DefKey", 2usize, |_e| -> _ {
match _e.emit_struct_field("parent",
0usize,
|_e| ->
_ {
(*__self_0_0).encode(_e)
}) {
::std::result::Result::Ok(__try_var)
=> __try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
};
return _e.emit_struct_field("disambiguated_data",
1usize,
|_e|
->
_
{
(*__self_0_1).encode(_e)
}); }),
}
}
}
#[automatically_derived]
impl ::std::hash::Hash for DefKey {
fn hash<__H: ::std::hash::Hasher>(&self, __arg_0: &mut __H)
-> () {
match *self {
DefKey {
parent: ref __self_0_0,
disambiguated_data: ref __self_0_1 } => {
::std::hash::Hash::hash(&(*__self_0_0), __arg_0);
::std::hash::Hash::hash(&(*__self_0_1), __arg_0);
}
}
}
}
#[automatically_derived]
impl ::std::cmp::Eq for DefKey {
#[inline]
#[doc(hidden)]
fn assert_receiver_is_total_eq(&self) -> () {
match *self {
DefKey {
parent: ref __self_0_0,
disambiguated_data: ref __self_0_1 } => {
(*__self_0_0).assert_receiver_is_total_eq();
(*__self_0_1).assert_receiver_is_total_eq();
}
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for DefKey {
#[inline]
fn eq(&self, __arg_0: &DefKey) -> bool {
match *__arg_0 {
DefKey {
parent: ref __self_1_0,
disambiguated_data: ref __self_1_1 } =>
match *self {
DefKey {
parent: ref __self_0_0,
disambiguated_data: ref __self_0_1 } =>
true && (*__self_0_0) == (*__self_1_0) &&
(*__self_0_1) == (*__self_1_1),
},
}
}
#[inline]
fn ne(&self, __arg_0: &DefKey) -> bool {
match *__arg_0 {
DefKey {
parent: ref __self_1_0,
disambiguated_data: ref __self_1_1 } =>
match *self {
DefKey {
parent: ref __self_0_0,
disambiguated_data: ref __self_0_1 } =>
false || (*__self_0_0) != (*__self_1_0) ||
(*__self_0_1) != (*__self_1_1),
},
}
}
}
#[automatically_derived]
impl ::std::fmt::Debug for DefKey {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match *self {
DefKey {
parent: ref __self_0_0,
disambiguated_data: ref __self_0_1 } =>
__arg_0.debug_struct("DefKey").field("parent",
&&(*__self_0_0)).field("disambiguated_data",
&&(*__self_0_1)).finish(),
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for DefKey {
#[inline]
fn clone(&self) -> DefKey {
match *self {
DefKey {
parent: ref __self_0_0,
disambiguated_data: ref __self_0_1 } =>
DefKey{parent:
::std::clone::Clone::clone(&(*__self_0_0)),
disambiguated_data:
::std::clone::Clone::clone(&(*__self_0_1)),},
}
}
}
/// Pair of `DefPathData` and an integer disambiguator. The integer is
/// normally 0, but in the event that there are multiple defs with the
/// same `parent` and `data`, we use this field to disambiguate
/// between them. This introduces some artificial ordering dependency
/// but means that if you have (e.g.) two impls for the same type in
/// the same module, they do get distinct def-ids.
pub struct DisambiguatedDefPathData {
pub data: DefPathData,
pub disambiguator: u32,
}
#[automatically_derived]
impl ::rustc_serialize::Decodable for DisambiguatedDefPathData {
fn decode<__D: ::rustc_serialize::Decoder>(__arg_0: &mut __D)
->
::std::result::Result<DisambiguatedDefPathData,
__D::Error> {
__arg_0.read_struct("DisambiguatedDefPathData", 2usize,
|_d| -> _ {
::std::result::Result::Ok(DisambiguatedDefPathData{data:
match _d.read_struct_field("data",
0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
},
disambiguator:
match _d.read_struct_field("disambiguator",
1usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
},})
})
}
}
#[automatically_derived]
impl ::rustc_serialize::Encodable for DisambiguatedDefPathData {
fn encode<__S: ::rustc_serialize::Encoder>(&self,
__arg_0: &mut __S)
-> ::std::result::Result<(), __S::Error> {
match *self {
DisambiguatedDefPathData {
data: ref __self_0_0, disambiguator: ref __self_0_1 }
=>
__arg_0.emit_struct("DisambiguatedDefPathData",
2usize, |_e| -> _ {
match _e.emit_struct_field("data",
0usize,
|_e| ->
_ {
(*__self_0_0).encode(_e)
}) {
::std::result::Result::Ok(__try_var)
=> __try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
};
return _e.emit_struct_field("disambiguator",
1usize,
|_e|
->
_
{
(*__self_0_1).encode(_e)
}); }),
}
}
}
#[automatically_derived]
impl ::std::hash::Hash for DisambiguatedDefPathData {
fn hash<__H: ::std::hash::Hasher>(&self, __arg_0: &mut __H)
-> () {
match *self {
DisambiguatedDefPathData {
data: ref __self_0_0, disambiguator: ref __self_0_1 }
=> {
::std::hash::Hash::hash(&(*__self_0_0), __arg_0);
::std::hash::Hash::hash(&(*__self_0_1), __arg_0);
}
}
}
}
#[automatically_derived]
impl ::std::cmp::Eq for DisambiguatedDefPathData {
#[inline]
#[doc(hidden)]
fn assert_receiver_is_total_eq(&self) -> () {
match *self {
DisambiguatedDefPathData {
data: ref __self_0_0, disambiguator: ref __self_0_1 }
=> {
(*__self_0_0).assert_receiver_is_total_eq();
(*__self_0_1).assert_receiver_is_total_eq();
}
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for DisambiguatedDefPathData {
#[inline]
fn eq(&self, __arg_0: &DisambiguatedDefPathData) -> bool {
match *__arg_0 {
DisambiguatedDefPathData {
data: ref __self_1_0, disambiguator: ref __self_1_1 }
=>
match *self {
DisambiguatedDefPathData {
data: ref __self_0_0,
disambiguator: ref __self_0_1 } =>
true && (*__self_0_0) == (*__self_1_0) &&
(*__self_0_1) == (*__self_1_1),
},
}
}
#[inline]
fn ne(&self, __arg_0: &DisambiguatedDefPathData) -> bool {
match *__arg_0 {
DisambiguatedDefPathData {
data: ref __self_1_0, disambiguator: ref __self_1_1 }
=>
match *self {
DisambiguatedDefPathData {
data: ref __self_0_0,
disambiguator: ref __self_0_1 } =>
false || (*__self_0_0) != (*__self_1_0) ||
(*__self_0_1) != (*__self_1_1),
},
}
}
}
#[automatically_derived]
impl ::std::fmt::Debug for DisambiguatedDefPathData {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match *self {
DisambiguatedDefPathData {
data: ref __self_0_0, disambiguator: ref __self_0_1 }
=>
__arg_0.debug_struct("DisambiguatedDefPathData").field("data",
&&(*__self_0_0)).field("disambiguator",
&&(*__self_0_1)).finish(),
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for DisambiguatedDefPathData {
#[inline]
fn clone(&self) -> DisambiguatedDefPathData {
match *self {
DisambiguatedDefPathData {
data: ref __self_0_0, disambiguator: ref __self_0_1 }
=>
DisambiguatedDefPathData{data:
::std::clone::Clone::clone(&(*__self_0_0)),
disambiguator:
::std::clone::Clone::clone(&(*__self_0_1)),},
}
}
}
/// For each definition, we track the following data. A definition
/// here is defined somewhat circularly as "something with a def-id",
/// but it generally corresponds to things like structs, enums, etc.
/// There are also some rather random cases (like const initializer
/// expressions) that are mostly just leftovers.
pub struct DefData {
pub key: DefKey,
/// Local ID within the HIR.
pub node_id: ast::NodeId,
}
#[automatically_derived]
impl ::std::fmt::Debug for DefData {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match *self {
DefData { key: ref __self_0_0, node_id: ref __self_0_1
} =>
__arg_0.debug_struct("DefData").field("key",
&&(*__self_0_0)).field("node_id",
&&(*__self_0_1)).finish(),
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for DefData {
#[inline]
fn clone(&self) -> DefData {
match *self {
DefData { key: ref __self_0_0, node_id: ref __self_0_1
} =>
DefData{key:
::std::clone::Clone::clone(&(*__self_0_0)),
node_id:
::std::clone::Clone::clone(&(*__self_0_1)),},
}
}
}
pub type DefPath = Vec<DisambiguatedDefPathData>;
pub enum DefPathData {
CrateRoot,
InlinedRoot(DefPath),
Misc,
Impl,
Type(ast::Name),
Mod(ast::Name),
Value(ast::Name),
MacroDef(ast::Name),
ClosureExpr,
TypeParam(ast::Name),
LifetimeDef(ast::Name),
EnumVariant(ast::Name),
PositionalField,
Field(hir::StructFieldKind),
StructCtor,
Initializer,
Binding(ast::Name),
DetachedCrate(ast::Name),
}
#[automatically_derived]
impl ::rustc_serialize::Decodable for DefPathData {
fn decode<__D: ::rustc_serialize::Decoder>(__arg_0: &mut __D)
-> ::std::result::Result<DefPathData, __D::Error> {
__arg_0.read_enum("DefPathData", |_d| -> _ {
_d.read_enum_variant(&["CrateRoot",
"InlinedRoot",
"Misc", "Impl",
"Type", "Mod",
"Value",
"MacroDef",
"ClosureExpr",
"TypeParam",
"LifetimeDef",
"EnumVariant",
"PositionalField",
"Field",
"StructCtor",
"Initializer",
"Binding",
"DetachedCrate"],
|_d, i| -> _ {
::std::result::Result::Ok(match i
{
0usize
=>
DefPathData::CrateRoot,
1usize
=>
DefPathData::InlinedRoot(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
2usize
=>
DefPathData::Misc,
3usize
=>
DefPathData::Impl,
4usize
=>
DefPathData::Type(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
5usize
=>
DefPathData::Mod(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
6usize
=>
DefPathData::Value(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
7usize
=>
DefPathData::MacroDef(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
8usize
=>
DefPathData::ClosureExpr,
9usize
=>
DefPathData::TypeParam(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
10usize
=>
DefPathData::LifetimeDef(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
11usize
=>
DefPathData::EnumVariant(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
12usize
=>
DefPathData::PositionalField,
13usize
=>
DefPathData::Field(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
14usize
=>
DefPathData::StructCtor,
15usize
=>
DefPathData::Initializer,
16usize
=>
DefPathData::Binding(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
17usize
=>
DefPathData::DetachedCrate(match _d.read_enum_variant_arg(0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
}),
_
=>
::std::rt::begin_unwind("internal error: entered unreachable code",
&("src/librustc/front/map/definitions.rs",
65u32)),
})
}) })
}
}
#[automatically_derived]
impl ::rustc_serialize::Encodable for DefPathData {
fn encode<__S: ::rustc_serialize::Encoder>(&self,
__arg_0: &mut __S)
-> ::std::result::Result<(), __S::Error> {
match (&*self,) {
(&DefPathData::CrateRoot,) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("CrateRoot",
0usize, 0usize,
|_e| -> _ {
return ::std::result::Result::Ok(());
}) })
}
(&DefPathData::InlinedRoot(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("InlinedRoot",
1usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::Misc,) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Misc", 2usize,
0usize,
|_e| -> _ {
return ::std::result::Result::Ok(());
}) })
}
(&DefPathData::Impl,) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Impl", 3usize,
0usize,
|_e| -> _ {
return ::std::result::Result::Ok(());
}) })
}
(&DefPathData::Type(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Type", 4usize,
1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::Mod(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Mod", 5usize,
1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::Value(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Value", 6usize,
1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::MacroDef(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("MacroDef",
7usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::ClosureExpr,) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("ClosureExpr",
8usize, 0usize,
|_e| -> _ {
return ::std::result::Result::Ok(());
}) })
}
(&DefPathData::TypeParam(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("TypeParam",
9usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::LifetimeDef(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("LifetimeDef",
10usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::EnumVariant(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("EnumVariant",
11usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::PositionalField,) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("PositionalField",
12usize, 0usize,
|_e| -> _ {
return ::std::result::Result::Ok(());
}) })
}
(&DefPathData::Field(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Field",
13usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::StructCtor,) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("StructCtor",
14usize, 0usize,
|_e| -> _ {
return ::std::result::Result::Ok(());
}) })
}
(&DefPathData::Initializer,) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Initializer",
15usize, 0usize,
|_e| -> _ {
return ::std::result::Result::Ok(());
}) })
}
(&DefPathData::Binding(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("Binding",
16usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
(&DefPathData::DetachedCrate(ref __self_0),) => {
let _e = __arg_0;
_e.emit_enum("DefPathData", |_e| -> _ {
_e.emit_enum_variant("DetachedCrate",
17usize, 1usize,
|_e| -> _ {
return _e.emit_enum_variant_arg(0usize,
|_e|
->
_
{
(*__self_0).encode(_e)
});
}) })
}
}
}
}
#[automatically_derived]
impl ::std::hash::Hash for DefPathData {
fn hash<__H: ::std::hash::Hasher>(&self, __arg_0: &mut __H)
-> () {
match (&*self,) {
(&DefPathData::CrateRoot,) => {
::std::hash::Hash::hash(&0usize, __arg_0);
}
(&DefPathData::InlinedRoot(ref __self_0),) => {
::std::hash::Hash::hash(&1usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::Misc,) => {
::std::hash::Hash::hash(&2usize, __arg_0);
}
(&DefPathData::Impl,) => {
::std::hash::Hash::hash(&3usize, __arg_0);
}
(&DefPathData::Type(ref __self_0),) => {
::std::hash::Hash::hash(&4usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::Mod(ref __self_0),) => {
::std::hash::Hash::hash(&5usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::Value(ref __self_0),) => {
::std::hash::Hash::hash(&6usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::MacroDef(ref __self_0),) => {
::std::hash::Hash::hash(&7usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::ClosureExpr,) => {
::std::hash::Hash::hash(&8usize, __arg_0);
}
(&DefPathData::TypeParam(ref __self_0),) => {
::std::hash::Hash::hash(&9usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::LifetimeDef(ref __self_0),) => {
::std::hash::Hash::hash(&10usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::EnumVariant(ref __self_0),) => {
::std::hash::Hash::hash(&11usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::PositionalField,) => {
::std::hash::Hash::hash(&12usize, __arg_0);
}
(&DefPathData::Field(ref __self_0),) => {
::std::hash::Hash::hash(&13usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::StructCtor,) => {
::std::hash::Hash::hash(&14usize, __arg_0);
}
(&DefPathData::Initializer,) => {
::std::hash::Hash::hash(&15usize, __arg_0);
}
(&DefPathData::Binding(ref __self_0),) => {
::std::hash::Hash::hash(&16usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
(&DefPathData::DetachedCrate(ref __self_0),) => {
::std::hash::Hash::hash(&17usize, __arg_0);
::std::hash::Hash::hash(&(*__self_0), __arg_0);
}
}
}
}
#[automatically_derived]
impl ::std::cmp::Eq for DefPathData {
#[inline]
#[doc(hidden)]
fn assert_receiver_is_total_eq(&self) -> () {
match (&*self,) {
(&DefPathData::CrateRoot,) => { }
(&DefPathData::InlinedRoot(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::Misc,) => { }
(&DefPathData::Impl,) => { }
(&DefPathData::Type(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::Mod(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::Value(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::MacroDef(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::ClosureExpr,) => { }
(&DefPathData::TypeParam(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::LifetimeDef(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::EnumVariant(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::PositionalField,) => { }
(&DefPathData::Field(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::StructCtor,) => { }
(&DefPathData::Initializer,) => { }
(&DefPathData::Binding(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
(&DefPathData::DetachedCrate(ref __self_0),) => {
(*__self_0).assert_receiver_is_total_eq();
}
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for DefPathData {
#[inline]
fn eq(&self, __arg_0: &DefPathData) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&DefPathData::CrateRoot,
&DefPathData::CrateRoot) => true,
(&DefPathData::InlinedRoot(ref __self_0),
&DefPathData::InlinedRoot(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::Misc, &DefPathData::Misc) =>
true,
(&DefPathData::Impl, &DefPathData::Impl) =>
true,
(&DefPathData::Type(ref __self_0),
&DefPathData::Type(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::Mod(ref __self_0),
&DefPathData::Mod(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::Value(ref __self_0),
&DefPathData::Value(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::MacroDef(ref __self_0),
&DefPathData::MacroDef(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::ClosureExpr,
&DefPathData::ClosureExpr) => true,
(&DefPathData::TypeParam(ref __self_0),
&DefPathData::TypeParam(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::LifetimeDef(ref __self_0),
&DefPathData::LifetimeDef(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::EnumVariant(ref __self_0),
&DefPathData::EnumVariant(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::PositionalField,
&DefPathData::PositionalField) => true,
(&DefPathData::Field(ref __self_0),
&DefPathData::Field(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::StructCtor,
&DefPathData::StructCtor) => true,
(&DefPathData::Initializer,
&DefPathData::Initializer) => true,
(&DefPathData::Binding(ref __self_0),
&DefPathData::Binding(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&DefPathData::DetachedCrate(ref __self_0),
&DefPathData::DetachedCrate(ref __arg_1_0))
=> true && (*__self_0) == (*__arg_1_0),
_ => unsafe {
::std::intrinsics::unreachable()
}
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &DefPathData) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&DefPathData::CrateRoot,
&DefPathData::CrateRoot) => false,
(&DefPathData::InlinedRoot(ref __self_0),
&DefPathData::InlinedRoot(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::Misc, &DefPathData::Misc) =>
false,
(&DefPathData::Impl, &DefPathData::Impl) =>
false,
(&DefPathData::Type(ref __self_0),
&DefPathData::Type(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::Mod(ref __self_0),
&DefPathData::Mod(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::Value(ref __self_0),
&DefPathData::Value(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::MacroDef(ref __self_0),
&DefPathData::MacroDef(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::ClosureExpr,
&DefPathData::ClosureExpr) => false,
(&DefPathData::TypeParam(ref __self_0),
&DefPathData::TypeParam(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::LifetimeDef(ref __self_0),
&DefPathData::LifetimeDef(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::EnumVariant(ref __self_0),
&DefPathData::EnumVariant(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::PositionalField,
&DefPathData::PositionalField) => false,
(&DefPathData::Field(ref __self_0),
&DefPathData::Field(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::StructCtor,
&DefPathData::StructCtor) => false,
(&DefPathData::Initializer,
&DefPathData::Initializer) => false,
(&DefPathData::Binding(ref __self_0),
&DefPathData::Binding(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&DefPathData::DetachedCrate(ref __self_0),
&DefPathData::DetachedCrate(ref __arg_1_0))
=> false || (*__self_0) != (*__arg_1_0),
_ => unsafe {
::std::intrinsics::unreachable()
}
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::fmt::Debug for DefPathData {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&DefPathData::CrateRoot,) =>
__arg_0.debug_tuple("CrateRoot").finish(),
(&DefPathData::InlinedRoot(ref __self_0),) =>
__arg_0.debug_tuple("InlinedRoot").field(&&(*__self_0)).finish(),
(&DefPathData::Misc,) =>
__arg_0.debug_tuple("Misc").finish(),
(&DefPathData::Impl,) =>
__arg_0.debug_tuple("Impl").finish(),
(&DefPathData::Type(ref __self_0),) =>
__arg_0.debug_tuple("Type").field(&&(*__self_0)).finish(),
(&DefPathData::Mod(ref __self_0),) =>
__arg_0.debug_tuple("Mod").field(&&(*__self_0)).finish(),
(&DefPathData::Value(ref __self_0),) =>
__arg_0.debug_tuple("Value").field(&&(*__self_0)).finish(),
(&DefPathData::MacroDef(ref __self_0),) =>
__arg_0.debug_tuple("MacroDef").field(&&(*__self_0)).finish(),
(&DefPathData::ClosureExpr,) =>
__arg_0.debug_tuple("ClosureExpr").finish(),
(&DefPathData::TypeParam(ref __self_0),) =>
__arg_0.debug_tuple("TypeParam").field(&&(*__self_0)).finish(),
(&DefPathData::LifetimeDef(ref __self_0),) =>
__arg_0.debug_tuple("LifetimeDef").field(&&(*__self_0)).finish(),
(&DefPathData::EnumVariant(ref __self_0),) =>
__arg_0.debug_tuple("EnumVariant").field(&&(*__self_0)).finish(),
(&DefPathData::PositionalField,) =>
__arg_0.debug_tuple("PositionalField").finish(),
(&DefPathData::Field(ref __self_0),) =>
__arg_0.debug_tuple("Field").field(&&(*__self_0)).finish(),
(&DefPathData::StructCtor,) =>
__arg_0.debug_tuple("StructCtor").finish(),
(&DefPathData::Initializer,) =>
__arg_0.debug_tuple("Initializer").finish(),
(&DefPathData::Binding(ref __self_0),) =>
__arg_0.debug_tuple("Binding").field(&&(*__self_0)).finish(),
(&DefPathData::DetachedCrate(ref __self_0),) =>
__arg_0.debug_tuple("DetachedCrate").field(&&(*__self_0)).finish(),
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for DefPathData {
#[inline]
fn clone(&self) -> DefPathData {
match (&*self,) {
(&DefPathData::CrateRoot,) => DefPathData::CrateRoot,
(&DefPathData::InlinedRoot(ref __self_0),) =>
DefPathData::InlinedRoot(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::Misc,) => DefPathData::Misc,
(&DefPathData::Impl,) => DefPathData::Impl,
(&DefPathData::Type(ref __self_0),) =>
DefPathData::Type(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::Mod(ref __self_0),) =>
DefPathData::Mod(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::Value(ref __self_0),) =>
DefPathData::Value(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::MacroDef(ref __self_0),) =>
DefPathData::MacroDef(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::ClosureExpr,) =>
DefPathData::ClosureExpr,
(&DefPathData::TypeParam(ref __self_0),) =>
DefPathData::TypeParam(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::LifetimeDef(ref __self_0),) =>
DefPathData::LifetimeDef(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::EnumVariant(ref __self_0),) =>
DefPathData::EnumVariant(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::PositionalField,) =>
DefPathData::PositionalField,
(&DefPathData::Field(ref __self_0),) =>
DefPathData::Field(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::StructCtor,) =>
DefPathData::StructCtor,
(&DefPathData::Initializer,) =>
DefPathData::Initializer,
(&DefPathData::Binding(ref __self_0),) =>
DefPathData::Binding(::std::clone::Clone::clone(&(*__self_0))),
(&DefPathData::DetachedCrate(ref __self_0),) =>
DefPathData::DetachedCrate(::std::clone::Clone::clone(&(*__self_0))),
}
}
}
impl Definitions {
pub fn new() -> Definitions {
Definitions{data:
<[_]>::into_vec(::std::boxed::Box::new([])),
key_map: FnvHashMap(),
node_map: NodeMap(),}
}
pub fn len(&self) -> usize { self.data.len() }
pub fn def_key(&self, index: DefIndex) -> DefKey {
self.data[index.as_usize()].key.clone()
}
/// Returns the path from the crate root to `index`. The root
/// nodes are not included in the path (i.e., this will be an
/// empty vector for the crate root). For an inlined item, this
/// will be the path of the item in the external crate (but the
/// path will begin with the path to the external crate).
pub fn def_path(&self, index: DefIndex) -> DefPath {
make_def_path(index, |p| self.def_key(p))
}
pub fn opt_def_index(&self, node: ast::NodeId)
-> Option<DefIndex> {
self.node_map.get(&node).cloned()
}
pub fn opt_local_def_id(&self, node: ast::NodeId)
-> Option<DefId> {
self.opt_def_index(node).map(DefId::local)
}
pub fn as_local_node_id(&self, def_id: DefId)
-> Option<ast::NodeId> {
if def_id.krate == LOCAL_CRATE {
if !(def_id.index.as_usize() < self.data.len()) {
{
::std::rt::begin_unwind("assertion failed: def_id.index.as_usize() < self.data.len()",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/definitions.rs",
134u32);
&_FILE_LINE
})
}
};
Some(self.data[def_id.index.as_usize()].node_id)
} else { None }
}
pub fn create_def_with_parent(&mut self,
parent: Option<DefIndex>,
node_id: ast::NodeId,
data: DefPathData) -> DefIndex {
if !!self.node_map.contains_key(&node_id) {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["adding a def\'n for node-id ",
" and data ",
" but a previous def\'n exists: "];
__STATIC_FMTSTR
},
&match (&node_id,
&data,
&self.data[self.node_map[&node_id].as_usize()])
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/definitions.rs",
146u32);
&_FILE_LINE
})
}
};
let mut key =
DefKey{parent: parent,
disambiguated_data:
DisambiguatedDefPathData{data: data,
disambiguator:
0,},};
while self.key_map.contains_key(&key) {
key.disambiguated_data.disambiguator += 1;
}
let index = DefIndex::new(self.data.len());
self.data.push(DefData{key: key.clone(),
node_id: node_id,});
self.node_map.insert(node_id, index);
self.key_map.insert(key, index);
index
}
}
impl DefPathData {
pub fn as_interned_str(&self) -> InternedString {
use self::DefPathData::*;
match *self {
Type(name) | Mod(name) | Value(name) | MacroDef(name)
| TypeParam(name) | LifetimeDef(name) |
EnumVariant(name) | DetachedCrate(name) |
Binding(name) => {
name.as_str()
}
Field(hir::StructFieldKind::NamedField(name, _)) => {
name.as_str()
}
PositionalField |
Field(hir::StructFieldKind::UnnamedField(_)) => {
InternedString::new("<field>")
}
CrateRoot => { InternedString::new("<root>") }
InlinedRoot(_) => {
InternedString::new("<inlined-root>")
}
Misc => { InternedString::new("?") }
Impl => { InternedString::new("<impl>") }
ClosureExpr => { InternedString::new("<closure>") }
StructCtor => { InternedString::new("<constructor>") }
Initializer => {
InternedString::new("<initializer>")
}
}
}
pub fn to_string(&self) -> String {
self.as_interned_str().to_string()
}
}
pub fn make_def_path<FN>(start_index: DefIndex, mut get_key: FN)
-> DefPath where FN: FnMut(DefIndex) -> DefKey {
let mut result = <[_]>::into_vec(::std::boxed::Box::new([]));
let mut index = Some(start_index);
loop {
match index {
Some(p) => {
let key = get_key(p);
match key.disambiguated_data.data {
DefPathData::CrateRoot => {
if !key.parent.is_none() {
{
::std::rt::begin_unwind("assertion failed: key.parent.is_none()",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/front/map/definitions.rs",
247u32);
&_FILE_LINE
})
}
};
break ;
}
DefPathData::InlinedRoot(ref p) => {
if !key.parent.is_none() {
{
::std::rt::begin_unwind("assertion failed: key.parent.is_none()",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/front/map/definitions.rs",
251u32);
&_FILE_LINE
})
}
};
result.extend(p.iter().cloned().rev());
break ;
}
_ => {
result.push(key.disambiguated_data);
index = key.parent;
}
}
}
_ => break ,
}
}
result.reverse();
result
}
}
pub enum PathElem { PathMod(Name), PathName(Name), }
#[automatically_derived]
impl ::std::fmt::Debug for PathElem {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&PathElem::PathMod(ref __self_0),) =>
__arg_0.debug_tuple("PathMod").field(&&(*__self_0)).finish(),
(&PathElem::PathName(ref __self_0),) =>
__arg_0.debug_tuple("PathName").field(&&(*__self_0)).finish(),
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for PathElem {
#[inline]
fn eq(&self, __arg_0: &PathElem) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&PathElem::PathMod(ref __self_0),
&PathElem::PathMod(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&PathElem::PathName(ref __self_0),
&PathElem::PathName(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &PathElem) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&PathElem::PathMod(ref __self_0),
&PathElem::PathMod(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&PathElem::PathName(ref __self_0),
&PathElem::PathName(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for PathElem { }
#[automatically_derived]
impl ::std::clone::Clone for PathElem {
#[inline]
fn clone(&self) -> PathElem {
match (&*self,) {
(&PathElem::PathMod(ref __self_0),) =>
PathElem::PathMod(::std::clone::Clone::clone(&(*__self_0))),
(&PathElem::PathName(ref __self_0),) =>
PathElem::PathName(::std::clone::Clone::clone(&(*__self_0))),
}
}
}
impl PathElem {
pub fn name(&self) -> Name {
match *self { PathMod(name) | PathName(name) => name, }
}
}
impl fmt::Display for PathElem {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[""];
__STATIC_FMTSTR
},
&match (&self.name(),)
{
(__arg0,) =>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}))
}
}
pub struct LinkedPathNode<'a> {
node: PathElem,
next: LinkedPath<'a>,
}
#[automatically_derived]
impl <'a> ::std::clone::Clone for LinkedPathNode<'a> {
#[inline]
fn clone(&self) -> LinkedPathNode<'a> {
match *self {
LinkedPathNode {
node: ref __self_0_0, next: ref __self_0_1 } =>
LinkedPathNode{node:
::std::clone::Clone::clone(&(*__self_0_0)),
next:
::std::clone::Clone::clone(&(*__self_0_1)),},
}
}
}
pub struct LinkedPath<'a>(Option<&'a LinkedPathNode<'a>>);
#[automatically_derived]
impl <'a> ::std::clone::Clone for LinkedPath<'a> {
#[inline]
fn clone(&self) -> LinkedPath<'a> {
match *self {
LinkedPath(ref __self_0_0) =>
LinkedPath(::std::clone::Clone::clone(&(*__self_0_0))),
}
}
}
#[automatically_derived]
impl <'a> ::std::marker::Copy for LinkedPath<'a> { }
impl <'a> LinkedPath<'a> {
pub fn empty() -> LinkedPath<'a> { LinkedPath(None) }
pub fn from(node: &'a LinkedPathNode) -> LinkedPath<'a> {
LinkedPath(Some(node))
}
}
impl <'a> Iterator for LinkedPath<'a> {
type
Item
=
PathElem;
fn next(&mut self) -> Option<PathElem> {
match self.0 {
Some(node) => { *self = node.next; Some(node.node) }
None => None,
}
}
}
/// The type of the iterator used by with_path.
pub type PathElems<'a, 'b> =
iter::Chain<iter::Cloned<slice::Iter<'a, PathElem>>,
LinkedPath<'b>>;
pub fn path_to_string<PI: Iterator<Item = PathElem>>(path: PI)
-> String {
let itr = token::get_ident_interner();
path.fold(String::new(), |mut s, e| { let e = itr.get(e.name());
if !s.is_empty() { s.push_str("::"); }
s.push_str(&e[..]); s })
}
pub enum Node<'ast> {
NodeItem(&'ast Item),
NodeForeignItem(&'ast ForeignItem),
NodeTraitItem(&'ast TraitItem),
NodeImplItem(&'ast ImplItem),
NodeVariant(&'ast Variant),
NodeExpr(&'ast Expr),
NodeStmt(&'ast Stmt),
NodeLocal(&'ast Pat),
NodePat(&'ast Pat),
NodeBlock(&'ast Block),
/// NodeStructCtor represents a tuple struct.
NodeStructCtor(&'ast VariantData),
NodeLifetime(&'ast Lifetime),
NodeTyParam(&'ast TyParam),
}
#[automatically_derived]
impl <'ast> ::std::fmt::Debug for Node<'ast> {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&Node::NodeItem(ref __self_0),) =>
__arg_0.debug_tuple("NodeItem").field(&&(*__self_0)).finish(),
(&Node::NodeForeignItem(ref __self_0),) =>
__arg_0.debug_tuple("NodeForeignItem").field(&&(*__self_0)).finish(),
(&Node::NodeTraitItem(ref __self_0),) =>
__arg_0.debug_tuple("NodeTraitItem").field(&&(*__self_0)).finish(),
(&Node::NodeImplItem(ref __self_0),) =>
__arg_0.debug_tuple("NodeImplItem").field(&&(*__self_0)).finish(),
(&Node::NodeVariant(ref __self_0),) =>
__arg_0.debug_tuple("NodeVariant").field(&&(*__self_0)).finish(),
(&Node::NodeExpr(ref __self_0),) =>
__arg_0.debug_tuple("NodeExpr").field(&&(*__self_0)).finish(),
(&Node::NodeStmt(ref __self_0),) =>
__arg_0.debug_tuple("NodeStmt").field(&&(*__self_0)).finish(),
(&Node::NodeLocal(ref __self_0),) =>
__arg_0.debug_tuple("NodeLocal").field(&&(*__self_0)).finish(),
(&Node::NodePat(ref __self_0),) =>
__arg_0.debug_tuple("NodePat").field(&&(*__self_0)).finish(),
(&Node::NodeBlock(ref __self_0),) =>
__arg_0.debug_tuple("NodeBlock").field(&&(*__self_0)).finish(),
(&Node::NodeStructCtor(ref __self_0),) =>
__arg_0.debug_tuple("NodeStructCtor").field(&&(*__self_0)).finish(),
(&Node::NodeLifetime(ref __self_0),) =>
__arg_0.debug_tuple("NodeLifetime").field(&&(*__self_0)).finish(),
(&Node::NodeTyParam(ref __self_0),) =>
__arg_0.debug_tuple("NodeTyParam").field(&&(*__self_0)).finish(),
}
}
}
#[automatically_derived]
impl <'ast> ::std::clone::Clone for Node<'ast> {
#[inline]
fn clone(&self) -> Node<'ast> {
match (&*self,) {
(&Node::NodeItem(ref __self_0),) =>
Node::NodeItem(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeForeignItem(ref __self_0),) =>
Node::NodeForeignItem(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeTraitItem(ref __self_0),) =>
Node::NodeTraitItem(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeImplItem(ref __self_0),) =>
Node::NodeImplItem(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeVariant(ref __self_0),) =>
Node::NodeVariant(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeExpr(ref __self_0),) =>
Node::NodeExpr(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeStmt(ref __self_0),) =>
Node::NodeStmt(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeLocal(ref __self_0),) =>
Node::NodeLocal(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodePat(ref __self_0),) =>
Node::NodePat(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeBlock(ref __self_0),) =>
Node::NodeBlock(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeStructCtor(ref __self_0),) =>
Node::NodeStructCtor(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeLifetime(ref __self_0),) =>
Node::NodeLifetime(::std::clone::Clone::clone(&(*__self_0))),
(&Node::NodeTyParam(ref __self_0),) =>
Node::NodeTyParam(::std::clone::Clone::clone(&(*__self_0))),
}
}
}
#[automatically_derived]
impl <'ast> ::std::marker::Copy for Node<'ast> { }
/// Represents an entry and its parent NodeID.
/// The odd layout is to bring down the total size.
pub enum MapEntry<'ast> {
/// Placeholder for holes in the map.
NotPresent,
/// All the node types, with a parent ID.
EntryItem(NodeId, &'ast Item),
EntryForeignItem(NodeId, &'ast ForeignItem),
EntryTraitItem(NodeId, &'ast TraitItem),
EntryImplItem(NodeId, &'ast ImplItem),
EntryVariant(NodeId, &'ast Variant),
EntryExpr(NodeId, &'ast Expr),
EntryStmt(NodeId, &'ast Stmt),
EntryLocal(NodeId, &'ast Pat),
EntryPat(NodeId, &'ast Pat),
EntryBlock(NodeId, &'ast Block),
EntryStructCtor(NodeId, &'ast VariantData),
EntryLifetime(NodeId, &'ast Lifetime),
EntryTyParam(NodeId, &'ast TyParam),
/// Roots for node trees.
RootCrate,
RootInlinedParent(&'ast InlinedParent),
}
#[automatically_derived]
impl <'ast> ::std::fmt::Debug for MapEntry<'ast> {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&MapEntry::NotPresent,) =>
__arg_0.debug_tuple("NotPresent").finish(),
(&MapEntry::EntryItem(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryItem").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryForeignItem(ref __self_0, ref __self_1),)
=>
__arg_0.debug_tuple("EntryForeignItem").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryTraitItem(ref __self_0, ref __self_1),)
=>
__arg_0.debug_tuple("EntryTraitItem").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryImplItem(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryImplItem").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryVariant(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryVariant").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryExpr(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryExpr").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryStmt(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryStmt").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryLocal(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryLocal").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryPat(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryPat").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryBlock(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryBlock").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryStructCtor(ref __self_0, ref __self_1),)
=>
__arg_0.debug_tuple("EntryStructCtor").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryLifetime(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryLifetime").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::EntryTyParam(ref __self_0, ref __self_1),) =>
__arg_0.debug_tuple("EntryTyParam").field(&&(*__self_0)).field(&&(*__self_1)).finish(),
(&MapEntry::RootCrate,) =>
__arg_0.debug_tuple("RootCrate").finish(),
(&MapEntry::RootInlinedParent(ref __self_0),) =>
__arg_0.debug_tuple("RootInlinedParent").field(&&(*__self_0)).finish(),
}
}
}
#[automatically_derived]
impl <'ast> ::std::marker::Copy for MapEntry<'ast> { }
impl <'ast> Clone for MapEntry<'ast> {
fn clone(&self) -> MapEntry<'ast> { *self }
}
pub struct InlinedParent {
path: Vec<PathElem>,
ii: InlinedItem,
}
#[automatically_derived]
impl ::std::fmt::Debug for InlinedParent {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match *self {
InlinedParent { path: ref __self_0_0, ii: ref __self_0_1 }
=>
__arg_0.debug_struct("InlinedParent").field("path",
&&(*__self_0_0)).field("ii",
&&(*__self_0_1)).finish(),
}
}
}
impl <'ast> MapEntry<'ast> {
fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
match node {
NodeItem(n) => EntryItem(p, n),
NodeForeignItem(n) => EntryForeignItem(p, n),
NodeTraitItem(n) => EntryTraitItem(p, n),
NodeImplItem(n) => EntryImplItem(p, n),
NodeVariant(n) => EntryVariant(p, n),
NodeExpr(n) => EntryExpr(p, n),
NodeStmt(n) => EntryStmt(p, n),
NodeLocal(n) => EntryLocal(p, n),
NodePat(n) => EntryPat(p, n),
NodeBlock(n) => EntryBlock(p, n),
NodeStructCtor(n) => EntryStructCtor(p, n),
NodeLifetime(n) => EntryLifetime(p, n),
NodeTyParam(n) => EntryTyParam(p, n),
}
}
fn parent_node(self) -> Option<NodeId> {
Some(match self {
EntryItem(id, _) => id,
EntryForeignItem(id, _) => id,
EntryTraitItem(id, _) => id,
EntryImplItem(id, _) => id,
EntryVariant(id, _) => id,
EntryExpr(id, _) => id,
EntryStmt(id, _) => id,
EntryLocal(id, _) => id,
EntryPat(id, _) => id,
EntryBlock(id, _) => id,
EntryStructCtor(id, _) => id,
EntryLifetime(id, _) => id,
EntryTyParam(id, _) => id,
_ => return None,
})
}
fn to_node(self) -> Option<Node<'ast>> {
Some(match self {
EntryItem(_, n) => NodeItem(n),
EntryForeignItem(_, n) => NodeForeignItem(n),
EntryTraitItem(_, n) => NodeTraitItem(n),
EntryImplItem(_, n) => NodeImplItem(n),
EntryVariant(_, n) => NodeVariant(n),
EntryExpr(_, n) => NodeExpr(n),
EntryStmt(_, n) => NodeStmt(n),
EntryLocal(_, n) => NodeLocal(n),
EntryPat(_, n) => NodePat(n),
EntryBlock(_, n) => NodeBlock(n),
EntryStructCtor(_, n) => NodeStructCtor(n),
EntryLifetime(_, n) => NodeLifetime(n),
EntryTyParam(_, n) => NodeTyParam(n),
_ => return None,
})
}
}
/// Stores a crate and any number of inlined items from other crates.
pub struct Forest {
pub krate: Crate,
inlined_items: TypedArena<InlinedParent>,
}
impl Forest {
pub fn new(krate: Crate) -> Forest {
Forest{krate: krate, inlined_items: TypedArena::new(),}
}
pub fn krate<'ast>(&'ast self) -> &'ast Crate { &self.krate }
}
/// Represents a mapping from Node IDs to AST elements and their parent
/// Node IDs
pub struct Map<'ast> {
/// The backing storage for all the AST nodes.
pub forest: &'ast Forest,
/// NodeIds are sequential integers from 0, so we can be
/// super-compact by storing them in a vector. Not everything with
/// a NodeId is in the map, but empirically the occupancy is about
/// 75-80%, so there's not too much overhead (certainly less than
/// a hashmap, since they (at the time of writing) have a maximum
/// of 75% occupancy).
///
/// Also, indexing is pretty quick when you've got a vector and
/// plain old integers.
map: RefCell<Vec<MapEntry<'ast>>>,
definitions: RefCell<Definitions>,
}
#[automatically_derived]
impl <'ast> ::std::clone::Clone for Map<'ast> {
#[inline]
fn clone(&self) -> Map<'ast> {
match *self {
Map {
forest: ref __self_0_0,
map: ref __self_0_1,
definitions: ref __self_0_2 } =>
Map{forest: ::std::clone::Clone::clone(&(*__self_0_0)),
map: ::std::clone::Clone::clone(&(*__self_0_1)),
definitions:
::std::clone::Clone::clone(&(*__self_0_2)),},
}
}
}
impl <'ast> Map<'ast> {
pub fn num_local_def_ids(&self) -> usize {
self.definitions.borrow().len()
}
pub fn def_key(&self, def_id: DefId) -> DefKey {
if !def_id.is_local() {
{
::std::rt::begin_unwind("assertion failed: def_id.is_local()",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/front/map/mod.rs",
275u32);
&_FILE_LINE
})
}
};
self.definitions.borrow().def_key(def_id.index)
}
pub fn def_path_from_id(&self, id: NodeId) -> DefPath {
self.def_path(self.local_def_id(id))
}
pub fn def_path(&self, def_id: DefId) -> DefPath {
if !def_id.is_local() {
{
::std::rt::begin_unwind("assertion failed: def_id.is_local()",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/front/map/mod.rs",
284u32);
&_FILE_LINE
})
}
};
self.definitions.borrow().def_path(def_id.index)
}
pub fn local_def_id(&self, node: NodeId) -> DefId {
self.opt_local_def_id(node).unwrap_or_else(|| {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["local_def_id: no entry for `",
"`, which has a map of `",
"`"];
__STATIC_FMTSTR
},
&match (&node,
&self.find_entry(node))
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/front/map/mod.rs",
290u32);
&_FILE_LINE
})
} })
}
pub fn opt_local_def_id(&self, node: NodeId) -> Option<DefId> {
self.definitions.borrow().opt_local_def_id(node)
}
pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
self.definitions.borrow().as_local_node_id(def_id)
}
fn entry_count(&self) -> usize { self.map.borrow().len() }
fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
self.map.borrow().get(id as usize).cloned()
}
pub fn krate(&self) -> &'ast Crate { &self.forest.krate }
/// Retrieve the Node corresponding to `id`, panicking if it cannot
/// be found.
pub fn get(&self, id: NodeId) -> Node<'ast> {
match self.find(id) {
Some(node) => node,
None => {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["couldn\'t find node id ",
" in the AST map"];
__STATIC_FMTSTR
},
&match (&id,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
320u32);
&_FILE_LINE
})
}
}
}
pub fn get_if_local(&self, id: DefId) -> Option<Node<'ast>> {
self.as_local_node_id(id).map(|id| self.get(id))
}
/// Retrieve the Node corresponding to `id`, returning None if
/// cannot be found.
pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
self.find_entry(id).and_then(|x| x.to_node())
}
/// Similar to get_parent, returns the parent node id or id if there is no
/// parent.
/// This function returns the immediate parent in the AST, whereas get_parent
/// returns the enclosing item. Note that this might not be the actual parent
/// node in the AST - some kinds of nodes are not in the map and these will
/// never appear as the parent_node. So you can always walk the parent_nodes
/// from a node to the root of the ast (unless you get the same id back here
/// that can happen if the id is not in the map itself or is just weird).
pub fn get_parent_node(&self, id: NodeId) -> NodeId {
self.find_entry(id).and_then(|x|
x.parent_node()).unwrap_or(id)
}
/// Check if the node is an argument. An argument is a local variable whose
/// immediate parent is an item or a closure.
pub fn is_argument(&self, id: NodeId) -> bool {
match self.find(id) {
Some(NodeLocal(_)) => (),
_ => return false,
}
match self.find(self.get_parent_node(id)) {
Some(NodeItem(_)) | Some(NodeTraitItem(_)) |
Some(NodeImplItem(_)) => true,
Some(NodeExpr(e)) => {
match e.node { ExprClosure(..) => true, _ => false, }
}
_ => false,
}
}
/// If there is some error when walking the parents (e.g., a node does not
/// have a parent in the map or a node can't be found), then we return the
/// last good node id we found. Note that reaching the crate root (id == 0),
/// is not an error, since items in the crate module have the crate root as
/// parent.
fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F)
-> Result<NodeId, NodeId> where F: Fn(&Node<'ast>) -> bool {
let mut id = start_id;
loop {
let parent_node = self.get_parent_node(id);
if parent_node == 0 { return Ok(0); }
if parent_node == id { return Err(id); }
let node = self.find_entry(parent_node);
if node.is_none() { return Err(id); }
let node = node.unwrap().to_node();
match node {
Some(ref node) => {
if found(node) { return Ok(parent_node); }
}
None => { return Err(parent_node); }
}
id = parent_node;
}
}
/// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
/// parent item is in this map. The "parent item" is the closest parent node
/// in the AST which is recorded by the map and is an item, either an item
/// in a module, trait, or impl.
pub fn get_parent(&self, id: NodeId) -> NodeId {
match self.walk_parent_nodes(id,
|node|
match *node {
NodeItem(_) |
NodeForeignItem(_) |
NodeTraitItem(_) |
NodeImplItem(_) => true,
_ => false,
}) {
Ok(id) => id,
Err(id) => id,
}
}
/// Returns the nearest enclosing scope. A scope is an item or block.
/// FIXME it is not clear to me that all items qualify as scopes - statics
/// and associated types probably shouldn't, for example. Behaviour in this
/// regard should be expected to be highly unstable.
pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
match self.walk_parent_nodes(id,
|node|
match *node {
NodeItem(_) |
NodeForeignItem(_) |
NodeTraitItem(_) |
NodeImplItem(_) |
NodeBlock(_) => true,
_ => false,
}) {
Ok(id) => Some(id),
Err(_) => None,
}
}
pub fn get_parent_did(&self, id: NodeId) -> DefId {
let parent = self.get_parent(id);
match self.find_entry(parent) {
Some(RootInlinedParent(&InlinedParent {
ii: II::TraitItem(did, _), .. }))
=> did,
Some(RootInlinedParent(&InlinedParent {
ii: II::ImplItem(did, _), .. })) =>
did,
_ => self.local_def_id(parent),
}
}
pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi {
let parent = self.get_parent(id);
let abi =
match self.find_entry(parent) {
Some(EntryItem(_, i)) => {
match i.node {
ItemForeignMod(ref nm) => Some(nm.abi),
_ => None,
}
}
/// Wrong but OK, because the only inlined foreign items are intrinsics.
Some(RootInlinedParent(_)) =>
Some(abi::RustIntrinsic),
_ => None,
};
match abi {
Some(abi) => abi,
None => {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected foreign mod or inlined parent, found "];
__STATIC_FMTSTR
},
&match (&self.node_to_string(parent),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
463u32);
&_FILE_LINE
})
}
}
}
pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
let vis = self.expect_foreign_item(id).vis;
match self.find(self.get_parent(id)) {
Some(NodeItem(i)) => vis.inherit_from(i.vis),
_ => vis,
}
}
pub fn expect_item(&self, id: NodeId) -> &'ast Item {
match self.find(id) {
Some(NodeItem(item)) => item,
_ => {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected item, found "];
__STATIC_FMTSTR
},
&match (&self.node_to_string(id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
479u32);
&_FILE_LINE
})
}
}
}
pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem {
match self.find(id) {
Some(NodeTraitItem(item)) => item,
_ => {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected trait item, found "];
__STATIC_FMTSTR
},
&match (&self.node_to_string(id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
486u32);
&_FILE_LINE
})
}
}
}
pub fn expect_struct(&self, id: NodeId) -> &'ast VariantData {
match self.find(id) {
Some(NodeItem(i)) => {
match i.node {
ItemStruct(ref struct_def, _) => struct_def,
_ => {
::std::rt::begin_unwind("struct ID bound to non-struct",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
495u32);
&_FILE_LINE
})
}
}
}
Some(NodeVariant(variant)) => {
if variant.node.data.is_struct() {
&variant.node.data
} else {
{
::std::rt::begin_unwind("struct ID bound to enum variant that isn\'t struct-like",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
502u32);
&_FILE_LINE
})
}
}
}
_ => {
::std::rt::begin_unwind(::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected struct, found "];
__STATIC_FMTSTR
},
&match (&self.node_to_string(id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/front/map/mod.rs",
505u32);
&_FILE_LINE
})
}
}
}
pub fn expect_variant(&self, id: NodeId) -> &'ast Variant {
match self.find(id) {
Some(NodeVariant(variant)) => variant,
_ => {
::std::rt::begin_unwind(::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected variant, found "];
__STATIC_FMTSTR
},
&match (&self.node_to_string(id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/front/map/mod.rs",
512u32);
&_FILE_LINE
})
}
}
}
pub fn expect_foreign_item(&self, id: NodeId)
-> &'ast ForeignItem {
match self.find(id) {
Some(NodeForeignItem(item)) => item,
_ => {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected foreign item, found "];
__STATIC_FMTSTR
},
&match (&self.node_to_string(id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
519u32);
&_FILE_LINE
})
}
}
}
pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
match self.find(id) {
Some(NodeExpr(expr)) => expr,
_ => {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected expr, found "];
__STATIC_FMTSTR
},
&match (&self.node_to_string(id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
526u32);
&_FILE_LINE
})
}
}
}
/// returns the name associated with the given NodeId's AST
pub fn get_path_elem(&self, id: NodeId) -> PathElem {
let node = self.get(id);
match node {
NodeItem(item) => {
match item.node {
ItemMod(_) | ItemForeignMod(_) => {
PathMod(item.name)
}
_ => PathName(item.name),
}
}
NodeForeignItem(i) => PathName(i.name),
NodeImplItem(ii) => PathName(ii.name),
NodeTraitItem(ti) => PathName(ti.name),
NodeVariant(v) => PathName(v.node.name),
NodeLifetime(lt) => PathName(lt.name),
NodeTyParam(tp) => PathName(tp.name),
NodeLocal(&Pat { node: PatIdent(_, l, _), .. }) => {
PathName(l.node.name)
}
_ => {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["no path elem for "];
__STATIC_FMTSTR
},
&match (&node,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/front/map/mod.rs",
551u32);
&_FILE_LINE
})
}
}
}
pub fn with_path<T, F>(&self, id: NodeId, f: F) -> T where
F: FnOnce(PathElems) -> T {
self.with_path_next(id, LinkedPath::empty(), f)
}
pub fn path_to_string(&self, id: NodeId) -> String {
self.with_path(id, |path| path_to_string(path))
}
fn path_to_str_with_name(&self, id: NodeId, name: Name)
-> String {
self.with_path(id, |path| {
path_to_string(path.chain(Some(PathName(name))))
})
}
fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F)
-> T where F: FnOnce(PathElems) -> T {
let parent = self.get_parent(id);
let parent =
match self.find_entry(id) {
Some(EntryForeignItem(..)) => {
self.get_parent(parent)
}
Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => {
return self.with_path_next(parent, next, f);
}
_ => parent,
};
if parent == id {
match self.find_entry(id) {
Some(RootInlinedParent(data)) => {
f(data.path.iter().cloned().chain(next))
}
_ => f([].iter().cloned().chain(next)),
}
} else {
self.with_path_next(parent,
LinkedPath::from(&LinkedPathNode{node:
self.get_path_elem(id),
next:
next,}),
f)
}
}
/// Given a node ID, get a list of attributes associated with the AST
/// corresponding to the Node ID
pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] {
let attrs =
match self.find(id) {
Some(NodeItem(i)) => Some(&i.attrs[..]),
Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
Some(NodeStructCtor(_)) => {
return self.attrs(self.get_parent(id));
}
_ => None,
};
attrs.unwrap_or(&[])
}
/// Returns an iterator that yields the node id's with paths that
/// match `parts`. (Requires `parts` is non-empty.)
///
/// For example, if given `parts` equal to `["bar", "quux"]`, then
/// the iterator will produce node id's for items with paths
/// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
/// any other such items it can find in the map.
pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
-> NodesMatchingSuffix<'a, 'ast> {
NodesMatchingSuffix{map: self,
item_name: parts.last().unwrap(),
in_which: &parts[..parts.len() - 1],
idx: 0,}
}
pub fn opt_span(&self, id: NodeId) -> Option<Span> {
let sp =
match self.find(id) {
Some(NodeItem(item)) => item.span,
Some(NodeForeignItem(foreign_item)) =>
foreign_item.span,
Some(NodeTraitItem(trait_method)) =>
trait_method.span,
Some(NodeImplItem(ref impl_item)) => impl_item.span,
Some(NodeVariant(variant)) => variant.span,
Some(NodeExpr(expr)) => expr.span,
Some(NodeStmt(stmt)) => stmt.span,
Some(NodeLocal(pat)) => pat.span,
Some(NodePat(pat)) => pat.span,
Some(NodeBlock(block)) => block.span,
Some(NodeStructCtor(_)) =>
self.expect_item(self.get_parent(id)).span,
Some(NodeTyParam(ty_param)) => ty_param.span,
_ => return None,
};
Some(sp)
}
pub fn span(&self, id: NodeId) -> Span {
self.opt_span(id).unwrap_or_else(|| {
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["AstMap.span: could not find span for id "];
__STATIC_FMTSTR
},
&match (&id,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/front/map/mod.rs",
659u32);
&_FILE_LINE
})
})
}
pub fn span_if_local(&self, id: DefId) -> Option<Span> {
self.as_local_node_id(id).map(|id| self.span(id))
}
pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
match self.as_local_node_id(def_id) {
Some(node_id) => {
self.opt_span(node_id).unwrap_or(fallback)
}
_ => { fallback }
}
}
pub fn node_to_string(&self, id: NodeId) -> String {
node_id_to_string(self, id, true)
}
pub fn node_to_user_string(&self, id: NodeId) -> String {
node_id_to_string(self, id, false)
}
}
pub struct NodesMatchingSuffix<'a, 'ast:'a> {
map: &'a Map<'ast>,
item_name: &'a String,
in_which: &'a [String],
idx: NodeId,
}
impl <'a, 'ast> NodesMatchingSuffix<'a, 'ast> {
/// Returns true only if some suffix of the module path for parent
/// matches `self.in_which`.
///
/// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
/// returns true if parent's path ends with the suffix
/// `x_0::x_1::...::x_k`.
fn suffix_matches(&self, parent: NodeId) -> bool {
let mut cursor = parent;
{
let result =
match ::std::iter::IntoIterator::into_iter(self.in_which.iter().rev())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(part) => {
let (mod_id, mod_name) =
match find_first_mod_parent(self.map,
cursor)
{
None => return false,
Some((node_id, name)) =>
(node_id, name),
};
if &part[..] != mod_name.as_str() {
return false;
}
cursor = self.map.get_parent(mod_id);
}
::std::option::Option::None => break ,
}
},
};
result
}
return true;
fn find_first_mod_parent<'a>(map: &'a Map, mut id: NodeId)
-> Option<(NodeId, Name)> {
loop {
match map.find(id) {
None => return None,
Some(NodeItem(item)) if item_is_mod(&*item) =>
return Some((id, item.name)),
_ => { }
}
let parent = map.get_parent(id);
if parent == id { return None }
id = parent;
}
fn item_is_mod(item: &Item) -> bool {
match item.node { ItemMod(_) => true, _ => false, }
}
}
}
fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool {
name.as_str() == &self.item_name[..] &&
self.suffix_matches(parent_of_n)
}
}
impl <'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
type
Item
=
NodeId;
fn next(&mut self) -> Option<NodeId> {
loop {
let idx = self.idx;
if idx as usize >= self.map.entry_count() { return None; }
self.idx += 1;
let name =
match self.map.find_entry(idx) {
Some(EntryItem(_, n)) => n.name(),
Some(EntryForeignItem(_, n)) => n.name(),
Some(EntryTraitItem(_, n)) => n.name(),
Some(EntryImplItem(_, n)) => n.name(),
Some(EntryVariant(_, n)) => n.name(),
_ => continue ,
};
if self.matches_names(self.map.get_parent(idx), name) {
return Some(idx)
}
}
}
}
trait Named {
fn name(&self)
-> Name;
}
impl <T: Named> Named for Spanned<T> {
fn name(&self) -> Name { self.node.name() }
}
impl Named for Item {
fn name(&self) -> Name { self.name }
}
impl Named for ForeignItem {
fn name(&self) -> Name { self.name }
}
impl Named for Variant_ {
fn name(&self) -> Name { self.name }
}
impl Named for TraitItem {
fn name(&self) -> Name { self.name }
}
impl Named for ImplItem {
fn name(&self) -> Name { self.name }
}
pub trait FoldOps {
fn new_id(&self, id: NodeId) -> NodeId { id }
fn new_def_id(&self, def_id: DefId) -> DefId { def_id }
fn new_span(&self, span: Span) -> Span { span }
}
/// A Folder that updates IDs and Span's according to fold_ops.
struct IdAndSpanUpdater<F> {
fold_ops: F,
}
impl <F: FoldOps> Folder for IdAndSpanUpdater<F> {
fn new_id(&mut self, id: NodeId) -> NodeId {
self.fold_ops.new_id(id)
}
fn new_span(&mut self, span: Span) -> Span {
self.fold_ops.new_span(span)
}
}
pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
let (map, definitions) =
{
let mut collector = NodeCollector::root(&forest.krate);
intravisit::walk_crate(&mut collector, &forest.krate);
(collector.map, collector.definitions)
};
if {
let lvl = ::log::DEBUG;
(lvl != ::log::DEBUG || false) && lvl <= ::log::log_level()
&& ::log::mod_enabled(lvl, "rustc::front::map")
} {
let (entries_less_1, _) =
map.iter().filter(|&x| {
match *x {
NotPresent => false,
_ => true,
}
}).enumerate().last().expect("AST map was empty after folding?");
let entries = entries_less_1 + 1;
let vector_length = map.len();
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 830u32,
file:
"src/librustc/front/map/mod.rs",
module_path:
"rustc::front::map",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::front::map")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1_formatted({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["The AST map has ",
" entries with a maximum of ",
": occupancy ",
"%"];
__STATIC_FMTSTR
},
&match (&entries,
&vector_length,
&((entries
as
f64
/
vector_length
as
f64)
*
100.))
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
},
{
static __STATIC_FMTARGS:
&'static [::std::fmt::rt::v1::Argument]
=
&[::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::Next,
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::Next,
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Implied,},},
::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::Next,
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Is(1usize),
width:
::std::fmt::rt::v1::Count::Implied,},}];
__STATIC_FMTARGS
}))
}
}
};
}
Map{forest: forest,
map: RefCell::new(map),
definitions: RefCell::new(definitions),}
}
/// Used for items loaded from external crate that are being inlined into this
/// crate. The `path` should be the path to the item but should not include
/// the item itself.
pub fn map_decoded_item<'ast,
F: FoldOps>(map: &Map<'ast>,
path: Vec<PathElem>,
def_path: DefPath,
ii: InlinedItem, fold_ops: F)
-> &'ast InlinedItem {
let mut fld = IdAndSpanUpdater{fold_ops: fold_ops,};
let ii =
match ii {
II::Item(i) => II::Item(i.map(|i| fld.fold_item(i))),
II::TraitItem(d, ti) => {
II::TraitItem(fld.fold_ops.new_def_id(d),
fld.fold_trait_item(ti))
}
II::ImplItem(d, ii) => {
II::ImplItem(fld.fold_ops.new_def_id(d),
fld.fold_impl_item(ii))
}
II::Foreign(i) => II::Foreign(fld.fold_foreign_item(i)),
};
let ii_parent =
map.forest.inlined_items.alloc(InlinedParent{path: path,
ii: ii,});
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
let mut collector =
NodeCollector::extend(map.krate(), ii_parent, ii_parent_id,
def_path,
mem::replace(&mut *map.map.borrow_mut(),
<[_]>::into_vec(::std::boxed::Box::new([]))),
mem::replace(&mut *map.definitions.borrow_mut(),
Definitions::new()));
ii_parent.ii.visit(&mut collector);
*map.map.borrow_mut() = collector.map;
*map.definitions.borrow_mut() = collector.definitions;
&ii_parent.ii
}
pub trait NodePrinter {
fn print_node(&mut self, node: &Node)
-> io::Result<()>;
}
impl <'a> NodePrinter for pprust::State<'a> {
fn print_node(&mut self, node: &Node) -> io::Result<()> {
match *node {
NodeItem(a) => self.print_item(&*a),
NodeForeignItem(a) => self.print_foreign_item(&*a),
NodeTraitItem(a) => self.print_trait_item(a),
NodeImplItem(a) => self.print_impl_item(a),
NodeVariant(a) => self.print_variant(&*a),
NodeExpr(a) => self.print_expr(&*a),
NodeStmt(a) => self.print_stmt(&*a),
NodePat(a) => self.print_pat(&*a),
NodeBlock(a) => self.print_block(&*a),
NodeLifetime(a) => self.print_lifetime(&*a),
NodeTyParam(_) => {
::std::rt::begin_unwind("cannot print TyParam",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/front/map/mod.rs",
903u32);
&_FILE_LINE
})
}
NodeLocal(_) => {
::std::rt::begin_unwind("cannot print isolated Local",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/front/map/mod.rs",
907u32);
&_FILE_LINE
})
}
NodeStructCtor(_) => {
::std::rt::begin_unwind("cannot print isolated StructCtor",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/front/map/mod.rs",
908u32);
&_FILE_LINE
})
}
}
}
}
fn node_id_to_string(map: &Map, id: NodeId, include_id: bool)
-> String {
let id_str =
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[" (id=",
")"];
__STATIC_FMTSTR
},
&match (&id,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}));
let id_str = if include_id { &id_str[..] } else { "" };
match map.find(id) {
Some(NodeItem(item)) => {
let path_str = map.path_to_str_with_name(id, item.name);
let item_str =
match item.node {
ItemExternCrate(..) => "extern crate",
ItemUse(..) => "use",
ItemStatic(..) => "static",
ItemConst(..) => "const",
ItemFn(..) => "fn",
ItemMod(..) => "mod",
ItemForeignMod(..) => "foreign mod",
ItemTy(..) => "ty",
ItemEnum(..) => "enum",
ItemStruct(..) => "struct",
ItemTrait(..) => "trait",
ItemImpl(..) => "impl",
ItemDefaultImpl(..) => "default impl",
};
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["",
" ",
""];
__STATIC_FMTSTR
},
&match (&item_str,
&path_str,
&id_str)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
}))
}
Some(NodeForeignItem(item)) => {
let path_str = map.path_to_str_with_name(id, item.name);
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["foreign item ",
""];
__STATIC_FMTSTR
},
&match (&path_str,
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodeImplItem(ii)) => {
match ii.node {
ImplItemKind::Const(..) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assoc const ",
" in ",
""];
__STATIC_FMTSTR
},
&match (&ii.name,
&map.path_to_string(id),
&id_str)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
}))
}
ImplItemKind::Method(..) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["method ",
" in ",
""];
__STATIC_FMTSTR
},
&match (&ii.name,
&map.path_to_string(id),
&id_str)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
}))
}
ImplItemKind::Type(_) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assoc type ",
" in ",
""];
__STATIC_FMTSTR
},
&match (&ii.name,
&map.path_to_string(id),
&id_str)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
}))
}
}
}
Some(NodeTraitItem(ti)) => {
let kind =
match ti.node {
ConstTraitItem(..) => "assoc constant",
MethodTraitItem(..) => "trait method",
TypeTraitItem(..) => "assoc type",
};
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["",
" ",
" in ",
""];
__STATIC_FMTSTR
},
&match (&kind,
&ti.name,
&map.path_to_string(id),
&id_str)
{
(__arg0,
__arg1,
__arg2,
__arg3)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg3,
::std::fmt::Display::fmt)],
}))
}
Some(NodeVariant(ref variant)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["variant ",
" in ",
""];
__STATIC_FMTSTR
},
&match (&variant.node.name,
&map.path_to_string(id),
&id_str)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Display::fmt)],
}))
}
Some(NodeExpr(ref expr)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expr ",
""];
__STATIC_FMTSTR
},
&match (&pprust::expr_to_string(&**expr),
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodeStmt(ref stmt)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["stmt ",
""];
__STATIC_FMTSTR
},
&match (&pprust::stmt_to_string(&**stmt),
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodeLocal(ref pat)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["local ",
""];
__STATIC_FMTSTR
},
&match (&pprust::pat_to_string(&**pat),
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodePat(ref pat)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["pat ",
""];
__STATIC_FMTSTR
},
&match (&pprust::pat_to_string(&**pat),
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodeBlock(ref block)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["block ",
""];
__STATIC_FMTSTR
},
&match (&pprust::block_to_string(&**block),
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodeStructCtor(_)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["struct_ctor ",
""];
__STATIC_FMTSTR
},
&match (&map.path_to_string(id),
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodeLifetime(ref l)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["lifetime ",
""];
__STATIC_FMTSTR
},
&match (&pprust::lifetime_to_string(&**l),
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
Some(NodeTyParam(ref ty_param)) => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["typaram ",
""];
__STATIC_FMTSTR
},
&match (&ty_param,
&id_str)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
None => {
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["unknown node"];
__STATIC_FMTSTR
},
&match (&id_str,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}))
}
}
}
}
}
pub mod middle {
#[prelude_import]
use std::prelude::v1::*;
pub mod astconv_util {
/*!
* This module contains a simple utility routine
* used by both `typeck` and `const_eval`.
* Almost certainly this could (and should) be refactored out of existence.
*/
#[prelude_import]
use std::prelude::v1::*;
use middle::def;
use middle::ty::{self, Ty};
use syntax::codemap::Span;
use rustc_front::hir as ast;
pub fn prohibit_type_params(tcx: &ty::ctxt,
segments: &[ast::PathSegment]) {
{
let result =
match ::std::iter::IntoIterator::into_iter(segments) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(segment) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(segment.parameters.types())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(typ)
=> {
{
();
tcx.sess.span_err_with_code(typ.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["type parameters are not allowed on this type"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0109")
};
break ;
}
::std::option::Option::None
=> break ,
}
},
};
result
}
{
let result =
match ::std::iter::IntoIterator::into_iter(segment.parameters.lifetimes())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(lifetime)
=> {
{
();
tcx.sess.span_err_with_code(lifetime.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["lifetime parameters are not allowed on this type"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0110")
};
break ;
}
::std::option::Option::None
=> break ,
}
},
};
result
}
{
let result =
match ::std::iter::IntoIterator::into_iter(segment.parameters.bindings())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(binding)
=> {
prohibit_projection(tcx,
binding.span);
break ;
}
::std::option::Option::None
=> break ,
}
},
};
result
}
}
::std::option::Option::None => break ,
}
},
};
result
}
}
pub fn prohibit_projection(tcx: &ty::ctxt, span: Span) {
{
();
tcx.sess.span_err_with_code(span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["associated type bindings are not allowed here"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0229")
};
}
pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
segments: &[ast::PathSegment],
nty: ast::PrimTy) -> Ty<'tcx> {
prohibit_type_params(tcx, segments);
match nty {
ast::TyBool => tcx.types.bool,
ast::TyChar => tcx.types.char,
ast::TyInt(it) => tcx.mk_mach_int(it),
ast::TyUint(uit) => tcx.mk_mach_uint(uit),
ast::TyFloat(ft) => tcx.mk_mach_float(ft),
ast::TyStr => tcx.mk_str(),
}
}
/// If a type in the AST is a primitive type, return the ty::Ty corresponding
/// to it.
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
-> Option<Ty<'tcx>> {
match ast_ty.node {
ast::TyPath(None, ref path) => {
let def =
match tcx.def_map.borrow().get(&ast_ty.id) {
None => {
tcx.sess.span_bug(ast_ty.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["unbound path "];
__STATIC_FMTSTR
},
&match (&path,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
})))
}
Some(d) => d.full_def(),
};
match def {
def::DefPrimTy(nty) => {
Some(prim_ty_to_ty(tcx, &path.segments, nty))
}
_ => { None }
}
}
_ => { None }
}
}
}
pub mod expr_use_visitor {
//! A different sort of visitor for walking fn bodies. Unlike the
//! normal visitor, which just walks the entire body in one shot, the
//! `ExprUseVisitor` determines how expressions are being used.
#[prelude_import]
use std::prelude::v1::*;
pub use self::MutateMode::*;
pub use self::LoanCause::*;
pub use self::ConsumeMode::*;
pub use self::MoveReason::*;
pub use self::MatchMode::*;
use self::TrackMatchMode::*;
use self::OverloadedCallType::*;
use middle::{def, pat_util};
use middle::def_id::{DefId};
use middle::infer;
use middle::mem_categorization as mc;
use middle::ty;
use middle::ty::adjustment;
use rustc_front::hir;
use syntax::ast;
use syntax::ptr::P;
use syntax::codemap::Span;
/// This trait defines the callbacks you can expect to receive when
/// employing the ExprUseVisitor.
pub trait Delegate<'tcx> {
fn consume(&mut self, consume_id: ast::NodeId, consume_span: Span,
cmt: mc::cmt<'tcx>, mode: ConsumeMode);
fn matched_pat(&mut self, matched_pat: &hir::Pat,
cmt: mc::cmt<'tcx>, mode: MatchMode);
fn consume_pat(&mut self, consume_pat: &hir::Pat,
cmt: mc::cmt<'tcx>, mode: ConsumeMode);
fn borrow(&mut self, borrow_id: ast::NodeId, borrow_span: Span,
cmt: mc::cmt<'tcx>, loan_region: ty::Region,
bk: ty::BorrowKind, loan_cause: LoanCause);
fn decl_without_init(&mut self, id: ast::NodeId, span: Span);
fn mutate(&mut self, assignment_id: ast::NodeId,
assignment_span: Span, assignee_cmt: mc::cmt<'tcx>,
mode: MutateMode);
}
pub enum LoanCause {
ClosureCapture(Span),
AddrOf,
AutoRef,
AutoUnsafe,
RefBinding,
OverloadedOperator,
ClosureInvocation,
ForLoop,
MatchDiscriminant,
}
#[automatically_derived]
impl ::std::fmt::Debug for LoanCause {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&LoanCause::ClosureCapture(ref __self_0),) =>
__arg_0.debug_tuple("ClosureCapture").field(&&(*__self_0)).finish(),
(&LoanCause::AddrOf,) =>
__arg_0.debug_tuple("AddrOf").finish(),
(&LoanCause::AutoRef,) =>
__arg_0.debug_tuple("AutoRef").finish(),
(&LoanCause::AutoUnsafe,) =>
__arg_0.debug_tuple("AutoUnsafe").finish(),
(&LoanCause::RefBinding,) =>
__arg_0.debug_tuple("RefBinding").finish(),
(&LoanCause::OverloadedOperator,) =>
__arg_0.debug_tuple("OverloadedOperator").finish(),
(&LoanCause::ClosureInvocation,) =>
__arg_0.debug_tuple("ClosureInvocation").finish(),
(&LoanCause::ForLoop,) =>
__arg_0.debug_tuple("ForLoop").finish(),
(&LoanCause::MatchDiscriminant,) =>
__arg_0.debug_tuple("MatchDiscriminant").finish(),
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for LoanCause {
#[inline]
fn eq(&self, __arg_0: &LoanCause) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&LoanCause::ClosureCapture(ref __self_0),
&LoanCause::ClosureCapture(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&LoanCause::AddrOf, &LoanCause::AddrOf) => true,
(&LoanCause::AutoRef, &LoanCause::AutoRef) =>
true,
(&LoanCause::AutoUnsafe, &LoanCause::AutoUnsafe)
=> true,
(&LoanCause::RefBinding, &LoanCause::RefBinding)
=> true,
(&LoanCause::OverloadedOperator,
&LoanCause::OverloadedOperator) => true,
(&LoanCause::ClosureInvocation,
&LoanCause::ClosureInvocation) => true,
(&LoanCause::ForLoop, &LoanCause::ForLoop) =>
true,
(&LoanCause::MatchDiscriminant,
&LoanCause::MatchDiscriminant) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &LoanCause) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&LoanCause::ClosureCapture(ref __self_0),
&LoanCause::ClosureCapture(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&LoanCause::AddrOf, &LoanCause::AddrOf) => false,
(&LoanCause::AutoRef, &LoanCause::AutoRef) =>
false,
(&LoanCause::AutoUnsafe, &LoanCause::AutoUnsafe)
=> false,
(&LoanCause::RefBinding, &LoanCause::RefBinding)
=> false,
(&LoanCause::OverloadedOperator,
&LoanCause::OverloadedOperator) => false,
(&LoanCause::ClosureInvocation,
&LoanCause::ClosureInvocation) => false,
(&LoanCause::ForLoop, &LoanCause::ForLoop) =>
false,
(&LoanCause::MatchDiscriminant,
&LoanCause::MatchDiscriminant) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for LoanCause {
#[inline]
fn clone(&self) -> LoanCause {
match (&*self,) {
(&LoanCause::ClosureCapture(ref __self_0),) =>
LoanCause::ClosureCapture(::std::clone::Clone::clone(&(*__self_0))),
(&LoanCause::AddrOf,) => LoanCause::AddrOf,
(&LoanCause::AutoRef,) => LoanCause::AutoRef,
(&LoanCause::AutoUnsafe,) => LoanCause::AutoUnsafe,
(&LoanCause::RefBinding,) => LoanCause::RefBinding,
(&LoanCause::OverloadedOperator,) =>
LoanCause::OverloadedOperator,
(&LoanCause::ClosureInvocation,) =>
LoanCause::ClosureInvocation,
(&LoanCause::ForLoop,) => LoanCause::ForLoop,
(&LoanCause::MatchDiscriminant,) =>
LoanCause::MatchDiscriminant,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for LoanCause { }
pub enum ConsumeMode { Copy, Move(MoveReason), }
#[automatically_derived]
impl ::std::fmt::Debug for ConsumeMode {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&ConsumeMode::Copy,) =>
__arg_0.debug_tuple("Copy").finish(),
(&ConsumeMode::Move(ref __self_0),) =>
__arg_0.debug_tuple("Move").field(&&(*__self_0)).finish(),
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for ConsumeMode {
#[inline]
fn eq(&self, __arg_0: &ConsumeMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&ConsumeMode::Copy, &ConsumeMode::Copy) => true,
(&ConsumeMode::Move(ref __self_0),
&ConsumeMode::Move(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &ConsumeMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&ConsumeMode::Copy, &ConsumeMode::Copy) => false,
(&ConsumeMode::Move(ref __self_0),
&ConsumeMode::Move(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for ConsumeMode {
#[inline]
fn clone(&self) -> ConsumeMode {
match (&*self,) {
(&ConsumeMode::Copy,) => ConsumeMode::Copy,
(&ConsumeMode::Move(ref __self_0),) =>
ConsumeMode::Move(::std::clone::Clone::clone(&(*__self_0))),
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for ConsumeMode { }
pub enum MoveReason { DirectRefMove, PatBindingMove, CaptureMove, }
#[automatically_derived]
impl ::std::fmt::Debug for MoveReason {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&MoveReason::DirectRefMove,) =>
__arg_0.debug_tuple("DirectRefMove").finish(),
(&MoveReason::PatBindingMove,) =>
__arg_0.debug_tuple("PatBindingMove").finish(),
(&MoveReason::CaptureMove,) =>
__arg_0.debug_tuple("CaptureMove").finish(),
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for MoveReason {
#[inline]
fn eq(&self, __arg_0: &MoveReason) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&MoveReason::DirectRefMove,
&MoveReason::DirectRefMove) => true,
(&MoveReason::PatBindingMove,
&MoveReason::PatBindingMove) => true,
(&MoveReason::CaptureMove,
&MoveReason::CaptureMove) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &MoveReason) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&MoveReason::DirectRefMove,
&MoveReason::DirectRefMove) => false,
(&MoveReason::PatBindingMove,
&MoveReason::PatBindingMove) => false,
(&MoveReason::CaptureMove,
&MoveReason::CaptureMove) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for MoveReason {
#[inline]
fn clone(&self) -> MoveReason {
match (&*self,) {
(&MoveReason::DirectRefMove,) =>
MoveReason::DirectRefMove,
(&MoveReason::PatBindingMove,) =>
MoveReason::PatBindingMove,
(&MoveReason::CaptureMove,) => MoveReason::CaptureMove,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for MoveReason { }
pub enum MatchMode {
NonBindingMatch,
BorrowingMatch,
CopyingMatch,
MovingMatch,
}
#[automatically_derived]
impl ::std::fmt::Debug for MatchMode {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&MatchMode::NonBindingMatch,) =>
__arg_0.debug_tuple("NonBindingMatch").finish(),
(&MatchMode::BorrowingMatch,) =>
__arg_0.debug_tuple("BorrowingMatch").finish(),
(&MatchMode::CopyingMatch,) =>
__arg_0.debug_tuple("CopyingMatch").finish(),
(&MatchMode::MovingMatch,) =>
__arg_0.debug_tuple("MovingMatch").finish(),
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for MatchMode {
#[inline]
fn eq(&self, __arg_0: &MatchMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&MatchMode::NonBindingMatch,
&MatchMode::NonBindingMatch) => true,
(&MatchMode::BorrowingMatch,
&MatchMode::BorrowingMatch) => true,
(&MatchMode::CopyingMatch,
&MatchMode::CopyingMatch) => true,
(&MatchMode::MovingMatch, &MatchMode::MovingMatch)
=> true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &MatchMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&MatchMode::NonBindingMatch,
&MatchMode::NonBindingMatch) => false,
(&MatchMode::BorrowingMatch,
&MatchMode::BorrowingMatch) => false,
(&MatchMode::CopyingMatch,
&MatchMode::CopyingMatch) => false,
(&MatchMode::MovingMatch, &MatchMode::MovingMatch)
=> false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for MatchMode {
#[inline]
fn clone(&self) -> MatchMode {
match (&*self,) {
(&MatchMode::NonBindingMatch,) =>
MatchMode::NonBindingMatch,
(&MatchMode::BorrowingMatch,) =>
MatchMode::BorrowingMatch,
(&MatchMode::CopyingMatch,) => MatchMode::CopyingMatch,
(&MatchMode::MovingMatch,) => MatchMode::MovingMatch,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for MatchMode { }
enum TrackMatchMode { Unknown, Definite(MatchMode), Conflicting, }
#[automatically_derived]
impl ::std::fmt::Debug for TrackMatchMode {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&TrackMatchMode::Unknown,) =>
__arg_0.debug_tuple("Unknown").finish(),
(&TrackMatchMode::Definite(ref __self_0),) =>
__arg_0.debug_tuple("Definite").field(&&(*__self_0)).finish(),
(&TrackMatchMode::Conflicting,) =>
__arg_0.debug_tuple("Conflicting").finish(),
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for TrackMatchMode {
#[inline]
fn eq(&self, __arg_0: &TrackMatchMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&TrackMatchMode::Unknown,
&TrackMatchMode::Unknown) => true,
(&TrackMatchMode::Definite(ref __self_0),
&TrackMatchMode::Definite(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&TrackMatchMode::Conflicting,
&TrackMatchMode::Conflicting) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &TrackMatchMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&TrackMatchMode::Unknown,
&TrackMatchMode::Unknown) => false,
(&TrackMatchMode::Definite(ref __self_0),
&TrackMatchMode::Definite(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&TrackMatchMode::Conflicting,
&TrackMatchMode::Conflicting) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for TrackMatchMode {
#[inline]
fn clone(&self) -> TrackMatchMode {
match (&*self,) {
(&TrackMatchMode::Unknown,) => TrackMatchMode::Unknown,
(&TrackMatchMode::Definite(ref __self_0),) =>
TrackMatchMode::Definite(::std::clone::Clone::clone(&(*__self_0))),
(&TrackMatchMode::Conflicting,) =>
TrackMatchMode::Conflicting,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for TrackMatchMode { }
impl TrackMatchMode {
fn lub(&mut self, mode: MatchMode) {
*self =
match (*self, mode) {
(Unknown, new) => Definite(new),
(Definite(old), new) if old == new => Definite(old),
(Definite(old), NonBindingMatch) => Definite(old),
(Definite(NonBindingMatch), new) => Definite(new),
(Definite(old), CopyingMatch) => Definite(old),
(Definite(CopyingMatch), new) => Definite(new),
(Definite(_), _) => Conflicting,
(Conflicting, _) => *self,
};
}
fn match_mode(&self) -> MatchMode {
match *self {
Unknown => NonBindingMatch,
Definite(mode) => mode,
Conflicting => { MovingMatch }
}
}
}
pub enum MutateMode { Init, JustWrite, WriteAndRead, }
#[automatically_derived]
impl ::std::fmt::Debug for MutateMode {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&MutateMode::Init,) =>
__arg_0.debug_tuple("Init").finish(),
(&MutateMode::JustWrite,) =>
__arg_0.debug_tuple("JustWrite").finish(),
(&MutateMode::WriteAndRead,) =>
__arg_0.debug_tuple("WriteAndRead").finish(),
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for MutateMode {
#[inline]
fn eq(&self, __arg_0: &MutateMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&MutateMode::Init, &MutateMode::Init) => true,
(&MutateMode::JustWrite, &MutateMode::JustWrite)
=> true,
(&MutateMode::WriteAndRead,
&MutateMode::WriteAndRead) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &MutateMode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&MutateMode::Init, &MutateMode::Init) => false,
(&MutateMode::JustWrite, &MutateMode::JustWrite)
=> false,
(&MutateMode::WriteAndRead,
&MutateMode::WriteAndRead) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for MutateMode {
#[inline]
fn clone(&self) -> MutateMode {
match (&*self,) {
(&MutateMode::Init,) => MutateMode::Init,
(&MutateMode::JustWrite,) => MutateMode::JustWrite,
(&MutateMode::WriteAndRead,) => MutateMode::WriteAndRead,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for MutateMode { }
enum OverloadedCallType {
FnOverloadedCall,
FnMutOverloadedCall,
FnOnceOverloadedCall,
}
#[automatically_derived]
impl ::std::clone::Clone for OverloadedCallType {
#[inline]
fn clone(&self) -> OverloadedCallType {
match (&*self,) {
(&OverloadedCallType::FnOverloadedCall,) =>
OverloadedCallType::FnOverloadedCall,
(&OverloadedCallType::FnMutOverloadedCall,) =>
OverloadedCallType::FnMutOverloadedCall,
(&OverloadedCallType::FnOnceOverloadedCall,) =>
OverloadedCallType::FnOnceOverloadedCall,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for OverloadedCallType { }
impl OverloadedCallType {
fn from_trait_id(tcx: &ty::ctxt, trait_id: DefId)
-> OverloadedCallType {
{
let result =
match ::std::iter::IntoIterator::into_iter(&[(tcx.lang_items.fn_once_trait(),
FnOnceOverloadedCall),
(tcx.lang_items.fn_mut_trait(),
FnMutOverloadedCall),
(tcx.lang_items.fn_trait(),
FnOverloadedCall)])
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(&(maybe_function_trait,
overloaded_call_type))
=> {
match maybe_function_trait {
Some(function_trait) if
function_trait == trait_id => {
return overloaded_call_type
}
_ => continue ,
}
}
::std::option::Option::None => break ,
}
},
};
result
}
tcx.sess.bug("overloaded call didn\'t map to known function trait")
}
fn from_method_id(tcx: &ty::ctxt, method_id: DefId)
-> OverloadedCallType {
let method = tcx.impl_or_trait_item(method_id);
OverloadedCallType::from_trait_id(tcx,
method.container().id())
}
}
pub struct ExprUseVisitor<'d, 't, 'a:'t, 'tcx:'a+'d> {
typer: &'t infer::InferCtxt<'a, 'tcx>,
mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
delegate: &'d mut Delegate<'tcx>,
}
/// Whether the elements of an overloaded operation are passed by value or by reference
enum PassArgs { ByValue, ByRef, }
impl <'d, 't, 'a, 'tcx> ExprUseVisitor<'d, 't, 'a, 'tcx> {
pub fn new(delegate: &'d mut (Delegate<'tcx>),
typer: &'t infer::InferCtxt<'a, 'tcx>)
-> ExprUseVisitor<'d, 't, 'a, 'tcx> where 'tcx:'a+'d {
let mc: mc::MemCategorizationContext<'t, 'a, 'tcx> =
mc::MemCategorizationContext::new(typer);
ExprUseVisitor{typer: typer, mc: mc, delegate: delegate,}
}
pub fn walk_fn(&mut self, decl: &hir::FnDecl, body: &hir::Block) {
self.walk_arg_patterns(decl, body);
self.walk_block(body);
}
fn walk_arg_patterns(&mut self, decl: &hir::FnDecl,
body: &hir::Block) {
{
let result =
match ::std::iter::IntoIterator::into_iter(&decl.inputs)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(arg) => {
let arg_ty =
match self.typer.node_ty(arg.pat.id)
{
Ok(v) => v,
Err(()) => {
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
299u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl !=
::log::DEBUG
||
false)
&&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
let fn_body_scope =
self.tcx().region_maps.node_extent(body.id);
let arg_cmt =
self.mc.cat_rvalue(arg.id,
arg.pat.span,
ty::ReScope(fn_body_scope),
arg_ty);
self.walk_irrefutable_pat(arg_cmt,
&*arg.pat);
}
::std::option::Option::None => break ,
}
},
};
result
}
}
fn tcx(&self) -> &'t ty::ctxt<'tcx> { self.typer.tcx }
fn delegate_consume(&mut self, consume_id: ast::NodeId,
consume_span: Span, cmt: mc::cmt<'tcx>) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 320u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["delegate_consume(consume_id=",
", cmt=",
")"];
__STATIC_FMTSTR
},
&match (&consume_id,
&cmt)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
let mode = copy_or_move(self.typer, &cmt, DirectRefMove);
self.delegate.consume(consume_id, consume_span, cmt, mode);
}
fn consume_exprs(&mut self, exprs: &Vec<P<hir::Expr>>) {
{
let result =
match ::std::iter::IntoIterator::into_iter(exprs) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(expr) => {
self.consume_expr(&**expr);
}
::std::option::Option::None => break ,
}
},
};
result
}
}
pub fn consume_expr(&mut self, expr: &hir::Expr) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 334u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["consume_expr(expr=",
")"];
__STATIC_FMTSTR
},
&match (&expr,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}))
}
}
};
let cmt =
match self.mc.cat_expr(expr) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 336u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
self.delegate_consume(expr.id, expr.span, cmt);
self.walk_expr(expr);
}
fn mutate_expr(&mut self, assignment_expr: &hir::Expr,
expr: &hir::Expr, mode: MutateMode) {
let cmt =
match self.mc.cat_expr(expr) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 345u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
self.delegate.mutate(assignment_expr.id, assignment_expr.span,
cmt, mode);
self.walk_expr(expr);
}
fn borrow_expr(&mut self, expr: &hir::Expr, r: ty::Region,
bk: ty::BorrowKind, cause: LoanCause) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 355u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["borrow_expr(expr=",
", r=",
", bk=",
")"];
__STATIC_FMTSTR
},
&match (&expr,
&r,
&bk)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Debug::fmt)],
}))
}
}
};
let cmt =
match self.mc.cat_expr(expr) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 358u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause);
self.walk_expr(expr)
}
fn select_from_expr(&mut self, expr: &hir::Expr) {
self.walk_expr(expr)
}
pub fn walk_expr(&mut self, expr: &hir::Expr) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 369u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_expr(expr=",
")"];
__STATIC_FMTSTR
},
&match (&expr,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}))
}
}
};
self.walk_adjustment(expr);
match expr.node {
hir::ExprPath(..) => { }
hir::ExprUnary(hir::UnDeref, ref base) => {
if !self.walk_overloaded_operator(expr, &**base,
Vec::new(),
PassArgs::ByRef) {
self.select_from_expr(&**base);
}
}
hir::ExprField(ref base, _) => {
self.select_from_expr(&**base);
}
hir::ExprTupField(ref base, _) => {
self.select_from_expr(&**base);
}
hir::ExprIndex(ref lhs, ref rhs) => {
if !self.walk_overloaded_operator(expr, &**lhs,
<[_]>::into_vec(::std::boxed::Box::new([&**rhs])),
PassArgs::ByValue) {
self.select_from_expr(&**lhs);
self.consume_expr(&**rhs);
}
}
hir::ExprRange(ref start, ref end) => {
start.as_ref().map(|e| self.consume_expr(&**e));
end.as_ref().map(|e| self.consume_expr(&**e));
}
hir::ExprCall(ref callee, ref args) => {
self.walk_callee(expr, &**callee);
self.consume_exprs(args);
}
hir::ExprMethodCall(_, _, ref args) => {
self.consume_exprs(args);
}
hir::ExprStruct(_, ref fields, ref opt_with) => {
self.walk_struct_expr(expr, fields, opt_with);
}
hir::ExprTup(ref exprs) => { self.consume_exprs(exprs); }
hir::ExprIf(ref cond_expr, ref then_blk,
ref opt_else_expr) => {
self.consume_expr(&**cond_expr);
self.walk_block(&**then_blk);
match *opt_else_expr {
Some(ref else_expr) => {
self.consume_expr(&**else_expr);
}
_ => (),
}
}
hir::ExprMatch(ref discr, ref arms, _) => {
let discr_cmt =
match self.mc.cat_expr(&**discr) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line:
431u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG ||
false) &&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow,
MatchDiscriminant);
{
let result =
match ::std::iter::IntoIterator::into_iter(arms)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(arm)
=> {
let mode =
self.arm_move_mode(discr_cmt.clone(),
arm);
let mode = mode.match_mode();
self.walk_arm(discr_cmt.clone(),
arm, mode);
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
hir::ExprVec(ref exprs) => { self.consume_exprs(exprs); }
hir::ExprAddrOf(m, ref base) => {
let expr_ty =
match self.typer.node_ty(expr.id) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line:
449u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG ||
false) &&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
match expr_ty.sty {
ty::TyRef(&r, _) => {
let bk = ty::BorrowKind::from_mutbl(m);
self.borrow_expr(&**base, r, bk, AddrOf);
}
_ => (),
}
}
hir::ExprInlineAsm(ref ia) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(&ia.inputs)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(&(_,
ref input))
=> {
self.consume_expr(&**input);
}
::std::option::Option::None =>
break ,
}
},
};
result
}
{
let result =
match ::std::iter::IntoIterator::into_iter(&ia.outputs)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(&(_,
ref output,
is_rw))
=> {
self.mutate_expr(expr,
&**output,
if is_rw {
WriteAndRead
} else {
JustWrite
});
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(..)
=> {
}
hir::ExprLoop(ref blk, _) => { self.walk_block(&**blk); }
hir::ExprWhile(ref cond_expr, ref blk, _) => {
self.consume_expr(&**cond_expr);
self.walk_block(&**blk);
}
hir::ExprUnary(op, ref lhs) => {
let pass_args =
if ::rustc_front::util::is_by_value_unop(op) {
PassArgs::ByValue
} else { PassArgs::ByRef };
if !self.walk_overloaded_operator(expr, &**lhs,
Vec::new(),
pass_args) {
self.consume_expr(&**lhs);
}
}
hir::ExprBinary(op, ref lhs, ref rhs) => {
let pass_args =
if ::rustc_front::util::is_by_value_binop(op.node)
{
PassArgs::ByValue
} else { PassArgs::ByRef };
if !self.walk_overloaded_operator(expr, &**lhs,
<[_]>::into_vec(::std::boxed::Box::new([&**rhs])),
pass_args) {
self.consume_expr(&**lhs);
self.consume_expr(&**rhs);
}
}
hir::ExprBlock(ref blk) => { self.walk_block(&**blk); }
hir::ExprRet(ref opt_expr) => {
match *opt_expr {
Some(ref expr) => { self.consume_expr(&**expr); }
_ => (),
}
}
hir::ExprAssign(ref lhs, ref rhs) => {
self.mutate_expr(expr, &**lhs, JustWrite);
self.consume_expr(&**rhs);
}
hir::ExprCast(ref base, _) => {
self.consume_expr(&**base);
}
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
if !::rustc_front::util::is_by_value_binop(op.node) {
{
::std::rt::begin_unwind("assertion failed: ::rustc_front::util::is_by_value_binop(op.node)",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/expr_use_visitor.rs",
526u32);
&_FILE_LINE
})
}
};
if !self.walk_overloaded_operator(expr, lhs,
<[_]>::into_vec(::std::boxed::Box::new([rhs])),
PassArgs::ByValue) {
self.mutate_expr(expr, &**lhs, WriteAndRead);
self.consume_expr(&**rhs);
}
}
hir::ExprRepeat(ref base, ref count) => {
self.consume_expr(&**base);
self.consume_expr(&**count);
}
hir::ExprClosure(..) => { self.walk_captures(expr) }
hir::ExprBox(ref base) => { self.consume_expr(&**base); }
}
}
fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
let callee_ty =
match self.typer.expr_ty_adjusted(callee) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 550u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 551u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_callee: callee=",
" callee_ty="];
__STATIC_FMTSTR
},
&match (&callee,
&callee_ty)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
let call_scope = self.tcx().region_maps.node_extent(call.id);
match callee_ty.sty {
ty::TyBareFn(..) => { self.consume_expr(callee); }
ty::TyError => { }
_ => {
let overloaded_call_type =
match self.typer.node_method_id(ty::MethodCall::expr(call.id))
{
Some(method_id) => {
OverloadedCallType::from_method_id(self.tcx(),
method_id)
}
None => {
self.tcx().sess.span_bug(callee.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["unexpected callee type "];
__STATIC_FMTSTR
},
&match (&callee_ty,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})))
}
};
match overloaded_call_type {
FnMutOverloadedCall => {
self.borrow_expr(callee,
ty::ReScope(call_scope),
ty::MutBorrow,
ClosureInvocation);
}
FnOverloadedCall => {
self.borrow_expr(callee,
ty::ReScope(call_scope),
ty::ImmBorrow,
ClosureInvocation);
}
FnOnceOverloadedCall => self.consume_expr(callee),
}
}
}
}
fn walk_stmt(&mut self, stmt: &hir::Stmt) {
match stmt.node {
hir::StmtDecl(ref decl, _) => {
match decl.node {
hir::DeclLocal(ref local) => {
self.walk_local(&**local);
}
hir::DeclItem(_) => { }
}
}
hir::StmtExpr(ref expr, _) | hir::StmtSemi(ref expr, _) =>
{
self.consume_expr(&**expr);
}
}
}
fn walk_local(&mut self, local: &hir::Local) {
match local.init {
None => {
let delegate = &mut self.delegate;
pat_util::pat_bindings(&self.typer.tcx.def_map,
&*local.pat, |_, id, span, _| {
delegate.decl_without_init(id,
span);
})
}
Some(ref expr) => {
self.walk_expr(&**expr);
let init_cmt =
match self.mc.cat_expr(&**expr) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line:
628u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG ||
false) &&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
self.walk_irrefutable_pat(init_cmt, &*local.pat);
}
}
}
/// Indicates that the value of `blk` will be consumed, meaning either copied or moved
/// depending on its type.
fn walk_block(&mut self, blk: &hir::Block) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 637u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_block(blk.id=",
")"];
__STATIC_FMTSTR
},
&match (&blk.id,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}))
}
}
};
{
let result =
match ::std::iter::IntoIterator::into_iter(&blk.stmts)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(stmt) => {
self.walk_stmt(&**stmt);
}
::std::option::Option::None => break ,
}
},
};
result
}
match blk.expr {
Some(ref tail_expr) => {
self.consume_expr(&**tail_expr);
}
_ => (),
}
}
fn walk_struct_expr(&mut self, _expr: &hir::Expr,
fields: &Vec<hir::Field>,
opt_with: &Option<P<hir::Expr>>) {
{
let result =
match ::std::iter::IntoIterator::into_iter(fields) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(field) => {
self.consume_expr(&*field.expr);
}
::std::option::Option::None => break ,
}
},
};
result
}
let with_expr =
match *opt_with {
Some(ref w) => &**w,
None => { return; }
};
let with_cmt =
match self.mc.cat_expr(&*with_expr) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 662u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
match with_cmt.ty.sty {
ty::TyStruct(def, substs) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(&def.struct_variant().fields)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(with_field)
=> {
if !contains_field_named(with_field,
fields)
{
let cmt_field =
self.mc.cat_field(&*with_expr,
with_cmt.clone(),
with_field.name,
with_field.ty(self.tcx(),
substs));
self.delegate_consume(with_expr.id,
with_expr.span,
cmt_field);
}
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
_ => {
if !self.tcx().sess.has_errors() {
self.tcx().sess.span_bug(with_expr.span,
"with expression doesn\'t evaluate to a struct");
}
}
};
self.walk_expr(with_expr);
fn contains_field_named(field: ty::FieldDef,
fields: &Vec<hir::Field>) -> bool {
fields.iter().any(|f| f.name.node == field.name)
}
}
fn walk_adjustment(&mut self, expr: &hir::Expr) {
let typer = self.typer;
let adj =
typer.adjustments().get(&expr.id).map(|x| x.clone());
match adj {
Some(adjustment) => {
match adjustment {
adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 717u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false)
&&
lvl <= ::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_adjustment(AdjustReifyFnPointer|AdjustUnsafeFnPointer)"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
let cmt_unadjusted =
match self.mc.cat_expr_unadjusted(expr) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
719u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl !=
::log::DEBUG
|| false) &&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
self.delegate_consume(expr.id, expr.span,
cmt_unadjusted);
}
adjustment::AdjustDerefRef(ref adj) => {
self.walk_autoderefref(expr, adj);
}
}
}
_ => (),
}
}
/// Autoderefs for overloaded Deref calls in fact reference their receiver. That is, if we have
/// `(*x)` where `x` is of type `Rc<T>`, then this in fact is equivalent to `x.deref()`. Since
/// `deref()` is declared with `&self`, this is an autoref of `x`.
fn walk_autoderefs(&mut self, expr: &hir::Expr,
autoderefs: usize) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 735u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_autoderefs expr=",
" autoderefs="];
__STATIC_FMTSTR
},
&match (&expr,
&autoderefs)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
}))
}
}
};
{
let result =
match ::std::iter::IntoIterator::into_iter(0..autoderefs)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(i) => {
let deref_id =
ty::MethodCall::autoderef(expr.id,
i as
u32);
match self.typer.node_method_ty(deref_id)
{
None => { }
Some(method_ty) => {
let cmt =
match self.mc.cat_expr_autoderefd(expr,
i)
{
Ok(v) => v,
Err(()) => {
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
742u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl
!=
::log::DEBUG
||
false)
&&
lvl
<=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
let self_ty =
method_ty.fn_sig().input(0);
let self_ty =
self.tcx().no_late_bound_regions(&self_ty).unwrap();
let (m, r) =
match self_ty.sty {
ty::TyRef(r, ref m) =>
(m.mutbl, r),
_ =>
self.tcx().sess.span_bug(expr.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["bad overloaded deref type "];
__STATIC_FMTSTR
},
&match (&method_ty,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}))),
};
let bk =
ty::BorrowKind::from_mutbl(m);
self.delegate.borrow(expr.id,
expr.span,
cmt, *r,
bk,
AutoRef);
}
}
}
::std::option::Option::None => break ,
}
},
};
result
}
}
fn walk_autoderefref(&mut self, expr: &hir::Expr,
adj: &adjustment::AutoDerefRef<'tcx>) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 766u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_autoderefref expr=",
" adj="];
__STATIC_FMTSTR
},
&match (&expr,
&adj)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
self.walk_autoderefs(expr, adj.autoderefs);
let cmt_derefd =
match self.mc.cat_expr_autoderefd(expr, adj.autoderefs) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 773u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
let cmt_refd =
self.walk_autoref(expr, cmt_derefd, adj.autoref);
if adj.unsize.is_some() {
self.delegate_consume(expr.id, expr.span, cmt_refd);
}
}
/// Walks the autoref `opt_autoref` applied to the autoderef'd
/// `expr`. `cmt_derefd` is the mem-categorized form of `expr`
/// after all relevant autoderefs have occurred. Because AutoRefs
/// can be recursive, this function is recursive: it first walks
/// deeply all the way down the autoref chain, and then processes
/// the autorefs on the way out. At each point, it returns the
/// `cmt` for the rvalue that will be produced by introduced an
/// autoref.
fn walk_autoref(&mut self, expr: &hir::Expr,
cmt_base: mc::cmt<'tcx>,
opt_autoref: Option<adjustment::AutoRef<'tcx>>)
-> mc::cmt<'tcx> {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 799u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_autoref(expr.id=",
" cmt_derefd=",
" opt_autoref=",
")"];
__STATIC_FMTSTR
},
&match (&expr.id,
&cmt_base,
&opt_autoref)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Debug::fmt)],
}))
}
}
};
let cmt_base_ty = cmt_base.ty;
let autoref =
match opt_autoref {
Some(ref autoref) => autoref,
None => { return cmt_base; }
};
match *autoref {
adjustment::AutoPtr(r, m) => {
self.delegate.borrow(expr.id, expr.span, cmt_base, *r,
ty::BorrowKind::from_mutbl(m),
AutoRef);
}
adjustment::AutoUnsafe(m) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 825u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_autoref: expr.id=",
" cmt_base="];
__STATIC_FMTSTR
},
&match (&expr.id,
&cmt_base)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
let r =
ty::ReScope(self.tcx().region_maps.node_extent(expr.id));
self.delegate.borrow(expr.id, expr.span, cmt_base, r,
ty::BorrowKind::from_mutbl(m),
AutoUnsafe);
}
}
let adj_ty =
cmt_base_ty.adjust_for_autoref(self.tcx(), opt_autoref);
self.mc.cat_rvalue_node(expr.id, expr.span, adj_ty)
}
fn walk_overloaded_operator(&mut self, expr: &hir::Expr,
receiver: &hir::Expr,
rhs: Vec<&hir::Expr>,
pass_args: PassArgs) -> bool {
if !self.typer.is_method_call(expr.id) { return false; }
match pass_args {
PassArgs::ByValue => {
self.consume_expr(receiver);
{
let result =
match ::std::iter::IntoIterator::into_iter(&rhs)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(&arg)
=> {
self.consume_expr(arg);
}
::std::option::Option::None =>
break ,
}
},
};
result
}
return true;
}
PassArgs::ByRef => { }
}
self.walk_expr(receiver);
let r =
ty::ReScope(self.tcx().region_maps.node_extent(expr.id));
let bk = ty::ImmBorrow;
{
let result =
match ::std::iter::IntoIterator::into_iter(&rhs) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(&arg) => {
self.borrow_expr(arg, r, bk,
OverloadedOperator);
}
::std::option::Option::None => break ,
}
},
};
result
}
return true;
}
fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>,
arm: &hir::Arm) -> TrackMatchMode {
let mut mode = Unknown;
{
let result =
match ::std::iter::IntoIterator::into_iter(&arm.pats)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(pat) => {
self.determine_pat_move_mode(discr_cmt.clone(),
&**pat,
&mut mode);
}
::std::option::Option::None => break ,
}
},
};
result
}
mode
}
fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm,
mode: MatchMode) {
{
let result =
match ::std::iter::IntoIterator::into_iter(&arm.pats)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(pat) => {
self.walk_pat(discr_cmt.clone(),
&**pat, mode);
}
::std::option::Option::None => break ,
}
},
};
result
}
match arm.guard {
Some(ref guard) => { self.consume_expr(&**guard); }
_ => (),
}
self.consume_expr(&*arm.body);
}
/// Walks a pat that occurs in isolation (i.e. top-level of fn
/// arg or let binding. *Not* a match arm or nested pat.)
fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>,
pat: &hir::Pat) {
let mut mode = Unknown;
self.determine_pat_move_mode(cmt_discr.clone(), pat,
&mut mode);
let mode = mode.match_mode();
self.walk_pat(cmt_discr, pat, mode);
}
/// Identifies any bindings within `pat` and accumulates within
/// `mode` whether the overall pattern/match structure is a move,
/// copy, or borrow.
fn determine_pat_move_mode(&mut self, cmt_discr: mc::cmt<'tcx>,
pat: &hir::Pat,
mode: &mut TrackMatchMode) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 932u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["determine_pat_move_mode cmt_discr=",
" pat="];
__STATIC_FMTSTR
},
&match (&cmt_discr,
&pat)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
match self.mc.cat_pattern(cmt_discr, pat,
|_mc, cmt_pat, pat| {
let tcx = self.tcx();
let def_map = &self.tcx().def_map;
if pat_util::pat_is_binding(&def_map.borrow(),
pat) {
match pat.node {
hir::PatIdent(hir::BindByRef(_),
_, _) =>
mode.lub(BorrowingMatch),
hir::PatIdent(hir::BindByValue(_),
_, _) => {
match copy_or_move(self.typer,
&cmt_pat,
PatBindingMove)
{
Copy =>
mode.lub(CopyingMatch),
Move(_) =>
mode.lub(MovingMatch),
}
}
_ => {
tcx.sess.span_bug(pat.span,
"binding pattern not an identifier");
}
}
} }) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 934u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
}
/// The core driver for walking a pattern; `match_mode` must be
/// established up front, e.g. via `determine_pat_move_mode` (see
/// also `walk_irrefutable_pat` for patterns that stand alone).
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat,
match_mode: MatchMode) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 964u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_pat cmt_discr=",
" pat="];
__STATIC_FMTSTR
},
&match (&cmt_discr,
&pat)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
let mc = &self.mc;
let typer = self.typer;
let def_map = &self.tcx().def_map;
let delegate = &mut self.delegate;
match mc.cat_pattern(cmt_discr.clone(), pat,
|mc, cmt_pat, pat| {
if pat_util::pat_is_binding(&def_map.borrow(),
pat) {
let tcx = typer.tcx;
if false {
{
static LOC:
::log::LogLocation =
::log::LogLocation{line:
971u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG
|| false) &&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["binding cmt_pat=",
" pat=",
" match_mode="];
__STATIC_FMTSTR
},
&match (&cmt_pat,
&pat,
&match_mode)
{
(__arg0,
__arg1,
__arg2)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg2,
::std::fmt::Debug::fmt)],
}))
}
}
};
let pat_ty =
match typer.node_ty(pat.id) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
971u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl !=
::log::DEBUG
||
false)
&&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
let def =
def_map.borrow().get(&pat.id).unwrap().full_def();
match mc.cat_def(pat.id, pat.span,
pat_ty, def) {
Ok(binding_cmt) => {
delegate.mutate(pat.id,
pat.span,
binding_cmt,
Init);
}
Err(_) => { }
}
match pat.node {
hir::PatIdent(hir::BindByRef(m),
_, _) => {
match pat_ty.sty {
ty::TyRef(&r, _) => {
let bk =
ty::BorrowKind::from_mutbl(m);
delegate.borrow(pat.id,
pat.span,
cmt_pat,
r,
bk,
RefBinding);
}
_ => (),
}
}
hir::PatIdent(hir::BindByValue(_),
_, _) => {
let mode =
copy_or_move(typer,
&cmt_pat,
PatBindingMove);
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
971u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl = lvl;
(lvl !=
::log::DEBUG
|| false)
&&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_pat binding consuming pat"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
delegate.consume_pat(pat,
cmt_pat,
mode);
}
_ => {
tcx.sess.span_bug(pat.span,
"binding pattern not an identifier");
}
}
} else {
match pat.node {
hir::PatVec(_,
Some(ref slice_pat),
_) => {
let (slice_cmt, slice_mutbl,
slice_r) =
match mc.cat_slice_pattern(cmt_pat,
&**slice_pat)
{
Ok(v) => v,
Err(()) => {
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
971u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl
!=
::log::DEBUG
||
false)
&&
lvl
<=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
let slice_bk =
ty::BorrowKind::from_mutbl(slice_mutbl);
delegate.borrow(pat.id,
pat.span,
slice_cmt,
slice_r,
slice_bk,
RefBinding);
}
_ => { }
}
} }) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 971u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
match mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
let def_map = def_map.borrow();
let tcx = typer.tcx;
match pat.node {
hir::PatEnum(_, _) |
hir::PatQPath(..) |
hir::PatIdent(_, _, None) |
hir::PatStruct(..) => {
match def_map.get(&pat.id).map(|d|
d.full_def())
{
None => { }
Some(def::DefVariant(enum_did,
variant_did,
_is_struct))
=> {
let downcast_cmt =
if tcx.lookup_adt_def(enum_did).is_univariant()
{
cmt_pat
} else {
let cmt_pat_ty =
cmt_pat.ty;
mc.cat_downcast(pat,
cmt_pat,
cmt_pat_ty,
variant_did)
};
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
1058u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl !=
::log::DEBUG
||
false)
&&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["variant downcast_cmt=",
" pat="];
__STATIC_FMTSTR
},
&match (&downcast_cmt,
&pat)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
delegate.matched_pat(pat,
downcast_cmt,
match_mode);
}
Some(def::DefStruct(..)) |
Some(def::DefTy(_, false)) =>
{
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
1058u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl !=
::log::DEBUG
||
false)
&&
lvl <=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["struct cmt_pat=",
" pat="];
__STATIC_FMTSTR
},
&match (&cmt_pat,
&pat)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
delegate.matched_pat(pat,
cmt_pat,
match_mode);
}
Some(def::DefConst(..)) |
Some(def::DefAssociatedConst(..))
| Some(def::DefLocal(..)) =>
{
}
Some(def@def::DefTy(_, true))
=> {
if !tcx.sess.has_errors()
{
let msg =
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["Pattern has unexpected type: ",
" and type "];
__STATIC_FMTSTR
},
&match (&def,
&cmt_pat.ty)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}));
tcx.sess.span_bug(pat.span,
&msg)
}
}
Some(def) => {
if !tcx.sess.has_errors()
{
let msg =
::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["Pattern has unexpected def: ",
" and type "];
__STATIC_FMTSTR
},
&match (&def,
&cmt_pat.ty)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}));
tcx.sess.span_bug(pat.span,
&msg[..])
}
}
}
}
hir::PatIdent(_, _, Some(_)) => { }
hir::PatWild | hir::PatTup(..) |
hir::PatBox(..) | hir::PatRegion(..)
| hir::PatLit(..) | hir::PatRange(..)
| hir::PatVec(..) => {
}
} }) {
Ok(v) => v,
Err(()) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 1058u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
}
fn walk_captures(&mut self, closure_expr: &hir::Expr) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 1157u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["walk_captures(",
")"];
__STATIC_FMTSTR
},
&match (&closure_expr,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}))
}
}
};
self.tcx().with_freevars(closure_expr.id, |freevars| {
{
let result =
match ::std::iter::IntoIterator::into_iter(freevars)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(freevar)
=> {
let id_var =
freevar.def.var_id();
let upvar_id =
ty::UpvarId{var_id:
id_var,
closure_expr_id:
closure_expr.id,};
let upvar_capture =
self.typer.upvar_capture(upvar_id).unwrap();
let cmt_var =
match self.cat_captured_var(closure_expr.id,
closure_expr.span,
freevar.def)
{
Ok(v)
=> v,
Err(())
=> {
if false
{
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
1165u32,
file:
"src/librustc/middle/expr_use_visitor.rs",
module_path:
"rustc::middle::expr_use_visitor",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl
!=
::log::DEBUG
||
false)
&&
lvl
<=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::expr_use_visitor")
}
{
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mc reported err"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
}
}
};
return
}
};
match upvar_capture
{
ty::UpvarCapture::ByValue
=> {
let mode =
copy_or_move(self.typer,
&cmt_var,
CaptureMove);
self.delegate.consume(closure_expr.id,
freevar.span,
cmt_var,
mode);
}
ty::UpvarCapture::ByRef(upvar_borrow)
=> {
self.delegate.borrow(closure_expr.id,
closure_expr.span,
cmt_var,
upvar_borrow.region,
upvar_borrow.kind,
ClosureCapture(freevar.span));
}
}
}
::std::option::Option::None
=> break ,
}
},
};
result
} });
}
fn cat_captured_var(&mut self, closure_id: ast::NodeId,
closure_span: Span, upvar_def: def::Def)
-> mc::McResult<mc::cmt<'tcx>> {
let var_id = upvar_def.var_id();
let var_ty =
match self.typer.node_ty(var_id) {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def)
}
}
fn copy_or_move<'a,
'tcx>(typer: &infer::InferCtxt<'a, 'tcx>,
cmt: &mc::cmt<'tcx>, move_reason: MoveReason)
-> ConsumeMode {
if typer.type_moves_by_default(cmt.ty, cmt.span) {
Move(move_reason)
} else { Copy }
}
}
pub mod cfg {
//! Module that constructs a control-flow graph representing an item.
//! Uses `Graph` as the underlying representation.
#[prelude_import]
use std::prelude::v1::*;
use rustc_data_structures::graph;
use middle::ty;
use syntax::ast;
use rustc_front::hir;
mod construct {
#[prelude_import]
use std::prelude::v1::*;
use rustc_data_structures::graph;
use middle::cfg::*;
use middle::def;
use middle::pat_util;
use middle::ty;
use syntax::ast;
use syntax::ptr::P;
use rustc_front::hir;
struct CFGBuilder<'a, 'tcx:'a> {
tcx: &'a ty::ctxt<'tcx>,
graph: CFGGraph,
fn_exit: CFGIndex,
loop_scopes: Vec<LoopScope>,
}
struct LoopScope {
loop_id: ast::NodeId,
continue_index: CFGIndex,
break_index: CFGIndex,
}
#[automatically_derived]
impl ::std::clone::Clone for LoopScope {
#[inline]
fn clone(&self) -> LoopScope {
match *self {
LoopScope {
loop_id: ref __self_0_0,
continue_index: ref __self_0_1,
break_index: ref __self_0_2 } =>
LoopScope{loop_id:
::std::clone::Clone::clone(&(*__self_0_0)),
continue_index:
::std::clone::Clone::clone(&(*__self_0_1)),
break_index:
::std::clone::Clone::clone(&(*__self_0_2)),},
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for LoopScope { }
pub fn construct(tcx: &ty::ctxt, blk: &hir::Block) -> CFG {
let mut graph = graph::Graph::new();
let entry = graph.add_node(CFGNodeData::Entry);
let fn_exit = graph.add_node(CFGNodeData::Exit);
let block_exit;
let mut cfg_builder =
CFGBuilder{graph: graph,
fn_exit: fn_exit,
tcx: tcx,
loop_scopes: Vec::new(),};
block_exit = cfg_builder.block(blk, entry);
cfg_builder.add_contained_edge(block_exit, fn_exit);
let CFGBuilder { graph, .. } = cfg_builder;
CFG{graph: graph, entry: entry, exit: fn_exit,}
}
impl <'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn block(&mut self, blk: &hir::Block, pred: CFGIndex)
-> CFGIndex {
let mut stmts_exit = pred;
{
let result =
match ::std::iter::IntoIterator::into_iter(&blk.stmts)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(stmt) => {
stmts_exit =
self.stmt(&**stmt,
stmts_exit);
}
::std::option::Option::None => break ,
}
},
};
result
}
let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
self.add_ast_node(blk.id, &[expr_exit])
}
fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex)
-> CFGIndex {
match stmt.node {
hir::StmtDecl(ref decl, id) => {
let exit = self.decl(&**decl, pred);
self.add_ast_node(id, &[exit])
}
hir::StmtExpr(ref expr, id) |
hir::StmtSemi(ref expr, id) => {
let exit = self.expr(&**expr, pred);
self.add_ast_node(id, &[exit])
}
}
}
fn decl(&mut self, decl: &hir::Decl, pred: CFGIndex)
-> CFGIndex {
match decl.node {
hir::DeclLocal(ref local) => {
let init_exit = self.opt_expr(&local.init, pred);
self.pat(&*local.pat, init_exit)
}
hir::DeclItem(_) => { pred }
}
}
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex)
-> CFGIndex {
match pat.node {
hir::PatIdent(_, _, None) | hir::PatEnum(_, None) |
hir::PatQPath(..) | hir::PatLit(..) |
hir::PatRange(..) | hir::PatWild => {
self.add_ast_node(pat.id, &[pred])
}
hir::PatBox(ref subpat) |
hir::PatRegion(ref subpat, _) |
hir::PatIdent(_, _, Some(ref subpat)) => {
let subpat_exit = self.pat(&**subpat, pred);
self.add_ast_node(pat.id, &[subpat_exit])
}
hir::PatEnum(_, Some(ref subpats)) |
hir::PatTup(ref subpats) => {
let pats_exit =
self.pats_all(subpats.iter(), pred);
self.add_ast_node(pat.id, &[pats_exit])
}
hir::PatStruct(_, ref subpats, _) => {
let pats_exit =
self.pats_all(subpats.iter().map(|f|
&f.node.pat),
pred);
self.add_ast_node(pat.id, &[pats_exit])
}
hir::PatVec(ref pre, ref vec, ref post) => {
let pre_exit = self.pats_all(pre.iter(), pred);
let vec_exit =
self.pats_all(vec.iter(), pre_exit);
let post_exit =
self.pats_all(post.iter(), vec_exit);
self.add_ast_node(pat.id, &[post_exit])
}
}
}
fn pats_all<'b, I: Iterator<Item =
&'b P<hir::Pat>>>(&mut self, pats: I,
pred: CFGIndex) -> CFGIndex {
//! Handles case where all of the patterns must match.
pats.fold(pred, |pred, pat| self.pat(&**pat, pred))
}
fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex)
-> CFGIndex {
match expr.node {
hir::ExprBlock(ref blk) => {
let blk_exit = self.block(&**blk, pred);
self.add_ast_node(expr.id, &[blk_exit])
}
hir::ExprIf(ref cond, ref then, None) => {
let cond_exit = self.expr(&**cond, pred);
let then_exit = self.block(&**then, cond_exit);
self.add_ast_node(expr.id,
&[cond_exit, then_exit])
}
hir::ExprIf(ref cond, ref then, Some(ref otherwise))
=> {
let cond_exit = self.expr(&**cond, pred);
let then_exit = self.block(&**then, cond_exit);
let else_exit =
self.expr(&**otherwise, cond_exit);
self.add_ast_node(expr.id,
&[then_exit, else_exit])
}
hir::ExprWhile(ref cond, ref body, _) => {
let loopback = self.add_dummy_node(&[pred]);
let cond_exit = self.expr(&**cond, loopback);
let expr_exit =
self.add_ast_node(expr.id, &[cond_exit]);
self.loop_scopes.push(LoopScope{loop_id: expr.id,
continue_index:
loopback,
break_index:
expr_exit,});
let body_exit = self.block(&**body, cond_exit);
self.add_contained_edge(body_exit, loopback);
self.loop_scopes.pop();
expr_exit
}
hir::ExprLoop(ref body, _) => {
let loopback = self.add_dummy_node(&[pred]);
let expr_exit = self.add_ast_node(expr.id, &[]);
self.loop_scopes.push(LoopScope{loop_id: expr.id,
continue_index:
loopback,
break_index:
expr_exit,});
let body_exit = self.block(&**body, loopback);
self.add_contained_edge(body_exit, loopback);
self.loop_scopes.pop();
expr_exit
}
hir::ExprMatch(ref discr, ref arms, _) => {
self.match_(expr.id, &discr, &arms, pred)
}
hir::ExprBinary(op, ref l, ref r) if
::rustc_front::util::lazy_binop(op.node) => {
let l_exit = self.expr(&**l, pred);
let r_exit = self.expr(&**r, l_exit);
self.add_ast_node(expr.id, &[l_exit, r_exit])
}
hir::ExprRet(ref v) => {
let v_exit = self.opt_expr(v, pred);
let b = self.add_ast_node(expr.id, &[v_exit]);
self.add_returning_edge(expr, b);
self.add_unreachable_node()
}
hir::ExprBreak(label) => {
let loop_scope =
self.find_scope(expr,
label.map(|l| l.node.name));
let b = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, b, loop_scope,
loop_scope.break_index);
self.add_unreachable_node()
}
hir::ExprAgain(label) => {
let loop_scope =
self.find_scope(expr,
label.map(|l| l.node.name));
let a = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, a, loop_scope,
loop_scope.continue_index);
self.add_unreachable_node()
}
hir::ExprVec(ref elems) => {
self.straightline(expr, pred,
elems.iter().map(|e| &**e))
}
hir::ExprCall(ref func, ref args) => {
self.call(expr, pred, &**func,
args.iter().map(|e| &**e))
}
hir::ExprMethodCall(_, _, ref args) => {
self.call(expr, pred, &*args[0],
args[1..].iter().map(|e| &**e))
}
hir::ExprIndex(ref l, ref r) |
hir::ExprBinary(_, ref l, ref r) if
self.tcx.is_method_call(expr.id) => {
self.call(expr, pred, &**l,
Some(&**r).into_iter())
}
hir::ExprRange(ref start, ref end) => {
let fields =
start.as_ref().map(|e|
&**e).into_iter().chain(end.as_ref().map(|e|
&**e));
self.straightline(expr, pred, fields)
}
hir::ExprUnary(_, ref e) if
self.tcx.is_method_call(expr.id) => {
self.call(expr, pred, &**e,
None::<hir::Expr>.iter())
}
hir::ExprTup(ref exprs) => {
self.straightline(expr, pred,
exprs.iter().map(|e| &**e))
}
hir::ExprStruct(_, ref fields, ref base) => {
let field_cfg =
self.straightline(expr, pred,
fields.iter().map(|f|
&*f.expr));
self.opt_expr(base, field_cfg)
}
hir::ExprRepeat(ref elem, ref count) => {
self.straightline(expr, pred,
[elem,
count].iter().map(|&e| &**e))
}
hir::ExprAssign(ref l, ref r) |
hir::ExprAssignOp(_, ref l, ref r) => {
self.straightline(expr, pred,
[r, l].iter().map(|&e| &**e))
}
hir::ExprIndex(ref l, ref r) |
hir::ExprBinary(_, ref l, ref r) => {
self.straightline(expr, pred,
[l, r].iter().map(|&e| &**e))
}
hir::ExprBox(ref e) | hir::ExprAddrOf(_, ref e) |
hir::ExprCast(ref e, _) | hir::ExprUnary(_, ref e) |
hir::ExprField(ref e, _) | hir::ExprTupField(ref e, _)
=> {
self.straightline(expr, pred,
Some(&**e).into_iter())
}
hir::ExprInlineAsm(ref inline_asm) => {
let inputs = inline_asm.inputs.iter();
let outputs = inline_asm.outputs.iter();
let post_inputs =
self.exprs(inputs.map(|a| {
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
365u32,
file:
"src/librustc/middle/cfg/construct.rs",
module_path:
"rustc::middle::cfg::construct",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl !=
::log::DEBUG
||
false)
&&
lvl
<=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::cfg::construct")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["cfg::construct InlineAsm id:",
" input:"];
__STATIC_FMTSTR
},
&match (&expr.id,
&a)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
let &(_, ref expr) = a;
&**expr }), pred);
let post_outputs =
self.exprs(outputs.map(|a| {
if false {
{
static LOC:
::log::LogLocation
=
::log::LogLocation{line:
370u32,
file:
"src/librustc/middle/cfg/construct.rs",
module_path:
"rustc::middle::cfg::construct",};
let lvl =
::log::DEBUG;
if {
let lvl =
lvl;
(lvl !=
::log::DEBUG
||
false)
&&
lvl
<=
::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::cfg::construct")
} {
::log::log(lvl,
&LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["cfg::construct InlineAsm id:",
" output:"];
__STATIC_FMTSTR
},
&match (&expr.id,
&a)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}))
}
}
};
let &(_, ref expr, _) =
a; &**expr }),
post_inputs);
self.add_ast_node(expr.id, &[post_outputs])
}
hir::ExprClosure(..) | hir::ExprLit(..) |
hir::ExprPath(..) => {
self.straightline(expr, pred,
None::<hir::Expr>.iter())
}
}
}
fn call<'b, I: Iterator<Item =
&'b hir::Expr>>(&mut self, call_expr: &hir::Expr,
pred: CFGIndex,
func_or_rcvr: &hir::Expr, args: I)
-> CFGIndex {
let method_call = ty::MethodCall::expr(call_expr.id);
let fn_ty =
match self.tcx.tables.borrow().method_map.get(&method_call)
{
Some(method) => method.ty,
None => self.tcx.expr_ty_adjusted(func_or_rcvr),
};
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
let ret =
self.straightline(call_expr, func_or_rcvr_exit, args);
if fn_ty.fn_ret().diverges() {
self.add_unreachable_node()
} else { ret }
}
fn exprs<'b, I: Iterator<Item =
&'b hir::Expr>>(&mut self, exprs: I, pred: CFGIndex)
-> CFGIndex {
//! Constructs graph for `exprs` evaluated in order
exprs.fold(pred, |p, e| self.expr(e, p))
}
fn opt_expr(&mut self, opt_expr: &Option<P<hir::Expr>>,
pred: CFGIndex) -> CFGIndex {
//! Constructs graph for `opt_expr` evaluated, if Some
opt_expr.iter().fold(pred, |p, e| self.expr(&**e, p))
}
fn straightline<'b, I: Iterator<Item =
&'b hir::Expr>>(&mut self, expr: &hir::Expr,
pred: CFGIndex, subexprs: I)
-> CFGIndex {
//! Handles case of an expression that evaluates `subexprs` in order
let subexprs_exit = self.exprs(subexprs, pred);
self.add_ast_node(expr.id, &[subexprs_exit])
}
fn match_(&mut self, id: ast::NodeId, discr: &hir::Expr,
arms: &[hir::Arm], pred: CFGIndex) -> CFGIndex {
let discr_exit = self.expr(discr, pred);
let expr_exit = self.add_ast_node(id, &[]);
let mut prev_guards = Vec::new();
let mut prev_has_bindings = false;
{
let result =
match ::std::iter::IntoIterator::into_iter(arms) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(arm) => {
let arm_exit =
self.add_dummy_node(&[]);
{
let result =
match ::std::iter::IntoIterator::into_iter(&arm.pats)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(pat)
=> {
let mut pat_exit =
self.pat(&**pat,
discr_exit);
match arm.guard
{
Some(ref guard)
=> {
let guard_start =
self.add_dummy_node(&[pat_exit]);
let guard_exit =
self.expr(&**guard,
guard_start);
let this_has_bindings =
pat_util::pat_contains_bindings_or_wild(&self.tcx.def_map.borrow(),
&**pat);
if prev_has_bindings
||
this_has_bindings
{
loop
{
match prev_guards.pop()
{
Some(prev)
=>
{
self.add_contained_edge(prev,
guard_start);
}
_
=>
break
,
}
}
}
prev_has_bindings
=
this_has_bindings;
prev_guards.push(guard_exit);
pat_exit
=
guard_exit;
}
_ =>
(),
}
self.add_contained_edge(pat_exit,
arm_exit);
}
::std::option::Option::None
=> break ,
}
},
};
result
}
let body_exit =
self.expr(&arm.body,
arm_exit);
self.add_contained_edge(body_exit,
expr_exit);
}
::std::option::Option::None => break ,
}
},
};
result
}
expr_exit
}
fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex {
self.add_node(CFGNodeData::Dummy, preds)
}
fn add_ast_node(&mut self, id: ast::NodeId,
preds: &[CFGIndex]) -> CFGIndex {
if !(id != ast::DUMMY_NODE_ID) {
{
::std::rt::begin_unwind("assertion failed: id != ast::DUMMY_NODE_ID",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/cfg/construct.rs",
536u32);
&_FILE_LINE
})
}
};
self.add_node(CFGNodeData::AST(id), preds)
}
fn add_unreachable_node(&mut self) -> CFGIndex {
self.add_node(CFGNodeData::Unreachable, &[])
}
fn add_node(&mut self, data: CFGNodeData, preds: &[CFGIndex])
-> CFGIndex {
let node = self.graph.add_node(data);
{
let result =
match ::std::iter::IntoIterator::into_iter(preds)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(&pred) =>
{
self.add_contained_edge(pred,
node);
}
::std::option::Option::None => break ,
}
},
};
result
}
node
}
fn add_contained_edge(&mut self, source: CFGIndex,
target: CFGIndex) {
let data =
CFGEdgeData{exiting_scopes:
<[_]>::into_vec(::std::boxed::Box::new([])),};
self.graph.add_edge(source, target, data);
}
fn add_exiting_edge(&mut self, from_expr: &hir::Expr,
from_index: CFGIndex, to_loop: LoopScope,
to_index: CFGIndex) {
let mut data =
CFGEdgeData{exiting_scopes:
<[_]>::into_vec(::std::boxed::Box::new([])),};
let mut scope =
self.tcx.region_maps.node_extent(from_expr.id);
let target_scope =
self.tcx.region_maps.node_extent(to_loop.loop_id);
while scope != target_scope {
data.exiting_scopes.push(scope.node_id(&self.tcx.region_maps));
scope = self.tcx.region_maps.encl_scope(scope);
}
self.graph.add_edge(from_index, to_index, data);
}
fn add_returning_edge(&mut self, _from_expr: &hir::Expr,
from_index: CFGIndex) {
let mut data =
CFGEdgeData{exiting_scopes:
<[_]>::into_vec(::std::boxed::Box::new([])),};
{
let result =
match ::std::iter::IntoIterator::into_iter(self.loop_scopes.iter().rev())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(&LoopScope {
loop_id: id,
.. }) => {
data.exiting_scopes.push(id);
}
::std::option::Option::None => break ,
}
},
};
result
}
self.graph.add_edge(from_index, self.fn_exit, data);
}
fn find_scope(&self, expr: &hir::Expr,
label: Option<ast::Name>) -> LoopScope {
if label.is_none() {
return *self.loop_scopes.last().unwrap();
}
match self.tcx.def_map.borrow().get(&expr.id).map(|d|
d.full_def())
{
Some(def::DefLabel(loop_id)) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(&self.loop_scopes)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(l)
=> {
if l.loop_id == loop_id {
return *l;
}
}
::std::option::Option::None =>
break ,
}
},
};
result
}
self.tcx.sess.span_bug(expr.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["no loop scope for id "];
__STATIC_FMTSTR
},
&match (&loop_id,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})));
}
r => {
self.tcx.sess.span_bug(expr.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["bad entry `",
"` in def_map for label"];
__STATIC_FMTSTR
},
&match (&r,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
})));
}
}
}
}
}
pub mod graphviz {
#[prelude_import]
use std::prelude::v1::*;
/// This module provides linkage between rustc::middle::graph and
/// libgraphviz traits.
use std::borrow::IntoCow;
use graphviz as dot;
use syntax::ast;
use front::map as ast_map;
use middle::cfg;
pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
pub type Edge<'a> = &'a cfg::CFGEdge;
pub struct LabelledCFG<'a, 'ast:'a> {
pub ast_map: &'a ast_map::Map<'ast>,
pub cfg: &'a cfg::CFG,
pub name: String,
/// `labelled_edges` controls whether we emit labels on the edges
pub labelled_edges: bool,
}
fn replace_newline_with_backslash_l(s: String) -> String {
if s.contains("\n") {
let mut s = s.replace("\n", "\\l");
let mut last_two: Vec<_> =
s.chars().rev().take(2).collect();
last_two.reverse();
if last_two != ['\\', 'l'] { s.push_str("\\l"); }
s
} else { s }
}
impl <'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for
LabelledCFG<'a, 'ast> {
fn graph_id(&'a self) -> dot::Id<'a> {
dot::Id::new(&self.name[..]).unwrap()
}
fn node_id(&'a self, &(i, _): &Node<'a>) -> dot::Id<'a> {
dot::Id::new(::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["N"];
__STATIC_FMTSTR
},
&match (&i.node_id(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}))).unwrap()
}
fn node_label(&'a self, &(i, n): &Node<'a>)
-> dot::LabelText<'a> {
if i == self.cfg.entry {
dot::LabelText::LabelStr("entry".into_cow())
} else if i == self.cfg.exit {
dot::LabelText::LabelStr("exit".into_cow())
} else if n.data.id() == ast::DUMMY_NODE_ID {
dot::LabelText::LabelStr("(dummy_node)".into_cow())
} else {
let s = self.ast_map.node_to_string(n.data.id());
let s = replace_newline_with_backslash_l(s);
dot::LabelText::EscStr(s.into_cow())
}
}
fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> {
let mut label = String::new();
if !self.labelled_edges {
return dot::LabelText::EscStr(label.into_cow());
}
let mut put_one = false;
{
let result =
match ::std::iter::IntoIterator::into_iter(e.data.exiting_scopes.iter().enumerate())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some((i,
&node_id))
=> {
if put_one {
label.push_str(",\\l");
} else { put_one = true; }
let s =
self.ast_map.node_to_string(node_id);
let s =
replace_newline_with_backslash_l(s);
label.push_str(&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["exiting scope_",
" "];
__STATIC_FMTSTR
},
&match (&i,
&&s[..])
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
})));
}
::std::option::Option::None => break ,
}
},
};
result
}
dot::LabelText::EscStr(label.into_cow())
}
}
impl <'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG
{
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
let mut v = Vec::new();
self.graph.each_node(|i, nd| { v.push((i, nd)); true });
v.into_cow()
}
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
self.graph.all_edges().iter().collect()
}
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> {
let i = edge.source();
(i, self.graph.node(i))
}
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> {
let i = edge.target();
(i, self.graph.node(i))
}
}
impl <'a, 'ast> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for
LabelledCFG<'a, 'ast> {
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
self.cfg.nodes()
}
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
self.cfg.edges()
}
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> {
self.cfg.source(edge)
}
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> {
self.cfg.target(edge)
}
}
}
pub struct CFG {
pub graph: CFGGraph,
pub entry: CFGIndex,
pub exit: CFGIndex,
}
pub enum CFGNodeData {
AST(ast::NodeId),
Entry,
Exit,
Dummy,
Unreachable,
}
#[automatically_derived]
impl ::std::cmp::PartialEq for CFGNodeData {
#[inline]
fn eq(&self, __arg_0: &CFGNodeData) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&CFGNodeData::AST(ref __self_0),
&CFGNodeData::AST(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&CFGNodeData::Entry, &CFGNodeData::Entry) =>
true,
(&CFGNodeData::Exit, &CFGNodeData::Exit) => true,
(&CFGNodeData::Dummy, &CFGNodeData::Dummy) =>
true,
(&CFGNodeData::Unreachable,
&CFGNodeData::Unreachable) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &CFGNodeData) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&CFGNodeData::AST(ref __self_0),
&CFGNodeData::AST(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&CFGNodeData::Entry, &CFGNodeData::Entry) =>
false,
(&CFGNodeData::Exit, &CFGNodeData::Exit) => false,
(&CFGNodeData::Dummy, &CFGNodeData::Dummy) =>
false,
(&CFGNodeData::Unreachable,
&CFGNodeData::Unreachable) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::fmt::Debug for CFGNodeData {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&CFGNodeData::AST(ref __self_0),) =>
__arg_0.debug_tuple("AST").field(&&(*__self_0)).finish(),
(&CFGNodeData::Entry,) =>
__arg_0.debug_tuple("Entry").finish(),
(&CFGNodeData::Exit,) =>
__arg_0.debug_tuple("Exit").finish(),
(&CFGNodeData::Dummy,) =>
__arg_0.debug_tuple("Dummy").finish(),
(&CFGNodeData::Unreachable,) =>
__arg_0.debug_tuple("Unreachable").finish(),
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for CFGNodeData {
#[inline]
fn clone(&self) -> CFGNodeData {
match (&*self,) {
(&CFGNodeData::AST(ref __self_0),) =>
CFGNodeData::AST(::std::clone::Clone::clone(&(*__self_0))),
(&CFGNodeData::Entry,) => CFGNodeData::Entry,
(&CFGNodeData::Exit,) => CFGNodeData::Exit,
(&CFGNodeData::Dummy,) => CFGNodeData::Dummy,
(&CFGNodeData::Unreachable,) => CFGNodeData::Unreachable,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for CFGNodeData { }
impl CFGNodeData {
pub fn id(&self) -> ast::NodeId {
match *self {
CFGNodeData::AST(id) => { id }
_ => { ast::DUMMY_NODE_ID }
}
}
}
pub struct CFGEdgeData {
pub exiting_scopes: Vec<ast::NodeId>,
}
#[automatically_derived]
impl ::std::fmt::Debug for CFGEdgeData {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match *self {
CFGEdgeData { exiting_scopes: ref __self_0_0 } =>
__arg_0.debug_struct("CFGEdgeData").field("exiting_scopes",
&&(*__self_0_0)).finish(),
}
}
}
pub type CFGIndex = graph::NodeIndex;
pub type CFGGraph = graph::Graph<CFGNodeData, CFGEdgeData>;
pub type CFGNode = graph::Node<CFGNodeData>;
pub type CFGEdge = graph::Edge<CFGEdgeData>;
impl CFG {
pub fn new(tcx: &ty::ctxt, blk: &hir::Block) -> CFG {
construct::construct(tcx, blk)
}
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
self.graph.depth_traverse(self.entry).any(|idx|
self.graph.node_data(idx).id()
== id)
}
}
}
pub mod check_const {
#[prelude_import]
use std::prelude::v1::*;
use middle::ty::cast::{CastKind};
use middle::const_eval;
use middle::const_eval::EvalHint::ExprTypeChecked;
use middle::def;
use middle::def_id::DefId;
use middle::expr_use_visitor as euv;
use middle::infer;
use middle::mem_categorization as mc;
use middle::mem_categorization::Categorization;
use middle::traits;
use middle::ty::{self, Ty};
use util::nodemap::NodeMap;
use rustc_front::hir;
use syntax::ast;
use syntax::codemap::Span;
use syntax::feature_gate::UnstableFeatures;
use rustc_front::intravisit::{self, FnKind, Visitor};
use std::collections::hash_map::Entry;
use std::cmp::Ordering;
pub struct ConstQualif {
bits: u8,
}
#[automatically_derived]
impl ::std::hash::Hash for ConstQualif {
fn hash<__H: ::std::hash::Hasher>(&self, __arg_0: &mut __H)
-> () {
match *self {
ConstQualif { bits: ref __self_0_0 } => {
::std::hash::Hash::hash(&(*__self_0_0), __arg_0);
}
}
}
}
#[automatically_derived]
impl ::std::cmp::Ord for ConstQualif {
#[inline]
fn cmp(&self, __arg_0: &ConstQualif) -> ::std::cmp::Ordering {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } => {
let __test =
::std::cmp::Ord::cmp(&(*__self_0_0),
&(*__self_1_0));
if __test == ::std::cmp::Ordering::Equal {
::std::cmp::Ordering::Equal
} else { __test }
}
},
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialOrd for ConstQualif {
#[inline]
fn partial_cmp(&self, __arg_0: &ConstQualif)
-> ::std::option::Option<::std::cmp::Ordering> {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } => {
let __test =
::std::cmp::PartialOrd::partial_cmp(&(*__self_0_0),
&(*__self_1_0));
if __test ==
::std::option::Option::Some(::std::cmp::Ordering::Equal)
{
::std::option::Option::Some(::std::cmp::Ordering::Equal)
} else { __test }
}
},
}
}
#[inline]
fn lt(&self, __arg_0: &ConstQualif) -> bool {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } =>
(*__self_0_0) < (*__self_1_0) ||
!((*__self_1_0) < (*__self_0_0)) && false,
},
}
}
#[inline]
fn le(&self, __arg_0: &ConstQualif) -> bool {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } =>
(*__self_0_0) < (*__self_1_0) ||
!((*__self_1_0) < (*__self_0_0)) && true,
},
}
}
#[inline]
fn gt(&self, __arg_0: &ConstQualif) -> bool {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } =>
(*__self_0_0) > (*__self_1_0) ||
!((*__self_1_0) > (*__self_0_0)) && false,
},
}
}
#[inline]
fn ge(&self, __arg_0: &ConstQualif) -> bool {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } =>
(*__self_0_0) > (*__self_1_0) ||
!((*__self_1_0) > (*__self_0_0)) && true,
},
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for ConstQualif {
#[inline]
fn clone(&self) -> ConstQualif {
match *self {
ConstQualif { bits: ref __self_0_0 } =>
ConstQualif{bits:
::std::clone::Clone::clone(&(*__self_0_0)),},
}
}
}
#[automatically_derived]
impl ::std::cmp::Eq for ConstQualif {
#[inline]
#[doc(hidden)]
fn assert_receiver_is_total_eq(&self) -> () {
match *self {
ConstQualif { bits: ref __self_0_0 } => {
(*__self_0_0).assert_receiver_is_total_eq();
}
}
}
}
#[automatically_derived]
impl ::std::cmp::PartialEq for ConstQualif {
#[inline]
fn eq(&self, __arg_0: &ConstQualif) -> bool {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } =>
true && (*__self_0_0) == (*__self_1_0),
},
}
}
#[inline]
fn ne(&self, __arg_0: &ConstQualif) -> bool {
match *__arg_0 {
ConstQualif { bits: ref __self_1_0 } =>
match *self {
ConstQualif { bits: ref __self_0_0 } =>
false || (*__self_0_0) != (*__self_1_0),
},
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for ConstQualif { }
#[automatically_derived]
impl ::rustc_serialize::Decodable for ConstQualif {
fn decode<__D: ::rustc_serialize::Decoder>(__arg_0: &mut __D)
-> ::std::result::Result<ConstQualif, __D::Error> {
__arg_0.read_struct("ConstQualif", 1usize, |_d| -> _ {
::std::result::Result::Ok(ConstQualif{bits:
match _d.read_struct_field("bits",
0usize,
::rustc_serialize::Decodable::decode)
{
::std::result::Result::Ok(__try_var)
=>
__try_var,
::std::result::Result::Err(__try_var)
=>
return ::std::result::Result::Err(__try_var),
},})
})
}
}
#[automatically_derived]
impl ::rustc_serialize::Encodable for ConstQualif {
fn encode<__S: ::rustc_serialize::Encoder>(&self,
__arg_0: &mut __S)
-> ::std::result::Result<(), __S::Error> {
match *self {
ConstQualif { bits: ref __self_0_0 } =>
__arg_0.emit_struct("ConstQualif", 1usize, |_e| -> _ {
return _e.emit_struct_field("bits",
0usize,
|_e| -> _
{
(*__self_0_0).encode(_e)
}); }),
}
}
}
impl ConstQualif {
pub const
MUTABLE_MEM:
ConstQualif
=
ConstQualif{bits: 1 << 0,};
pub const
NEEDS_DROP:
ConstQualif
=
ConstQualif{bits: 1 << 1,};
pub const
PREFER_IN_PLACE:
ConstQualif
=
ConstQualif{bits: 1 << 2,};
pub const
NON_ZERO_SIZED:
ConstQualif
=
ConstQualif{bits: 1 << 3,};
pub const
HAS_STATIC_BORROWS:
ConstQualif
=
ConstQualif{bits: 1 << 4,};
pub const
NOT_CONST:
ConstQualif
=
ConstQualif{bits: 1 << 5,};
pub const
NON_STATIC_BORROWS:
ConstQualif
=
ConstQualif{bits:
ConstQualif::MUTABLE_MEM.bits |
ConstQualif::NEEDS_DROP.bits |
ConstQualif::NOT_CONST.bits,};
/// Returns an empty set of flags.
#[inline]
pub fn empty() -> ConstQualif { ConstQualif{bits: 0,} }
/// Returns the set containing all flags.
#[inline]
pub fn all() -> ConstQualif {
ConstQualif{bits:
1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 |
1 << 5 |
ConstQualif::MUTABLE_MEM.bits |
ConstQualif::NEEDS_DROP.bits |
ConstQualif::NOT_CONST.bits,}
}
/// Returns the raw value of the flags currently stored.
#[inline]
pub fn bits(&self) -> u8 { self.bits }
/// Convert from underlying bit representation, unless that
/// representation contains bits that do not correspond to a flag.
#[inline]
pub fn from_bits(bits: u8) -> ::std::option::Option<ConstQualif> {
if (bits & !ConstQualif::all().bits()) != 0 {
::std::option::Option::None
} else {
::std::option::Option::Some(ConstQualif{bits: bits,})
}
}
/// Convert from underlying bit representation, dropping any bits
/// that do not correspond to flags.
#[inline]
pub fn from_bits_truncate(bits: u8) -> ConstQualif {
ConstQualif{bits: bits,} & ConstQualif::all()
}
/// Returns `true` if no flags are currently stored.
#[inline]
pub fn is_empty(&self) -> bool { *self == ConstQualif::empty() }
/// Returns `true` if all flags are currently set.
#[inline]
pub fn is_all(&self) -> bool { *self == ConstQualif::all() }
/// Returns `true` if there are flags common to both `self` and `other`.
#[inline]
pub fn intersects(&self, other: ConstQualif) -> bool {
!(*self & other).is_empty()
}
/// Returns `true` all of the flags in `other` are contained within `self`.
#[inline]
pub fn contains(&self, other: ConstQualif) -> bool {
(*self & other) == other
}
/// Inserts the specified flags in-place.
#[inline]
pub fn insert(&mut self, other: ConstQualif) {
self.bits |= other.bits;
}
/// Removes the specified flags in-place.
#[inline]
pub fn remove(&mut self, other: ConstQualif) {
self.bits &= !other.bits;
}
/// Toggles the specified flags in-place.
#[inline]
pub fn toggle(&mut self, other: ConstQualif) {
self.bits ^= other.bits;
}
}
impl ::std::ops::BitOr for ConstQualif {
type
Output
=
ConstQualif;
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(self, other: ConstQualif) -> ConstQualif {
ConstQualif{bits: self.bits | other.bits,}
}
}
impl ::std::ops::BitXor for ConstQualif {
type
Output
=
ConstQualif;
/// Returns the left flags, but with all the right flags toggled.
#[inline]
fn bitxor(self, other: ConstQualif) -> ConstQualif {
ConstQualif{bits: self.bits ^ other.bits,}
}
}
impl ::std::ops::BitAnd for ConstQualif {
type
Output
=
ConstQualif;
/// Returns the intersection between the two sets of flags.
#[inline]
fn bitand(self, other: ConstQualif) -> ConstQualif {
ConstQualif{bits: self.bits & other.bits,}
}
}
impl ::std::ops::Sub for ConstQualif {
type
Output
=
ConstQualif;
/// Returns the set difference of the two sets of flags.
#[inline]
fn sub(self, other: ConstQualif) -> ConstQualif {
ConstQualif{bits: self.bits & !other.bits,}
}
}
impl ::std::ops::Not for ConstQualif {
type
Output
=
ConstQualif;
/// Returns the complement of this set of flags.
#[inline]
fn not(self) -> ConstQualif {
ConstQualif{bits: !self.bits,} & ConstQualif::all()
}
}
enum Mode { Const, ConstFn, Static, StaticMut, Var, }
#[automatically_derived]
impl ::std::cmp::PartialEq for Mode {
#[inline]
fn eq(&self, __arg_0: &Mode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Mode::Const, &Mode::Const) => true,
(&Mode::ConstFn, &Mode::ConstFn) => true,
(&Mode::Static, &Mode::Static) => true,
(&Mode::StaticMut, &Mode::StaticMut) => true,
(&Mode::Var, &Mode::Var) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &Mode) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Mode::Const, &Mode::Const) => false,
(&Mode::ConstFn, &Mode::ConstFn) => false,
(&Mode::Static, &Mode::Static) => false,
(&Mode::StaticMut, &Mode::StaticMut) => false,
(&Mode::Var, &Mode::Var) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::cmp::Eq for Mode {
#[inline]
#[doc(hidden)]
fn assert_receiver_is_total_eq(&self) -> () {
match (&*self,) {
(&Mode::Const,) => { }
(&Mode::ConstFn,) => { }
(&Mode::Static,) => { }
(&Mode::StaticMut,) => { }
(&Mode::Var,) => { }
}
}
}
#[automatically_derived]
impl ::std::fmt::Debug for Mode {
fn fmt(&self, __arg_0: &mut ::std::fmt::Formatter)
-> ::std::fmt::Result {
match (&*self,) {
(&Mode::Const,) => __arg_0.debug_tuple("Const").finish(),
(&Mode::ConstFn,) =>
__arg_0.debug_tuple("ConstFn").finish(),
(&Mode::Static,) =>
__arg_0.debug_tuple("Static").finish(),
(&Mode::StaticMut,) =>
__arg_0.debug_tuple("StaticMut").finish(),
(&Mode::Var,) => __arg_0.debug_tuple("Var").finish(),
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for Mode {
#[inline]
fn clone(&self) -> Mode {
match (&*self,) {
(&Mode::Const,) => Mode::Const,
(&Mode::ConstFn,) => Mode::ConstFn,
(&Mode::Static,) => Mode::Static,
(&Mode::StaticMut,) => Mode::StaticMut,
(&Mode::Var,) => Mode::Var,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for Mode { }
struct CheckCrateVisitor<'a, 'tcx:'a> {
tcx: &'a ty::ctxt<'tcx>,
mode: Mode,
qualif: ConstQualif,
rvalue_borrows: NodeMap<hir::Mutability>,
}
impl <'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where
F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>) -> R {
let (old_mode, old_qualif) = (self.mode, self.qualif);
self.mode = mode;
self.qualif = ConstQualif::empty();
let r = f(self);
self.mode = old_mode;
self.qualif = old_qualif;
r
}
fn with_euv<'b, F,
R>(&'b mut self, item_id: Option<ast::NodeId>, f: F)
-> R where
F: for<'t>FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) ->
R {
let param_env =
match item_id {
Some(item_id) =>
ty::ParameterEnvironment::for_item(self.tcx, item_id),
None => self.tcx.empty_parameter_environment(),
};
let infcx =
infer::new_infer_ctxt(self.tcx, &self.tcx.tables,
Some(param_env), false);
f(&mut euv::ExprUseVisitor::new(self, &infcx))
}
fn global_expr(&mut self, mode: Mode, expr: &hir::Expr)
-> ConstQualif {
if !(mode != Mode::Var) {
{
::std::rt::begin_unwind("assertion failed: mode != Mode::Var",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/middle/check_const.rs",
132u32);
&_FILE_LINE
})
}
};
match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
Entry::Occupied(entry) => return *entry.get(),
Entry::Vacant(entry) => {
entry.insert(ConstQualif::empty());
}
}
self.with_mode(mode, |this| {
this.with_euv(None,
|euv| euv.consume_expr(expr));
this.visit_expr(expr); this.qualif })
}
fn fn_like(&mut self, fk: FnKind, fd: &hir::FnDecl,
b: &hir::Block, s: Span, fn_id: ast::NodeId)
-> ConstQualif {
match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
Entry::Occupied(entry) => return *entry.get(),
Entry::Vacant(entry) => {
entry.insert(ConstQualif::empty());
}
}
let mode =
match fk {
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _)
=> {
Mode::ConstFn
}
FnKind::Method(_, m, _) => {
if m.constness == hir::Constness::Const {
Mode::ConstFn
} else { Mode::Var }
}
_ => Mode::Var,
};
if mode == Mode::ConstFn {
{
let result =
match ::std::iter::IntoIterator::into_iter(&fd.inputs)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(arg) => {
match arg.pat.node {
hir::PatWild => { }
hir::PatIdent(hir::BindByValue(hir::MutImmutable),
_, None) => {
}
_ => {
{
();
self.tcx.sess.span_err_with_code(arg.pat.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["arguments of constant functions can only be immutable by-value bindings"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0022")
};
}
}
}
::std::option::Option::None => break ,
}
},
};
result
}
}
let qualif =
self.with_mode(mode, |this| {
this.with_euv(Some(fn_id),
|euv| euv.walk_fn(fd, b));
intravisit::walk_fn(this, fk, fd, b, s);
this.qualif });
let qualif =
qualif &
(ConstQualif::NON_ZERO_SIZED |
ConstQualif::PREFER_IN_PLACE);
self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
qualif
}
fn add_qualif(&mut self, qualif: ConstQualif) {
self.qualif = self.qualif | qualif;
}
/// Returns true if the call is to a const fn or method.
fn handle_const_fn_call(&mut self, expr: &hir::Expr,
def_id: DefId, ret_ty: Ty<'tcx>) -> bool {
match const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
Some(fn_like) => {
if self.mode != Mode::Var &&
!self.tcx.sess.features.borrow().const_fn &&
!self.tcx.sess.codemap().span_allows_unstable(expr.span)
{
self.tcx.sess.span_err(expr.span,
"const fns are an unstable feature");
{
(self.tcx.sess).fileline_help(expr.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["in Nightly builds, add `#![feature(const_fn)]` to the crate attributes to enable"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})))
};
}
let qualif =
self.fn_like(fn_like.kind(), fn_like.decl(),
fn_like.body(), fn_like.span(),
fn_like.id());
self.add_qualif(qualif);
if ret_ty.type_contents(self.tcx).interior_unsafe() {
self.add_qualif(ConstQualif::MUTABLE_MEM);
}
true
}
_ => { false }
}
}
fn record_borrow(&mut self, id: ast::NodeId,
mutbl: hir::Mutability) {
match self.rvalue_borrows.entry(id) {
Entry::Occupied(mut entry) => {
if mutbl == hir::MutMutable { entry.insert(mutbl); }
}
Entry::Vacant(entry) => { entry.insert(mutbl); }
}
}
fn msg(&self) -> &'static str {
match self.mode {
Mode::Const => "constant",
Mode::ConstFn => "constant function",
Mode::StaticMut | Mode::Static => "static",
Mode::Var => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_const.rs",
273u32);
&_FILE_LINE
})
}
}
}
}
fn check_static_mut_type(&self, e: &hir::Expr) {
let node_ty = self.tcx.node_id_to_type(e.id);
let tcontents = node_ty.type_contents(self.tcx);
let suffix =
if tcontents.has_dtor() {
"destructors"
} else if tcontents.owns_owned() {
"boxes"
} else { return };
{
();
self.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mutable statics are not allowed to have "];
__STATIC_FMTSTR
},
&match (&suffix,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0397")
};
}
fn check_static_type(&self, e: &hir::Expr) {
let ty = self.tcx.node_id_to_type(e.id);
let infcx =
infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None,
false);
let cause =
traits::ObligationCause::new(e.span, e.id,
traits::SharedStatic);
let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync,
cause);
match fulfill_cx.select_all_or_error(&infcx) {
Ok(()) => { }
Err(ref errors) => {
traits::report_fulfillment_errors(&infcx, errors);
}
}
}
}
impl <'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
fn visit_item(&mut self, i: &hir::Item) {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 310u32,
file:
"src/librustc/middle/check_const.rs",
module_path:
"rustc::middle::check_const",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::check_const")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["visit_item(item=",
")"];
__STATIC_FMTSTR
},
&match (&self.tcx.map.node_to_string(i.id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}))
}
}
};
{
match (&(self.mode), &(Mode::Var)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_const.rs",
311u32);
&_FILE_LINE
})
}
}
}
}
};
match i.node {
hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
self.check_static_type(&**expr);
self.global_expr(Mode::Static, &**expr);
}
hir::ItemStatic(_, hir::MutMutable, ref expr) => {
self.check_static_mut_type(&**expr);
self.global_expr(Mode::StaticMut, &**expr);
}
hir::ItemConst(_, ref expr) => {
self.global_expr(Mode::Const, &**expr);
}
hir::ItemEnum(ref enum_definition, _) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(&enum_definition.variants)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(var)
=> {
match var.node.disr_expr {
Some(ref ex) => {
self.global_expr(Mode::Const,
&**ex);
}
_ => (),
}
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
_ => { intravisit::walk_item(self, i); }
}
}
fn visit_trait_item(&mut self, t: &'v hir::TraitItem) {
match t.node {
hir::ConstTraitItem(_, ref default) => {
match *default {
Some(ref expr) => {
self.global_expr(Mode::Const, &*expr);
}
_ => { intravisit::walk_trait_item(self, t); }
}
}
_ =>
self.with_mode(Mode::Var,
|v| intravisit::walk_trait_item(v, t)),
}
}
fn visit_impl_item(&mut self, i: &'v hir::ImplItem) {
match i.node {
hir::ImplItemKind::Const(_, ref expr) => {
self.global_expr(Mode::Const, &*expr);
}
_ =>
self.with_mode(Mode::Var,
|v| intravisit::walk_impl_item(v, i)),
}
}
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
self.fn_like(fk, fd, b, s, fn_id);
}
fn visit_pat(&mut self, p: &hir::Pat) {
match p.node {
hir::PatLit(ref lit) => {
self.global_expr(Mode::Const, &**lit);
}
hir::PatRange(ref start, ref end) => {
self.global_expr(Mode::Const, &**start);
self.global_expr(Mode::Const, &**end);
match const_eval::compare_lit_exprs(self.tcx, start,
end) {
Some(Ordering::Less) | Some(Ordering::Equal) => {
}
Some(Ordering::Greater) => {
{
();
self.tcx.sess.span_err_with_code(start.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["lower range bound must be less than or equal to upper"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0030")
};
}
None => {
self.tcx.sess.delay_span_bug(start.span,
"non-constant path in constant expr");
}
}
}
_ => intravisit::walk_pat(self, p),
}
}
fn visit_block(&mut self, block: &hir::Block) {
{
let result =
match ::std::iter::IntoIterator::into_iter(&block.stmts)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(stmt) => {
let span =
match stmt.node {
hir::StmtDecl(ref decl, _) =>
{
match decl.node {
hir::DeclLocal(_) =>
decl.span,
hir::DeclItem(_) =>
continue ,
}
}
hir::StmtExpr(ref expr, _) =>
expr.span,
hir::StmtSemi(ref semi, _) =>
semi.span,
};
self.add_qualif(ConstQualif::NOT_CONST);
if self.mode != Mode::Var {
{
();
self.tcx.sess.span_err_with_code(span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["blocks in ",
"s are limited to items and tail expressions"];
__STATIC_FMTSTR
},
&match (&self.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0016")
};
}
}
::std::option::Option::None => break ,
}
},
};
result
}
intravisit::walk_block(self, block);
}
fn visit_expr(&mut self, ex: &hir::Expr) {
let mut outer = self.qualif;
self.qualif = ConstQualif::empty();
let node_ty = self.tcx.node_id_to_type(ex.id);
check_expr(self, ex, node_ty);
check_adjustments(self, ex);
match ex.node {
hir::ExprCall(ref callee, ref args) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(args)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(arg)
=> {
self.visit_expr(&**arg)
}
::std::option::Option::None =>
break ,
}
},
};
result
}
let inner = self.qualif;
self.visit_expr(&**callee);
let added = self.qualif - inner;
self.qualif =
inner | (added - ConstQualif::NON_ZERO_SIZED);
}
hir::ExprRepeat(ref element, _) => {
self.visit_expr(&**element);
let count =
match node_ty.sty {
ty::TyArray(_, n) => n,
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_const.rs",
445u32);
&_FILE_LINE
})
}
}
};
if count == 0 {
self.qualif.remove(ConstQualif::NON_ZERO_SIZED |
ConstQualif::PREFER_IN_PLACE);
}
}
hir::ExprMatch(ref discr, ref arms, _) => {
let mut borrow = None;
{
let result =
match ::std::iter::IntoIterator::into_iter(arms.iter().flat_map(|arm|
&arm.pats))
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(pat)
=> {
let pat_borrow =
self.rvalue_borrows.remove(&pat.id);
match (borrow, pat_borrow) {
(None, _) |
(_, Some(hir::MutMutable))
=> {
borrow = pat_borrow;
}
_ => { }
}
}
::std::option::Option::None =>
break ,
}
},
};
result
}
match borrow {
Some(mutbl) => {
self.record_borrow(discr.id, mutbl);
}
_ => (),
}
intravisit::walk_expr(self, ex);
}
hir::ExprBinary(op, _, _) => {
intravisit::walk_expr(self, ex);
let div_or_rem =
op.node == hir::BiDiv || op.node == hir::BiRem;
match node_ty.sty {
ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
if !self.qualif.intersects(ConstQualif::NOT_CONST)
{
match const_eval::eval_const_expr_partial(self.tcx,
ex,
ExprTypeChecked,
None)
{
Ok(_) => { }
Err(msg) => {
self.tcx.sess.add_lint(::lint::builtin::CONST_ERR,
ex.id,
msg.span,
msg.description().into_owned())
}
}
}
}
_ => { }
}
}
_ => intravisit::walk_expr(self, ex),
}
match self.rvalue_borrows.remove(&ex.id) {
Some(hir::MutImmutable) => {
let tc = node_ty.type_contents(self.tcx);
if self.qualif.intersects(ConstQualif::MUTABLE_MEM) &&
tc.interior_unsafe() {
outer = outer | ConstQualif::NOT_CONST;
if self.mode != Mode::Var {
{
();
self.tcx.sess.span_err_with_code(ex.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["cannot borrow a constant which contains interior mutability, create a static instead"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0492")
};
}
}
if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS)
{
self.qualif =
self.qualif - ConstQualif::PREFER_IN_PLACE;
self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
}
}
Some(hir::MutMutable) => {
if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED)
{
if self.mode == Mode::Var {
outer = outer | ConstQualif::NOT_CONST;
self.add_qualif(ConstQualif::MUTABLE_MEM);
} else {
{
();
self.tcx.sess.span_err_with_code(ex.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["references in ",
"s may only refer to immutable values"];
__STATIC_FMTSTR
},
&match (&self.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0017")
}
}
}
if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS)
{
self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
}
}
None => { }
}
self.tcx.const_qualif_map.borrow_mut().insert(ex.id,
self.qualif);
self.qualif =
outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
}
}
/// This function is used to enforce the constraints on
/// const/static items. It walks through the *value*
/// of the item walking down the expression and evaluating
/// every nested expression. If the expression is not part
/// of a const/static item, it is qualified for promotion
/// instead of producing errors.
fn check_expr<'a,
'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
e: &hir::Expr, node_ty: Ty<'tcx>) {
match node_ty.sty {
ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() =>
{
v.add_qualif(ConstQualif::NEEDS_DROP);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["",
"s are not allowed to have destructors"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0493")
};
}
}
_ => { }
}
let method_call = ty::MethodCall::expr(e.id);
match e.node {
hir::ExprUnary(..) | hir::ExprBinary(..) | hir::ExprIndex(..)
if v.tcx.tables.borrow().method_map.contains_key(&method_call)
=> {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["user-defined operators are not allowed in ",
"s"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0011")
};
}
}
hir::ExprBox(_) => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["allocations are not allowed in ",
"s"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0010")
};
}
}
hir::ExprUnary(op, ref inner) => {
match v.tcx.node_id_to_type(inner.id).sty {
ty::TyRawPtr(_) => {
if !(op == hir::UnDeref) {
{
::std::rt::begin_unwind("assertion failed: op == hir::UnDeref",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_const.rs",
584u32);
&_FILE_LINE
})
}
};
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["raw pointers cannot be dereferenced in ",
"s"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0396")
};
}
}
_ => { }
}
}
hir::ExprBinary(op, ref lhs, _) => {
match v.tcx.node_id_to_type(lhs.id).sty {
ty::TyRawPtr(_) => {
if !(op.node == hir::BiEq || op.node == hir::BiNe
|| op.node == hir::BiLe ||
op.node == hir::BiLt ||
op.node == hir::BiGe ||
op.node == hir::BiGt) {
{
::std::rt::begin_unwind("assertion failed: op.node == hir::BiEq || op.node == hir::BiNe || op.node == hir::BiLe ||\n op.node == hir::BiLt || op.node == hir::BiGe || op.node == hir::BiGt",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_const.rs",
598u32);
&_FILE_LINE
})
}
};
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["raw pointers cannot be compared in ",
"s"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0395")
};
}
}
_ => { }
}
}
hir::ExprCast(ref from, _) => {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 612u32,
file:
"src/librustc/middle/check_const.rs",
module_path:
"rustc::middle::check_const",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::check_const")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["Checking const cast(id=",
")"];
__STATIC_FMTSTR
},
&match (&from.id,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}))
}
}
};
match v.tcx.cast_kinds.borrow().get(&from.id) {
None =>
v.tcx.sess.span_bug(e.span, "no kind for cast"),
Some(&CastKind::PtrAddrCast) |
Some(&CastKind::FnPtrAddrCast) => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["raw pointers cannot be cast to integers in ",
"s"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0018")
};
}
}
_ => { }
}
}
hir::ExprPath(..) => {
let def =
v.tcx.def_map.borrow().get(&e.id).map(|d|
d.full_def());
match def {
Some(def::DefVariant(_, _, _)) => {
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
Some(def::DefStruct(_)) => {
match node_ty.sty {
ty::TyBareFn(..) => {
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
_ => (),
}
}
Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
Some(def::DefStatic(..)) => {
match v.mode {
Mode::Static | Mode::StaticMut => { }
Mode::Const | Mode::ConstFn => {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["",
"s cannot refer to other statics, insert an intermediate constant instead"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0013")
};
}
Mode::Var =>
v.add_qualif(ConstQualif::NOT_CONST),
}
}
Some(def::DefConst(did)) |
Some(def::DefAssociatedConst(did)) => {
match const_eval::lookup_const_by_id(v.tcx, did,
Some(e.id)) {
Some(expr) => {
let inner =
v.global_expr(Mode::Const, expr);
v.add_qualif(inner);
}
_ => {
v.tcx.sess.span_bug(e.span,
"DefConst or DefAssociatedConst doesn\'t point to a constant");
}
}
}
Some(def::DefLocal(..)) if v.mode == Mode::ConstFn =>
{
v.add_qualif(ConstQualif::NOT_CONST |
ConstQualif::NON_ZERO_SIZED);
}
def => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 672u32,
file:
"src/librustc/middle/check_const.rs",
module_path:
"rustc::middle::check_const",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false)
&&
lvl <= ::log::log_level()
&&
::log::mod_enabled(lvl,
"rustc::middle::check_const")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["(checking const) found bad def: "];
__STATIC_FMTSTR
},
&match (&def,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}))
}
}
};
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["paths in ",
"s may only refer to constants or functions"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0014")
};
}
}
}
}
hir::ExprCall(ref callee, _) => {
let mut callee = &**callee;
loop {
callee =
match callee.node {
hir::ExprBlock(ref block) =>
match block.expr {
Some(ref tail) => &**tail,
None => break ,
},
_ => break ,
};
}
let def =
v.tcx.def_map.borrow().get(&callee.id).map(|d|
d.full_def());
let is_const =
match def {
Some(def::DefStruct(..)) => true,
Some(def::DefVariant(..)) => {
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
true
}
Some(def::DefFn(did, _)) => {
v.handle_const_fn_call(e, did, node_ty)
}
Some(def::DefMethod(did)) => {
match v.tcx.impl_or_trait_item(did).container()
{
ty::ImplContainer(_) => {
v.handle_const_fn_call(e, did,
node_ty)
}
ty::TraitContainer(_) => false,
}
}
_ => false,
};
if !is_const {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
fn span_limited_call_error(tcx: &ty::ctxt,
span: Span, s: &str) {
{
();
tcx.sess.span_err_with_code(span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[""];
__STATIC_FMTSTR
},
&match (&s,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0015")
};
}
match v.tcx.sess.opts.unstable_features {
UnstableFeatures::Disallow => {
span_limited_call_error(&v.tcx, e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["function calls in ",
"s are limited to struct and enum constructors"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})));
v.tcx.sess.span_note(e.span,
"a limited form of compile-time function evaluation is available on a nightly compiler via `const fn`");
}
_ => {
span_limited_call_error(&v.tcx, e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["function calls in ",
"s are limited to constant functions, struct and enum constructors"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})));
}
}
}
}
}
hir::ExprMethodCall(..) => {
let method =
v.tcx.tables.borrow().method_map[&method_call];
let is_const =
match v.tcx.impl_or_trait_item(method.def_id).container()
{
ty::ImplContainer(_) =>
v.handle_const_fn_call(e, method.def_id, node_ty),
ty::TraitContainer(_) => false,
};
if !is_const {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["method calls in ",
"s are limited to constant inherent methods"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0378")
};
}
}
}
hir::ExprStruct(..) => {
let did =
v.tcx.def_map.borrow().get(&e.id).map(|def|
def.def_id());
if did == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(ConstQualif::MUTABLE_MEM);
}
}
hir::ExprLit(_) | hir::ExprAddrOf(..) => {
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
hir::ExprRepeat(..) => {
v.add_qualif(ConstQualif::PREFER_IN_PLACE);
}
hir::ExprClosure(..) => {
if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
if !(v.mode == Mode::Var) {
{
::std::rt::begin_unwind("global closures can\'t capture anything",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_const.rs",
774u32);
&_FILE_LINE
})
}
};
v.add_qualif(ConstQualif::NOT_CONST);
}
}
hir::ExprBlock(_) | hir::ExprIndex(..) | hir::ExprField(..) |
hir::ExprTupField(..) | hir::ExprVec(_) | hir::ExprTup(..) =>
{
}
hir::ExprMatch(..) | hir::ExprIf(..) | hir::ExprWhile(..) |
hir::ExprLoop(..) | hir::ExprBreak(_) | hir::ExprAgain(_) |
hir::ExprRet(_) | hir::ExprRange(..) | hir::ExprAssign(..) |
hir::ExprAssignOp(..) | hir::ExprInlineAsm(_) => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["",
" contains unimplemented expression type"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0019")
};
}
}
}
}
/// Check the adjustments of an expression
fn check_adjustments<'a,
'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
e: &hir::Expr) {
match v.tcx.tables.borrow().adjustments.get(&e.id) {
None | Some(&ty::adjustment::AdjustReifyFnPointer) |
Some(&ty::adjustment::AdjustUnsafeFnPointer) => {
}
Some(&ty::adjustment::AdjustDerefRef(ty::adjustment::AutoDerefRef {
autoderefs, .. })) => {
if (0..autoderefs as
u32).any(|autoderef| {
v.tcx.is_overloaded_autoderef(e.id,
autoderef)
}) {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
{
();
v.tcx.sess.span_err_with_code(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["user-defined dereference operators are not allowed in ",
"s"];
__STATIC_FMTSTR
},
&match (&v.msg(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0400")
};
}
}
}
}
}
pub fn check_crate(tcx: &ty::ctxt) {
tcx.map.krate().visit_all_items(&mut CheckCrateVisitor{tcx: tcx,
mode:
Mode::Var,
qualif:
ConstQualif::NOT_CONST,
rvalue_borrows:
NodeMap(),});
tcx.sess.abort_if_errors();
}
impl <'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
fn consume(&mut self, _consume_id: ast::NodeId,
consume_span: Span, cmt: mc::cmt,
_mode: euv::ConsumeMode) {
let mut cur = &cmt;
loop {
match cur.cat {
Categorization::StaticItem => {
if self.mode != Mode::Var {
{
();
self.tcx.sess.span_err_with_code(consume_span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["cannot refer to other statics by value, use the address-of operator or a constant instead"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0394")
};
}
break ;
}
Categorization::Deref(ref cmt, _, _) |
Categorization::Downcast(ref cmt, _) |
Categorization::Interior(ref cmt, _) => cur = cmt,
Categorization::Rvalue(..) | Categorization::Upvar(..)
| Categorization::Local(..) => break ,
}
}
}
fn borrow(&mut self, borrow_id: ast::NodeId, borrow_span: Span,
cmt: mc::cmt<'tcx>, _loan_region: ty::Region,
bk: ty::BorrowKind, loan_cause: euv::LoanCause) {
match loan_cause {
euv::LoanCause::AutoUnsafe => { return; }
_ => { }
}
let mut cur = &cmt;
let mut is_interior = false;
loop {
match cur.cat {
Categorization::Rvalue(..) => {
if loan_cause == euv::MatchDiscriminant {
break ;
}
let mutbl = bk.to_mutbl_lossy();
if mutbl == hir::MutMutable &&
self.mode == Mode::StaticMut {
match cmt.ty.sty {
ty::TyArray(_, _) | ty::TySlice(_) =>
break ,
_ => { }
}
}
self.record_borrow(borrow_id, mutbl);
break ;
}
Categorization::StaticItem => {
if is_interior && self.mode != Mode::Var {
{
();
self.tcx.sess.span_err_with_code(borrow_span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["cannot refer to the interior of another static, use a constant instead"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0494")
};
}
break ;
}
Categorization::Deref(ref cmt, _, _) |
Categorization::Downcast(ref cmt, _) |
Categorization::Interior(ref cmt, _) => {
is_interior = true;
cur = cmt;
}
Categorization::Upvar(..) | Categorization::Local(..)
=> break ,
}
}
}
fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) { }
fn mutate(&mut self, _assignment_id: ast::NodeId,
_assignment_span: Span, _assignee_cmt: mc::cmt,
_mode: euv::MutateMode) {
}
fn matched_pat(&mut self, _: &hir::Pat, _: mc::cmt,
_: euv::MatchMode) {
}
fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: mc::cmt,
_mode: euv::ConsumeMode) {
}
}
}
pub mod check_static_recursion {
#[prelude_import]
use std::prelude::v1::*;
use front::map as ast_map;
use session::Session;
use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefVariant,
DefMap};
use util::nodemap::NodeMap;
use syntax::{ast};
use syntax::codemap::Span;
use syntax::feature_gate::{GateIssue, emit_feature_err};
use rustc_front::intravisit::{self, Visitor};
use rustc_front::hir;
use std::cell::RefCell;
struct CheckCrateVisitor<'a, 'ast:'a> {
sess: &'a Session,
def_map: &'a DefMap,
ast_map: &'a ast_map::Map<'ast>,
discriminant_map: RefCell<NodeMap<Option<&'ast hir::Expr>>>,
}
impl <'a, 'ast:'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
fn visit_item(&mut self, it: &'ast hir::Item) {
match it.node {
hir::ItemStatic(..) | hir::ItemConst(..) => {
let mut recursion_visitor =
CheckItemRecursionVisitor::new(self, &it.span);
recursion_visitor.visit_item(it);
}
hir::ItemEnum(ref enum_def, ref generics) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(&enum_def.variants)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(variant)
=> {
match variant.node.disr_expr {
Some(_) => {
let mut recursion_visitor =
CheckItemRecursionVisitor::new(self,
&variant.span);
recursion_visitor.populate_enum_discriminants(enum_def);
recursion_visitor.visit_variant(variant,
generics,
it.id);
}
_ => (),
}
}
::std::option::Option::None =>
break ,
}
},
};
result
}
}
_ => { }
}
intravisit::walk_item(self, it)
}
fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
match ti.node {
hir::ConstTraitItem(_, ref default) => {
match *default {
Some(_) => {
let mut recursion_visitor =
CheckItemRecursionVisitor::new(self,
&ti.span);
recursion_visitor.visit_trait_item(ti);
}
_ => (),
}
}
_ => { }
}
intravisit::walk_trait_item(self, ti)
}
fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
match ii.node {
hir::ImplItemKind::Const(..) => {
let mut recursion_visitor =
CheckItemRecursionVisitor::new(self, &ii.span);
recursion_visitor.visit_impl_item(ii);
}
_ => { }
}
intravisit::walk_impl_item(self, ii)
}
}
pub fn check_crate<'ast>(sess: &Session, krate: &'ast hir::Crate,
def_map: &DefMap,
ast_map: &ast_map::Map<'ast>) {
let mut visitor =
CheckCrateVisitor{sess: sess,
def_map: def_map,
ast_map: ast_map,
discriminant_map: RefCell::new(NodeMap()),};
krate.visit_all_items(&mut visitor);
sess.abort_if_errors();
}
struct CheckItemRecursionVisitor<'a, 'ast:'a> {
root_span: &'a Span,
sess: &'a Session,
ast_map: &'a ast_map::Map<'ast>,
def_map: &'a DefMap,
discriminant_map: &'a RefCell<NodeMap<Option<&'ast hir::Expr>>>,
idstack: Vec<ast::NodeId>,
}
impl <'a, 'ast:'a> CheckItemRecursionVisitor<'a, 'ast> {
fn new(v: &'a CheckCrateVisitor<'a, 'ast>, span: &'a Span)
-> CheckItemRecursionVisitor<'a, 'ast> {
CheckItemRecursionVisitor{root_span: span,
sess: v.sess,
ast_map: v.ast_map,
def_map: v.def_map,
discriminant_map:
&v.discriminant_map,
idstack: Vec::new(),}
}
fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F) where
F: Fn(&mut Self) {
if self.idstack.iter().any(|&x| x == id) {
let any_static =
self.idstack.iter().any(|&x| {
match self.ast_map.get(x) {
ast_map::NodeItem(item) =>
{
match item.node {
hir::ItemStatic(..)
=> {
true
}
_ => { false }
}
}
_ => { false }
} });
if any_static {
if !self.sess.features.borrow().static_recursion {
emit_feature_err(&self.sess.parse_sess.span_diagnostic,
"static_recursion",
*self.root_span,
GateIssue::Language,
"recursive static");
}
} else {
{
();
self.sess.span_err_with_code(*self.root_span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["recursive constant"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0265")
};
}
return;
}
self.idstack.push(id);
f(self);
self.idstack.pop();
}
fn populate_enum_discriminants(&self,
enum_definition:
&'ast hir::EnumDef) {
let mut discriminant_map = self.discriminant_map.borrow_mut();
match enum_definition.variants.first() {
None => { return; }
Some(variant) if
discriminant_map.contains_key(&variant.node.data.id()) =>
{
return;
}
_ => { }
}
let mut variant_stack: Vec<ast::NodeId> = Vec::new();
{
let result =
match ::std::iter::IntoIterator::into_iter(enum_definition.variants.iter().rev())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(variant) => {
variant_stack.push(variant.node.data.id());
match variant.node.disr_expr {
Some(ref expr) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(&variant_stack)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(id)
=> {
discriminant_map.insert(*id,
Some(expr));
}
::std::option::Option::None
=> break ,
}
},
};
result
}
variant_stack.clear()
}
_ => (),
}
}
::std::option::Option::None => break ,
}
},
};
result
}
{
let result =
match ::std::iter::IntoIterator::into_iter(&variant_stack)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(id) => {
discriminant_map.insert(*id, None);
}
::std::option::Option::None => break ,
}
},
};
result
}
}
}
impl <'a, 'ast:'a> Visitor<'ast> for
CheckItemRecursionVisitor<'a, 'ast> {
fn visit_item(&mut self, it: &'ast hir::Item) {
self.with_item_id_pushed(it.id,
|v| intravisit::walk_item(v, it));
}
fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef,
generics: &'ast hir::Generics,
item_id: ast::NodeId, _: Span) {
self.populate_enum_discriminants(enum_definition);
intravisit::walk_enum_def(self, enum_definition, generics,
item_id);
}
fn visit_variant(&mut self, variant: &'ast hir::Variant,
_: &'ast hir::Generics, _: ast::NodeId) {
let variant_id = variant.node.data.id();
let maybe_expr;
match self.discriminant_map.borrow().get(&variant_id) {
Some(get_expr) => { maybe_expr = (*get_expr).clone(); }
_ => {
self.sess.span_bug(variant.span,
"`check_static_recursion` attempted to visit variant with unknown discriminant")
}
}
match maybe_expr {
Some(expr) => {
self.with_item_id_pushed(expr.id,
|v|
intravisit::walk_expr(v,
expr));
}
_ => (),
}
}
fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
self.with_item_id_pushed(ti.id,
|v|
intravisit::walk_trait_item(v,
ti));
}
fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
self.with_item_id_pushed(ii.id,
|v|
intravisit::walk_impl_item(v,
ii));
}
fn visit_expr(&mut self, e: &'ast hir::Expr) {
match e.node {
hir::ExprPath(..) => {
match self.def_map.get(&e.id).map(|d| d.base_def) {
Some(DefStatic(def_id, _)) |
Some(DefAssociatedConst(def_id)) |
Some(DefConst(def_id)) => {
match self.ast_map.as_local_node_id(def_id) {
Some(node_id) => {
match self.ast_map.get(node_id) {
ast_map::NodeItem(item) =>
self.visit_item(item),
ast_map::NodeTraitItem(item) =>
self.visit_trait_item(item),
ast_map::NodeImplItem(item) =>
self.visit_impl_item(item),
ast_map::NodeForeignItem(_) => { }
_ => {
self.sess.span_bug(e.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["expected item, found "];
__STATIC_FMTSTR
},
&match (&self.ast_map.node_to_string(node_id),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})));
}
}
}
_ => (),
}
}
Some(DefVariant(enum_id, variant_id, false)) => {
match self.ast_map.as_local_node_id(enum_id) {
Some(enum_node_id) => {
match self.ast_map.expect_item(enum_node_id).node
{
hir::ItemEnum(ref enum_def,
ref generics) => {
self.populate_enum_discriminants(enum_def);
let enum_id =
self.ast_map.as_local_node_id(enum_id).unwrap();
let variant_id =
self.ast_map.as_local_node_id(variant_id).unwrap();
let variant =
self.ast_map.expect_variant(variant_id);
self.visit_variant(variant,
generics,
enum_id);
}
_ => {
self.sess.span_bug(e.span,
"`check_static_recursion` found non-enum in DefVariant");
}
}
}
_ => (),
}
}
_ => (),
}
}
_ => (),
}
intravisit::walk_expr(self, e);
}
}
}
pub mod check_loop {
#[prelude_import]
use std::prelude::v1::*;
use self::Context::*;
use session::Session;
use syntax::codemap::Span;
use rustc_front::intravisit::{self, Visitor};
use rustc_front::hir;
enum Context { Normal, Loop, Closure, }
#[automatically_derived]
impl ::std::cmp::PartialEq for Context {
#[inline]
fn eq(&self, __arg_0: &Context) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Context::Normal, &Context::Normal) => true,
(&Context::Loop, &Context::Loop) => true,
(&Context::Closure, &Context::Closure) => true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &Context) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Context::Normal, &Context::Normal) => false,
(&Context::Loop, &Context::Loop) => false,
(&Context::Closure, &Context::Closure) => false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for Context { }
#[automatically_derived]
impl ::std::clone::Clone for Context {
#[inline]
fn clone(&self) -> Context {
match (&*self,) {
(&Context::Normal,) => Context::Normal,
(&Context::Loop,) => Context::Loop,
(&Context::Closure,) => Context::Closure,
}
}
}
struct CheckLoopVisitor<'a> {
sess: &'a Session,
cx: Context,
}
#[automatically_derived]
impl <'a> ::std::clone::Clone for CheckLoopVisitor<'a> {
#[inline]
fn clone(&self) -> CheckLoopVisitor<'a> {
match *self {
CheckLoopVisitor {
sess: ref __self_0_0, cx: ref __self_0_1 } =>
CheckLoopVisitor{sess:
::std::clone::Clone::clone(&(*__self_0_0)),
cx:
::std::clone::Clone::clone(&(*__self_0_1)),},
}
}
}
#[automatically_derived]
impl <'a> ::std::marker::Copy for CheckLoopVisitor<'a> { }
pub fn check_crate(sess: &Session, krate: &hir::Crate) {
krate.visit_all_items(&mut CheckLoopVisitor{sess: sess,
cx: Normal,});
}
impl <'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
fn visit_item(&mut self, i: &hir::Item) {
self.with_context(Normal, |v| intravisit::walk_item(v, i));
}
fn visit_expr(&mut self, e: &hir::Expr) {
match e.node {
hir::ExprWhile(ref e, ref b, _) => {
self.visit_expr(&**e);
self.with_context(Loop, |v| v.visit_block(&**b));
}
hir::ExprLoop(ref b, _) => {
self.with_context(Loop, |v| v.visit_block(&**b));
}
hir::ExprClosure(_, _, ref b) => {
self.with_context(Closure, |v| v.visit_block(&**b));
}
hir::ExprBreak(_) => self.require_loop("break", e.span),
hir::ExprAgain(_) =>
self.require_loop("continue", e.span),
_ => intravisit::walk_expr(self, e),
}
}
}
impl <'a> CheckLoopVisitor<'a> {
fn with_context<F>(&mut self, cx: Context, f: F) where
F: FnOnce(&mut CheckLoopVisitor<'a>) {
let old_cx = self.cx;
self.cx = cx;
f(self);
self.cx = old_cx;
}
fn require_loop(&self, name: &str, span: Span) {
match self.cx {
Loop => { }
Closure => {
{
();
self.sess.span_err_with_code(span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["`",
"` inside of a closure"];
__STATIC_FMTSTR
},
&match (&name,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0267")
};
}
Normal => {
{
();
self.sess.span_err_with_code(span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["`",
"` outside of loop"];
__STATIC_FMTSTR
},
&match (&name,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0268")
};
}
}
}
}
}
pub mod check_match {
#[prelude_import]
use std::prelude::v1::*;
pub use self::Constructor::*;
use self::Usefulness::*;
use self::WitnessPreference::*;
use middle::const_eval::{compare_const_vals, ConstVal};
use middle::const_eval::{eval_const_expr, eval_const_expr_partial};
use middle::const_eval::{const_expr_to_pat, lookup_const_by_id};
use middle::const_eval::EvalHint::ExprTypeChecked;
use middle::def::*;
use middle::def_id::{DefId};
use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor,
Init};
use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
use middle::expr_use_visitor::WriteAndRead;
use middle::expr_use_visitor as euv;
use middle::infer;
use middle::mem_categorization::{cmt};
use middle::pat_util::*;
use middle::ty::*;
use middle::ty;
use std::cmp::Ordering;
use std::fmt;
use std::iter::{FromIterator, IntoIterator, repeat};
use rustc_front::hir;
use rustc_front::hir::Pat;
use rustc_front::intravisit::{self, Visitor, FnKind};
use rustc_front::util as front_util;
use rustc_back::slice;
use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
use syntax::ast_util;
use syntax::codemap::{Span, Spanned, DUMMY_SP};
use rustc_front::fold::{Folder, noop_fold_pat};
use rustc_front::print::pprust::pat_to_string;
use syntax::ptr::P;
use util::nodemap::FnvHashMap;
pub const DUMMY_WILD_PAT: &'static Pat =
&Pat{id: DUMMY_NODE_ID, node: hir::PatWild, span: DUMMY_SP,};
struct Matrix<'a>(Vec<Vec<&'a Pat>>);
/// Pretty-printer for matrices of patterns, example:
/// ++++++++++++++++++++++++++
/// + _ + [] +
/// ++++++++++++++++++++++++++
/// + true + [First] +
/// ++++++++++++++++++++++++++
/// + true + [Second(true)] +
/// ++++++++++++++++++++++++++
/// + false + [_] +
/// ++++++++++++++++++++++++++
/// + _ + [_, _, ..tail] +
/// ++++++++++++++++++++++++++
impl <'a> fmt::Debug for Matrix<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["\n"];
__STATIC_FMTSTR
},
&match () {
() => [],
})) {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
let &Matrix(ref m) = self;
let pretty_printed_matrix: Vec<Vec<String>> =
m.iter().map(|row| {
row.iter().map(|&pat|
pat_to_string(&*pat)).collect::<Vec<String>>()
}).collect();
let column_count =
m.iter().map(|row| row.len()).max().unwrap_or(0);
if !m.iter().all(|row| row.len() == column_count) {
{
::std::rt::begin_unwind("assertion failed: m.iter().all(|row| row.len() == column_count)",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/middle/check_match.rs",
80u32);
&_FILE_LINE
})
}
};
let column_widths: Vec<usize> =
(0..column_count).map(|col| {
pretty_printed_matrix.iter().map(|row|
row[col].len()).max().unwrap_or(0)
}).collect();
let total_width =
column_widths.iter().cloned().sum::<usize>() +
column_count * 3 + 1;
let br = repeat('+').take(total_width).collect::<String>();
match f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["",
"\n"];
__STATIC_FMTSTR
},
&match (&br,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})) {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
{
let result =
match ::std::iter::IntoIterator::into_iter(pretty_printed_matrix)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(row) => {
match f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["+"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
{
::std::result::Result::Ok(val) =>
val,
::std::result::Result::Err(err) =>
{
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
{
let result =
match ::std::iter::IntoIterator::into_iter(row.into_iter().enumerate())
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some((column,
pat_str))
=> {
match f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[" "];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
{
::std::result::Result::Ok(val)
=> val,
::std::result::Result::Err(err)
=> {
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
match f.write_fmt(::std::fmt::Arguments::new_v1_formatted({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[""];
__STATIC_FMTSTR
},
&match (&pat_str,
&column_widths[column])
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::from_usize(__arg1)],
},
{
static __STATIC_FMTARGS:
&'static [::std::fmt::rt::v1::Argument]
=
&[::std::fmt::rt::v1::Argument{position:
::std::fmt::rt::v1::Position::Next,
format:
::std::fmt::rt::v1::FormatSpec{fill:
' ',
align:
::std::fmt::rt::v1::Alignment::Unknown,
flags:
0u32,
precision:
::std::fmt::rt::v1::Count::Implied,
width:
::std::fmt::rt::v1::Count::Param(1usize),},}];
__STATIC_FMTARGS
}))
{
::std::result::Result::Ok(val)
=> val,
::std::result::Result::Err(err)
=> {
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
match f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[" +"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
{
::std::result::Result::Ok(val)
=> val,
::std::result::Result::Err(err)
=> {
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
}
::std::option::Option::None
=> break ,
}
},
};
result
}
match f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["\n"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
}))
{
::std::result::Result::Ok(val) =>
val,
::std::result::Result::Err(err) =>
{
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
match f.write_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["",
"\n"];
__STATIC_FMTSTR
},
&match (&br,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
}))
{
::std::result::Result::Ok(val) =>
val,
::std::result::Result::Err(err) =>
{
return ::std::result::Result::Err(::std::convert::From::from(err))
}
};
}
::std::option::Option::None => break ,
}
},
};
result
}
Ok(())
}
}
impl <'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> {
fn from_iter<T: IntoIterator<Item = Vec<&'a Pat>>>(iter: T)
-> Matrix<'a> {
Matrix(iter.into_iter().collect())
}
}
pub struct MatchCheckCtxt<'a, 'tcx:'a> {
pub tcx: &'a ty::ctxt<'tcx>,
pub param_env: ParameterEnvironment<'a, 'tcx>,
}
pub enum Constructor {
/// The constructor of all patterns that don't vary by constructor,
/// e.g. struct patterns and fixed-length arrays.
Single,
/// Enum variants.
Variant(DefId),
/// Literal values.
ConstantValue(ConstVal),
/// Ranges of literal values (2..5).
ConstantRange(ConstVal, ConstVal),
/// Array patterns of length n.
Slice(usize),
/// Array patterns with a subslice.
SliceWithSubslice(usize, usize),
}
#[automatically_derived]
impl ::std::cmp::PartialEq for Constructor {
#[inline]
fn eq(&self, __arg_0: &Constructor) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Constructor::Single, &Constructor::Single) =>
true,
(&Constructor::Variant(ref __self_0),
&Constructor::Variant(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&Constructor::ConstantValue(ref __self_0),
&Constructor::ConstantValue(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&Constructor::ConstantRange(ref __self_0,
ref __self_1),
&Constructor::ConstantRange(ref __arg_1_0,
ref __arg_1_1)) =>
true && (*__self_0) == (*__arg_1_0) &&
(*__self_1) == (*__arg_1_1),
(&Constructor::Slice(ref __self_0),
&Constructor::Slice(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&Constructor::SliceWithSubslice(ref __self_0,
ref __self_1),
&Constructor::SliceWithSubslice(ref __arg_1_0,
ref __arg_1_1))
=>
true && (*__self_0) == (*__arg_1_0) &&
(*__self_1) == (*__arg_1_1),
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &Constructor) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Constructor::Single, &Constructor::Single) =>
false,
(&Constructor::Variant(ref __self_0),
&Constructor::Variant(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&Constructor::ConstantValue(ref __self_0),
&Constructor::ConstantValue(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&Constructor::ConstantRange(ref __self_0,
ref __self_1),
&Constructor::ConstantRange(ref __arg_1_0,
ref __arg_1_1)) =>
false || (*__self_0) != (*__arg_1_0) ||
(*__self_1) != (*__arg_1_1),
(&Constructor::Slice(ref __self_0),
&Constructor::Slice(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&Constructor::SliceWithSubslice(ref __self_0,
ref __self_1),
&Constructor::SliceWithSubslice(ref __arg_1_0,
ref __arg_1_1))
=>
false || (*__self_0) != (*__arg_1_0) ||
(*__self_1) != (*__arg_1_1),
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for Constructor {
#[inline]
fn clone(&self) -> Constructor {
match (&*self,) {
(&Constructor::Single,) => Constructor::Single,
(&Constructor::Variant(ref __self_0),) =>
Constructor::Variant(::std::clone::Clone::clone(&(*__self_0))),
(&Constructor::ConstantValue(ref __self_0),) =>
Constructor::ConstantValue(::std::clone::Clone::clone(&(*__self_0))),
(&Constructor::ConstantRange(ref __self_0, ref __self_1),)
=>
Constructor::ConstantRange(::std::clone::Clone::clone(&(*__self_0)),
::std::clone::Clone::clone(&(*__self_1))),
(&Constructor::Slice(ref __self_0),) =>
Constructor::Slice(::std::clone::Clone::clone(&(*__self_0))),
(&Constructor::SliceWithSubslice(ref __self_0,
ref __self_1),) =>
Constructor::SliceWithSubslice(::std::clone::Clone::clone(&(*__self_0)),
::std::clone::Clone::clone(&(*__self_1))),
}
}
}
enum Usefulness { Useful, UsefulWithWitness(Vec<P<Pat>>), NotUseful, }
#[automatically_derived]
impl ::std::cmp::PartialEq for Usefulness {
#[inline]
fn eq(&self, __arg_0: &Usefulness) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Usefulness::Useful, &Usefulness::Useful) =>
true,
(&Usefulness::UsefulWithWitness(ref __self_0),
&Usefulness::UsefulWithWitness(ref __arg_1_0)) =>
true && (*__self_0) == (*__arg_1_0),
(&Usefulness::NotUseful, &Usefulness::NotUseful)
=> true,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { false }
}
}
#[inline]
fn ne(&self, __arg_0: &Usefulness) -> bool {
{
let __self_vi =
unsafe {
::std::intrinsics::discriminant_value(&*self)
} as i32;
let __arg_1_vi =
unsafe {
::std::intrinsics::discriminant_value(&*__arg_0)
} as i32;
if true && __self_vi == __arg_1_vi {
match (&*self, &*__arg_0) {
(&Usefulness::Useful, &Usefulness::Useful) =>
false,
(&Usefulness::UsefulWithWitness(ref __self_0),
&Usefulness::UsefulWithWitness(ref __arg_1_0)) =>
false || (*__self_0) != (*__arg_1_0),
(&Usefulness::NotUseful, &Usefulness::NotUseful)
=> false,
_ => unsafe { ::std::intrinsics::unreachable() }
}
} else { true }
}
}
}
#[automatically_derived]
impl ::std::clone::Clone for Usefulness {
#[inline]
fn clone(&self) -> Usefulness {
match (&*self,) {
(&Usefulness::Useful,) => Usefulness::Useful,
(&Usefulness::UsefulWithWitness(ref __self_0),) =>
Usefulness::UsefulWithWitness(::std::clone::Clone::clone(&(*__self_0))),
(&Usefulness::NotUseful,) => Usefulness::NotUseful,
}
}
}
enum WitnessPreference { ConstructWitness, LeaveOutWitness, }
#[automatically_derived]
impl ::std::clone::Clone for WitnessPreference {
#[inline]
fn clone(&self) -> WitnessPreference {
match (&*self,) {
(&WitnessPreference::ConstructWitness,) =>
WitnessPreference::ConstructWitness,
(&WitnessPreference::LeaveOutWitness,) =>
WitnessPreference::LeaveOutWitness,
}
}
}
#[automatically_derived]
impl ::std::marker::Copy for WitnessPreference { }
impl <'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
fn visit_expr(&mut self, ex: &hir::Expr) { check_expr(self, ex); }
fn visit_local(&mut self, l: &hir::Local) {
check_local(self, l);
}
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
b: &'v hir::Block, s: Span, n: NodeId) {
check_fn(self, fk, fd, b, s, n);
}
}
pub fn check_crate(tcx: &ty::ctxt) {
tcx.map.krate().visit_all_items(&mut MatchCheckCtxt{tcx: tcx,
param_env:
tcx.empty_parameter_environment(),});
tcx.sess.abort_if_errors();
}
fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
intravisit::walk_expr(cx, ex);
match ex.node {
hir::ExprMatch(ref scrut, ref arms, source) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(arms) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(arm) => {
check_legality_of_move_bindings(cx,
arm.guard.is_some(),
&arm.pats);
match arm.guard {
Some(ref guard) =>
check_for_mutation_in_guard(cx,
&**guard),
None => { }
}
}
::std::option::Option::None => break ,
}
},
};
result
}
let mut static_inliner = StaticInliner::new(cx.tcx, None);
let inlined_arms =
arms.iter().map(|arm| {
(arm.pats.iter().map(|pat| {
static_inliner.fold_pat((*pat).clone())
}).collect(),
arm.guard.as_ref().map(|e| &**e))
}).collect::<Vec<(Vec<P<Pat>>,
Option<&hir::Expr>)>>();
if static_inliner.failed { return; }
{
let result =
match ::std::iter::IntoIterator::into_iter(inlined_arms.iter().flat_map(|&(ref pats,
_)|
pats))
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(pat) => {
check_legality_of_bindings_in_at_patterns(cx,
&**pat);
check_for_static_nan(cx, &**pat);
check_for_bindings_named_the_same_as_variants(cx,
&**pat);
}
::std::option::Option::None => break ,
}
},
};
result
}
check_arms(cx, &inlined_arms[..], source);
let pat_ty = cx.tcx.node_id_to_type(scrut.id);
if inlined_arms.is_empty() {
if !pat_ty.is_empty(cx.tcx) {
{
();
cx.tcx.sess.span_err_with_code(ex.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["non-exhaustive patterns: type ",
" is non-empty"];
__STATIC_FMTSTR
},
&match (&pat_ty,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0002")
};
{
(cx.tcx.sess).span_help(ex.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["Please ensure that all possible cases are being handled; possibly adding wildcards or more match arms."];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})))
};
}
return;
}
let matrix: Matrix =
inlined_arms.iter().filter(|&&(_, guard)|
guard.is_none()).flat_map(|arm|
&arm.0).map(|pat|
<[_]>::into_vec(::std::boxed::Box::new([&**pat]))).collect();
check_exhaustive(cx, ex.span, &matrix, source);
}
_ => (),
}
}
fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt,
pat: &Pat) {
front_util::walk_pat(pat, |p| {
match p.node {
hir::PatIdent(hir::BindByValue(hir::MutImmutable),
ident, None) => {
let pat_ty = cx.tcx.pat_ty(p);
match pat_ty.sty {
ty::TyEnum(edef, _) => {
let def =
cx.tcx.def_map.borrow().get(&p.id).map(|d|
d.full_def());
match def {
Some(DefLocal(..)) => {
if edef.variants.iter().any(|variant|
variant.name
==
ident.node.name
&&
variant.kind()
==
VariantKind::Unit)
{
{
();
cx.tcx.sess.span_warn_with_code(p.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["pattern binding `",
"` is named the same as one of the variants of the type `",
"`"];
__STATIC_FMTSTR
},
&match (&ident.node,
&pat_ty)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
})),
"E0170")
};
{
(cx.tcx.sess).fileline_help(p.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["if you meant to match on a variant, consider making the path in the pattern qualified: `",
"::",
"`"];
__STATIC_FMTSTR
},
&match (&pat_ty,
&ident.node)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
})))
};
}
}
_ => (),
}
}
_ => (),
}
}
_ => (),
} true });
}
fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
front_util::walk_pat(pat, |p| {
match p.node {
hir::PatLit(ref expr) => {
match eval_const_expr_partial(cx.tcx,
&**expr,
ExprTypeChecked,
None) {
Ok(ConstVal::Float(f)) if
f.is_nan() => {
{
();
cx.tcx.sess.span_warn_with_code(p.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["unmatchable NaN in pattern, use the is_nan method in a guard instead"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0003")
};
}
Ok(_) => { }
Err(err) => {
{
();
cx.tcx.sess.span_err_with_code(err.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["constant evaluation error: "];
__STATIC_FMTSTR
},
&match (&err.description(),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0471")
};
if !p.span.contains(err.span)
{
cx.tcx.sess.span_note(p.span,
"in pattern here")
}
}
}
}
_ => (),
} true });
}
fn check_arms(cx: &MatchCheckCtxt,
arms: &[(Vec<P<Pat>>, Option<&hir::Expr>)],
source: hir::MatchSource) {
let mut seen =
Matrix(<[_]>::into_vec(::std::boxed::Box::new([])));
let mut printed_if_let_err = false;
{
let result =
match ::std::iter::IntoIterator::into_iter(arms) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(&(ref pats,
guard)) => {
{
let result =
match ::std::iter::IntoIterator::into_iter(pats)
{
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter)
{
::std::option::Option::Some(pat)
=> {
let v =
<[_]>::into_vec(::std::boxed::Box::new([&**pat]));
match is_useful(cx,
&seen,
&v[..],
LeaveOutWitness)
{
NotUseful => {
match source
{
hir::MatchSource::IfLetDesugar {
.. }
=> {
if printed_if_let_err
{
} else {
let &(ref first_arm_pats,
_) =
&arms[0];
let first_pat =
&first_arm_pats[0];
let span =
first_pat.span;
{
();
cx.tcx.sess.span_err_with_code(span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["irrefutable if-let pattern"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0162")
};
printed_if_let_err
=
true;
}
}
hir::MatchSource::WhileLetDesugar
=> {
let &(ref first_arm_pats,
_) =
&arms[0];
let first_pat =
&first_arm_pats[0];
let span =
first_pat.span;
{
();
cx.tcx.sess.span_err_with_code(span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["irrefutable while-let pattern"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0165")
};
}
hir::MatchSource::ForLoopDesugar
=> {
cx.tcx.sess.span_bug(pat.span,
"unreachable for-loop pattern")
}
hir::MatchSource::Normal
=> {
{
();
cx.tcx.sess.span_err_with_code(pat.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["unreachable pattern"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0001")
}
}
}
}
Useful => (),
UsefulWithWitness(_)
=> {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
347u32);
&_FILE_LINE
})
}
}
}
if guard.is_none()
{
let Matrix(mut rows) =
seen;
rows.push(v);
seen =
Matrix(rows);
}
}
::std::option::Option::None
=> break ,
}
},
};
result
}
}
::std::option::Option::None => break ,
}
},
};
result
}
}
fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
match p.node {
hir::PatIdent(_, _, Some(ref s)) => raw_pat(&**s),
_ => p,
}
}
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix,
source: hir::MatchSource) {
match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
UsefulWithWitness(pats) => {
let witness =
match &pats[..] {
[ref witness] => &**witness,
[] => DUMMY_WILD_PAT,
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_match.rs",
371u32);
&_FILE_LINE
})
}
}
};
match source {
hir::MatchSource::ForLoopDesugar => {
let witness =
match witness.node {
hir::PatEnum(_, Some(ref pats)) =>
match &pats[..] {
[ref pat] => &**pat,
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
379u32);
&_FILE_LINE
})
}
}
},
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
381u32);
&_FILE_LINE
})
}
}
};
{
();
cx.tcx.sess.span_err_with_code(sp,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["refutable pattern in `for` loop binding: `",
"` not covered"];
__STATIC_FMTSTR
},
&match (&pat_to_string(witness),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0297")
};
}
_ => {
{
();
cx.tcx.sess.span_err_with_code(sp,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["non-exhaustive patterns: `",
"` not covered"];
__STATIC_FMTSTR
},
&match (&pat_to_string(witness),)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt)],
})),
"E0004")
};
}
}
}
NotUseful => { }
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str, u32)
=
("src/librustc/middle/check_match.rs",
400u32);
&_FILE_LINE
})
}
}
}
}
fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
let node =
match value {
&ConstVal::Bool(b) => ast::LitBool(b),
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_match.rs",
407u32);
&_FILE_LINE
})
}
}
};
P(hir::Expr{id: 0,
node:
hir::ExprLit(P(Spanned{node: node,
span: DUMMY_SP,})),
span: DUMMY_SP,
attrs: None,})
}
pub struct StaticInliner<'a, 'tcx:'a> {
pub tcx: &'a ty::ctxt<'tcx>,
pub failed: bool,
pub renaming_map: Option<&'a mut FnvHashMap<(NodeId, Span),
NodeId>>,
}
impl <'a, 'tcx> StaticInliner<'a, 'tcx> {
pub fn new<'b>(tcx: &'b ty::ctxt<'tcx>,
renaming_map:
Option<&'b mut FnvHashMap<(NodeId, Span),
NodeId>>)
-> StaticInliner<'b, 'tcx> {
StaticInliner{tcx: tcx,
failed: false,
renaming_map: renaming_map,}
}
}
struct RenamingRecorder<'map> {
substituted_node_id: NodeId,
origin_span: Span,
renaming_map: &'map mut FnvHashMap<(NodeId, Span), NodeId>,
}
impl <'map> ast_util::IdVisitingOperation for RenamingRecorder<'map> {
fn visit_id(&mut self, node_id: NodeId) {
let key = (node_id, self.origin_span);
self.renaming_map.insert(key, self.substituted_node_id);
}
}
impl <'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
return match pat.node {
hir::PatIdent(..) | hir::PatEnum(..) |
hir::PatQPath(..) => {
let def =
self.tcx.def_map.borrow().get(&pat.id).map(|d|
d.full_def());
match def {
Some(DefAssociatedConst(did)) |
Some(DefConst(did)) =>
match lookup_const_by_id(self.tcx, did,
Some(pat.id)) {
Some(const_expr) => {
const_expr_to_pat(self.tcx,
const_expr,
pat.span).map(|new_pat|
{
match self.renaming_map
{
Some(ref mut renaming_map)
=>
{
record_renamings(const_expr,
&pat,
renaming_map);
}
_
=>
(),
}
new_pat
})
}
None => {
self.failed = true;
{
();
self.tcx.sess.span_err_with_code(pat.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["statics cannot be referenced in patterns"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0158")
};
pat
}
},
_ => noop_fold_pat(pat, self),
}
}
_ => noop_fold_pat(pat, self),
};
fn record_renamings(const_expr: &hir::Expr,
substituted_pat: &hir::Pat,
renaming_map:
&mut FnvHashMap<(NodeId, Span),
NodeId>) {
let mut renaming_recorder =
RenamingRecorder{substituted_node_id:
substituted_pat.id,
origin_span: substituted_pat.span,
renaming_map: renaming_map,};
let mut id_visitor =
front_util::IdVisitor::new(&mut renaming_recorder);
id_visitor.visit_expr(const_expr);
}
}
}
/// Constructs a partial witness for a pattern given a list of
/// patterns expanded by the specialization step.
///
/// When a pattern P is discovered to be useful, this function is used bottom-up
/// to reconstruct a complete witness, e.g. a pattern P' that covers a subset
/// of values, V, where each value in that set is not covered by any previously
/// used patterns and is covered by the pattern P'. Examples:
///
/// left_ty: tuple of 3 elements
/// pats: [10, 20, _] => (10, 20, _)
///
/// left_ty: struct X { a: (bool, &'static str), b: usize}
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
fn construct_witness<'a,
'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
ctor: &Constructor, pats: Vec<&Pat>,
left_ty: Ty<'tcx>) -> P<Pat> {
let pats_len = pats.len();
let mut pats = pats.into_iter().map(|p| P((*p).clone()));
let pat =
match left_ty.sty {
ty::TyTuple(_) => hir::PatTup(pats.collect()),
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
let v = adt.variant_of_ctor(ctor);
match v.kind() {
VariantKind::Struct => {
let field_pats: Vec<_> =
v.fields.iter().zip(pats).filter(|&(_,
ref pat)|
pat.node
!=
hir::PatWild).map(|(field,
pat)|
Spanned{span:
DUMMY_SP,
node:
hir::FieldPat{name:
field.name,
pat:
pat,
is_shorthand:
false,},}).collect();
let has_more_fields =
field_pats.len() < pats_len;
hir::PatStruct(def_to_path(cx.tcx, v.did),
field_pats, has_more_fields)
}
_ => {
hir::PatEnum(def_to_path(cx.tcx, v.did),
Some(pats.collect()))
}
}
}
ty::TyRef(_, ty::TypeAndMut { ty, mutbl }) => {
match ty.sty {
ty::TyArray(_, n) =>
match ctor {
&Single => {
{
match (&(pats_len), &(n)) {
(left_val, right_val) => {
if !(*left_val == *right_val)
{
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
541u32);
&_FILE_LINE
})
}
}
}
}
};
hir::PatVec(pats.collect(), None,
<[_]>::into_vec(::std::boxed::Box::new([])))
}
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
544u32);
&_FILE_LINE
})
}
}
},
ty::TySlice(_) =>
match ctor {
&Slice(n) => {
{
match (&(pats_len), &(n)) {
(left_val, right_val) => {
if !(*left_val == *right_val)
{
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
548u32);
&_FILE_LINE
})
}
}
}
}
};
hir::PatVec(pats.collect(), None,
<[_]>::into_vec(::std::boxed::Box::new([])))
}
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
551u32);
&_FILE_LINE
})
}
}
},
ty::TyStr => hir::PatWild,
_ => {
{
match (&(pats_len), &(1)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
556u32);
&_FILE_LINE
})
}
}
}
}
};
hir::PatRegion(pats.nth(0).unwrap(), mutbl)
}
}
}
ty::TyArray(_, len) => {
{
match (&(pats_len), &(len)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Debug::fmt)],
}),
{
static _FILE_LINE:
(&'static str,
u32)
=
("src/librustc/middle/check_match.rs",
563u32);
&_FILE_LINE
})
}
}
}
}
};
hir::PatVec(pats.collect(), None,
<[_]>::into_vec(::std::boxed::Box::new([])))
}
_ => {
match *ctor {
ConstantValue(ref v) =>
hir::PatLit(const_val_to_expr(v)),
_ => hir::PatWild,
}
}
};
P(hir::Pat{id: 0, node: pat, span: DUMMY_SP,})
}
impl <'tcx, 'container> ty::AdtDefData<'tcx, 'container> {
fn variant_of_ctor(&self, ctor: &Constructor)
-> &VariantDefData<'tcx, 'container> {
match ctor {
&Variant(vid) => self.variant_with_id(vid),
_ => self.struct_variant(),
}
}
}
fn missing_constructor(cx: &MatchCheckCtxt,
&Matrix(ref rows): &Matrix, left_ty: Ty,
max_slice_length: usize)
-> Option<Constructor> {
let used_constructors: Vec<Constructor> =
rows.iter().flat_map(|row|
pat_constructors(cx, row[0], left_ty,
max_slice_length)).collect();
all_constructors(cx, left_ty,
max_slice_length).into_iter().find(|c|
!used_constructors.contains(c))
}
/// This determines the set of all possible constructors of a pattern matching
/// values of type `left_ty`. For vectors, this would normally be an infinite set
/// but is instead bounded by the maximum fixed length of slice patterns in
/// the column of patterns being analyzed.
fn all_constructors(_cx: &MatchCheckCtxt, left_ty: Ty,
max_slice_length: usize) -> Vec<Constructor> {
match left_ty.sty {
ty::TyBool =>
[true,
false].iter().map(|b|
ConstantValue(ConstVal::Bool(*b))).collect(),
ty::TyRef(_, ty::TypeAndMut { ty, .. }) =>
match ty.sty {
ty::TySlice(_) =>
(0..max_slice_length +
1).map(|length| Slice(length)).collect(),
_ => <[_]>::into_vec(::std::boxed::Box::new([Single])),
},
ty::TyEnum(def, _) =>
def.variants.iter().map(|v| Variant(v.did)).collect(),
_ => <[_]>::into_vec(::std::boxed::Box::new([Single])),
}
}
fn is_useful(cx: &MatchCheckCtxt, matrix: &Matrix, v: &[&Pat],
witness: WitnessPreference) -> Usefulness {
let &Matrix(ref rows) = matrix;
if false {
{
static LOC: ::log::LogLocation =
::log::LogLocation{line: 643u32,
file:
"src/librustc/middle/check_match.rs",
module_path:
"rustc::middle::check_match",};
let lvl = ::log::DEBUG;
if {
let lvl = lvl;
(lvl != ::log::DEBUG || false) &&
lvl <= ::log::log_level() &&
::log::mod_enabled(lvl,
"rustc::middle::check_match")
} {
::log::log(lvl, &LOC,
::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[""];
__STATIC_FMTSTR
},
&match (&matrix,)
{
(__arg0,)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt)],
}))
}
}
};
if rows.is_empty() {
return match witness {
ConstructWitness =>
UsefulWithWitness(<[_]>::into_vec(::std::boxed::Box::new([]))),
LeaveOutWitness => Useful,
};
}
if rows[0].is_empty() { return NotUseful; }
if !rows.iter().all(|r| r.len() == v.len()) {
{
::std::rt::begin_unwind("assertion failed: rows.iter().all(|r| r.len() == v.len())",
{
static _FILE_LINE:
(&'static str, u32) =
("src/librustc/middle/check_match.rs",
653u32);
&_FILE_LINE
})
}
};
let real_pat =
match rows.iter().find(|r| (*r)[0].id != DUMMY_NODE_ID) {
Some(r) => raw_pat(r[0]),
None if v.is_empty() => return NotUseful,
None => v[0],
};
let left_ty =
if real_pat.id == DUMMY_NODE_ID {
cx.tcx.mk_nil()
} else {
let left_ty = cx.tcx.pat_ty(&*real_pat);
match real_pat.node {
hir::PatIdent(hir::BindByRef(..), _, _) => {
left_ty.builtin_deref(false,
NoPreference).unwrap().ty
}
_ => left_ty,
}
};
let max_slice_length =
rows.iter().filter_map(|row|
match row[0].node {
hir::PatVec(ref before, _,
ref after) =>
Some(before.len() +
after.len()),
_ => None,
}).max().map_or(0, |v| v + 1);
let constructors =
pat_constructors(cx, v[0], left_ty, max_slice_length);
if constructors.is_empty() {
match missing_constructor(cx, matrix, left_ty,
max_slice_length) {
None => {
all_constructors(cx, left_ty,
max_slice_length).into_iter().map(|c|
{
match is_useful_specialized(cx,
matrix,
v,
c.clone(),
left_ty,
witness)
{
UsefulWithWitness(pats)
=>
UsefulWithWitness({
let arity =
constructor_arity(cx,
&c,
left_ty);
let mut result =
{
let pat_slice =
&pats[..];
let subpats:
Vec<_> =
(0..arity).map(|i|
{
pat_slice.get(i).map_or(DUMMY_WILD_PAT,
|p|
&**p)
}).collect();
<[_]>::into_vec(::std::boxed::Box::new([construct_witness(cx,
&c,
subpats,
left_ty)]))
};
result.extend(pats.into_iter().skip(arity));
result
}),
result
=>
result,
}
}).find(|result|
result
!=
&NotUseful).unwrap_or(NotUseful)
}
Some(constructor) => {
let matrix =
rows.iter().filter_map(|r| {
if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(),
raw_pat(r[0]))
{
Some(r[1..].to_vec())
} else { None }
}).collect();
match is_useful(cx, &matrix, &v[1..], witness) {
UsefulWithWitness(pats) => {
let arity =
constructor_arity(cx, &constructor,
left_ty);
let wild_pats =
::std::vec::from_elem(DUMMY_WILD_PAT,
arity);
let enum_pat =
construct_witness(cx, &constructor,
wild_pats, left_ty);
let mut new_pats =
<[_]>::into_vec(::std::boxed::Box::new([enum_pat]));
new_pats.extend(pats);
UsefulWithWitness(new_pats)
}
result => result,
}
}
}
} else {
constructors.into_iter().map(|c|
is_useful_specialized(cx,
matrix,
v,
c.clone(),
left_ty,
witness)).find(|result|
result
!=
&NotUseful).unwrap_or(NotUseful)
}
}
fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix,
v: &[&Pat], ctor: Constructor, lty: Ty,
witness: WitnessPreference) -> Usefulness {
let arity = constructor_arity(cx, &ctor, lty);
let matrix =
Matrix(m.iter().filter_map(|r| {
specialize(cx, &r[..], &ctor, 0,
arity) }).collect());
match specialize(cx, v, &ctor, 0, arity) {
Some(v) => is_useful(cx, &matrix, &v[..], witness),
None => NotUseful,
}
}
/// Determines the constructors that the given pattern can be specialized to.
///
/// In most cases, there's only one constructor that a specific pattern
/// represents, such as a specific enum variant or a specific literal value.
/// Slice patterns, however, can match slices of different lengths. For instance,
/// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on.
///
/// On the other hand, a wild pattern and an identifier pattern cannot be
/// specialized in any way.
fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, left_ty: Ty,
max_slice_length: usize) -> Vec<Constructor> {
let pat = raw_pat(p);
match pat.node {
hir::PatIdent(..) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d|
d.full_def())
{
Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
cx.tcx.sess.span_bug(pat.span,
"const pattern should\'ve been rewritten"),
Some(DefStruct(_)) =>
<[_]>::into_vec(::std::boxed::Box::new([Single])),
Some(DefVariant(_, id, _)) =>
<[_]>::into_vec(::std::boxed::Box::new([Variant(id)])),
_ => <[_]>::into_vec(::std::boxed::Box::new([])),
},
hir::PatEnum(..) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d|
d.full_def())
{
Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
cx.tcx.sess.span_bug(pat.span,
"const pattern should\'ve been rewritten"),
Some(DefVariant(_, id, _)) =>
<[_]>::into_vec(::std::boxed::Box::new([Variant(id)])),
_ => <[_]>::into_vec(::std::boxed::Box::new([Single])),
},
hir::PatQPath(..) =>
cx.tcx.sess.span_bug(pat.span,
"const pattern should\'ve been rewritten"),
hir::PatStruct(..) =>
match cx.tcx.def_map.borrow().get(&pat.id).map(|d|
d.full_def())
{
Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
cx.tcx.sess.span_bug(pat.span,
"const pattern should\'ve been rewritten"),
Some(DefVariant(_, id, _)) =>
<[_]>::into_vec(::std::boxed::Box::new([Variant(id)])),
_ => <[_]>::into_vec(::std::boxed::Box::new([Single])),
},
hir::PatLit(ref expr) =>
<[_]>::into_vec(::std::boxed::Box::new([ConstantValue(eval_const_expr(cx.tcx,
&**expr))])),
hir::PatRange(ref lo, ref hi) =>
<[_]>::into_vec(::std::boxed::Box::new([ConstantRange(eval_const_expr(cx.tcx,
&**lo),
eval_const_expr(cx.tcx,
&**hi))])),
hir::PatVec(ref before, ref slice, ref after) =>
match left_ty.sty {
ty::TyArray(_, _) =>
<[_]>::into_vec(::std::boxed::Box::new([Single])),
_ =>
if slice.is_some() {
(before.len() +
after.len()..max_slice_length +
1).map(|length|
Slice(length)).collect()
} else {
<[_]>::into_vec(::std::boxed::Box::new([Slice(before.len()
+
after.len())]))
},
},
hir::PatBox(_) | hir::PatTup(_) | hir::PatRegion(..) =>
<[_]>::into_vec(::std::boxed::Box::new([Single])),
hir::PatWild => <[_]>::into_vec(::std::boxed::Box::new([])),
}
}
/// This computes the arity of a constructor. The arity of a constructor
/// is how many subpattern patterns of that constructor should be expanded to.
///
/// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3.
/// A struct pattern's arity is the number of fields it contains, etc.
pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor,
ty: Ty) -> usize {
match ty.sty {
ty::TyTuple(ref fs) => fs.len(),
ty::TyBox(_) => 1,
ty::TyRef(_, ty::TypeAndMut { ty, .. }) =>
match ty.sty {
ty::TySlice(_) =>
match *ctor {
Slice(length) => length,
ConstantValue(_) => 0,
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_match.rs",
817u32);
&_FILE_LINE
})
}
}
},
ty::TyStr => 0,
_ => 1,
},
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
adt.variant_of_ctor(ctor).fields.len()
}
ty::TyArray(_, n) => n,
_ => 0,
}
}
fn range_covered_by_constructor(ctor: &Constructor, from: &ConstVal,
to: &ConstVal) -> Option<bool> {
let (c_from, c_to) =
match *ctor {
ConstantValue(ref value) => (value, value),
ConstantRange(ref from, ref to) => (from, to),
Single => return Some(true),
_ => {
{
::std::rt::begin_unwind("internal error: entered unreachable code",
{
static _FILE_LINE:
(&'static str,
u32) =
("src/librustc/middle/check_match.rs",
836u32);
&_FILE_LINE
})
}
}
};
let cmp_from = compare_const_vals(c_from, from);
let cmp_to = compare_const_vals(c_to, to);
match (cmp_from, cmp_to) {
(Some(cmp_from), Some(cmp_to)) => {
Some(cmp_from != Ordering::Less &&
cmp_to != Ordering::Greater)
}
_ => None,
}
}
/// This is the main specialization step. It expands the first pattern in the given row
/// into `arity` patterns based on the constructor. For most patterns, the step is trivial,
/// for instance tuple patterns are flattened and box patterns expand into their inner pattern.
///
/// OTOH, slice patterns with a subslice pattern (..tail) can be expanded into multiple
/// different patterns.
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
/// fields filled with wild patterns.
pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
constructor: &Constructor, col: usize,
arity: usize) -> Option<Vec<&'a Pat>> {
let &Pat { id: pat_id, ref node, span: pat_span } =
raw_pat(r[col]);
let head: Option<Vec<&Pat>> =
match *node {
hir::PatWild =>
Some(::std::vec::from_elem(DUMMY_WILD_PAT, arity)),
hir::PatIdent(_, _, _) => {
let opt_def =
cx.tcx.def_map.borrow().get(&pat_id).map(|d|
d.full_def());
match opt_def {
Some(DefConst(..)) | Some(DefAssociatedConst(..))
=>
cx.tcx.sess.span_bug(pat_span,
"const pattern should\'ve been rewritten"),
Some(DefVariant(_, id, _)) =>
if *constructor == Variant(id) {
Some(<[_]>::into_vec(::std::boxed::Box::new([])))
} else { None },
_ =>
Some(::std::vec::from_elem(DUMMY_WILD_PAT,
arity)),
}
}
hir::PatEnum(_, ref args) => {
let def =
cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
match def {
DefConst(..) | DefAssociatedConst(..) =>
cx.tcx.sess.span_bug(pat_span,
"const pattern should\'ve been rewritten"),
DefVariant(_, id, _) if
*constructor != Variant(id) => None,
DefVariant(..) | DefStruct(..) => {
Some(match args {
&Some(ref args) =>
args.iter().map(|p| &**p).collect(),
&None =>
::std::vec::from_elem(DUMMY_WILD_PAT,
arity),
})
}
_ => None,
}
}
hir::PatQPath(_, _) => {
cx.tcx.sess.span_bug(pat_span,
"const pattern should\'ve been rewritten")
}
hir::PatStruct(_, ref pattern_fields, _) => {
let def =
cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
let adt =
cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
let variant = adt.variant_of_ctor(constructor);
let def_variant = adt.variant_of_def(def);
if variant.did == def_variant.did {
Some(variant.fields.iter().map(|sf| {
match pattern_fields.iter().find(|f|
f.node.name
==
sf.name)
{
Some(ref f) =>
&*f.node.pat,
_ =>
DUMMY_WILD_PAT,
} }).collect())
} else { None }
}
hir::PatTup(ref args) =>
Some(args.iter().map(|p| &**p).collect()),
hir::PatBox(ref inner) | hir::PatRegion(ref inner, _) =>
Some(<[_]>::into_vec(::std::boxed::Box::new([&**inner]))),
hir::PatLit(ref expr) => {
let expr_value = eval_const_expr(cx.tcx, &**expr);
match range_covered_by_constructor(constructor,
&expr_value,
&expr_value) {
Some(true) =>
Some(<[_]>::into_vec(::std::boxed::Box::new([]))),
Some(false) => None,
None => {
{
();
cx.tcx.sess.span_err_with_code(pat_span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mismatched types between arms"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0298")
};
None
}
}
}
hir::PatRange(ref from, ref to) => {
let from_value = eval_const_expr(cx.tcx, &**from);
let to_value = eval_const_expr(cx.tcx, &**to);
match range_covered_by_constructor(constructor,
&from_value,
&to_value) {
Some(true) =>
Some(<[_]>::into_vec(::std::boxed::Box::new([]))),
Some(false) => None,
None => {
{
();
cx.tcx.sess.span_err_with_code(pat_span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["mismatched types between arms"];
__STATIC_FMTSTR
},
&match ()
{
()
=>
[],
})),
"E0299")
};
None
}
}
}
hir::PatVec(ref before, ref slice, ref after) => {
match *constructor {
Single => {
let mut pats: Vec<&Pat> =
before.iter().map(|p| &**p).collect();
pats.extend(repeat(DUMMY_WILD_PAT).take(arity
-
before.len()
-
after.len()));
pats.extend(after.iter().map(|p| &**p));
Some(pats)
}
Slice(length) if
before.len() + after.len() <= length &&
slice.is_some() => {
let mut pats: Vec<&Pat> =
before.iter().map(|p| &**p).collect();
pats.extend(repeat(DUMMY_WILD_PAT).take(arity
-
before.len()
-
after.len()));
pats.extend(after.iter().map(|p| &**p));
Some(pats)
}
Slice(length) if
before.len() + after.len() == length => {
let mut pats: Vec<&Pat> =
before.iter().map(|p| &**p).collect();
pats.extend(after.iter().map(|p| &**p));
Some(pats)
}
SliceWithSubslice(prefix, suffix) if
before.len() == prefix && after.len() == suffix &&
slice.is_some() => {
let mut pats: Vec<&Pat> =
before.iter().map(|p| &**p).collect();
pats.extend(after.iter().map(|p| &**p));
Some(pats)
}
_ => None,
}
}
};
head.map(|mut head| { head.extend_from_slice(&r[..col]);
head.extend_from_slice(&r[col + 1..]); head })
}
fn check_local(cx: &mut MatchCheckCtxt, loc: &hir::Local) {
intravisit::walk_local(cx, loc);
let pat =
StaticInliner::new(cx.tcx, None).fold_pat(loc.pat.clone());
check_irrefutable(cx, &pat, false);
check_legality_of_move_bindings(cx, false,
slice::ref_slice(&loc.pat));
check_legality_of_bindings_in_at_patterns(cx, &*loc.pat);
}
fn check_fn(cx: &mut MatchCheckCtxt, kind: FnKind, decl: &hir::FnDecl,
body: &hir::Block, sp: Span, fn_id: NodeId) {
match kind {
FnKind::Closure => { }
_ =>
cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id),
}
intravisit::walk_fn(cx, kind, decl, body, sp);
{
let result =
match ::std::iter::IntoIterator::into_iter(&decl.inputs) {
mut iter =>
loop {
match ::std::iter::Iterator::next(&mut iter) {
::std::option::Option::Some(input) => {
check_irrefutable(cx, &input.pat, true);
check_legality_of_move_bindings(cx, false,
slice::ref_slice(&input.pat));
check_legality_of_bindings_in_at_patterns(cx,
&*input.pat);
}
::std::option::Option::None => break ,
}
},
};
result
}
}
fn check_irrefutable(cx: &MatchCheckCtxt, pat: &Pat,
is_fn_arg: bool) {
let origin =
if is_fn_arg { "function argument" } else { "local binding" };
is_refutable(cx, pat, |uncovered_pat| {
{
();
cx.tcx.sess.span_err_with_code(pat.span,
&::std::fmt::format(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["refutable pattern in ",
": `",
"` not covered"];
__STATIC_FMTSTR
},
&match (&origin,
&pat_to_string(uncovered_pat))
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Display::fmt),
::std::fmt::ArgumentV1::new(__arg1,
::std::fmt::Display::fmt)],
})),
"E0005")
}; });
}
fn is_refutable<A, F>(cx: &MatchCheckCtxt, pat: &Pat, refutable: F)
-> Option<A> where F: FnOnce(&Pat) -> A {
let pats =
Matrix(<[_]>::into_vec(::std::boxed::Box::new([<[_]>::into_vec(::std::boxed::Box::new([pat]))])));
match is_useful(cx, &pats, &[DUMMY_WILD_PAT], ConstructWitness) {
UsefulWithWitness(pats) => {
{
match (&(pats.len()), &(1)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
{
::std::rt::begin_unwind_fmt(::std::fmt::Arguments::new_v1({
static __STATIC_FMTSTR:
&'static [&'static str]
=
&["assertion failed: `(left == right)` (left: `",
"`, right: `",
"`)"];
__STATIC_FMTSTR
},
&match (&left_val,
&right_val)
{
(__arg0,
__arg1)
=>
[::std::fmt::ArgumentV1::new(__arg0,
::std::fmt::Debug::fmt),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.