rustc_data_structures rustc_platform_intrinsics rustc_errors \
rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \
rustc_const_eval rustc_const_math rustc_incremental
-HOST_CRATES := syntax syntax_ext syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \
+HOST_CRATES := syntax syntax_ext proc_macro syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \
flate arena graphviz rbml log serialize
TOOLS := compiletest rustdoc rustc rustbook error_index_generator
DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode rustc_errors syntax_pos
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros
+DEPS_proc_macro := syntax syntax_pos rustc_plugin log
DEPS_syntax_pos := serialize
DEPS_rustc_const_math := std syntax log serialize
DEPS_rustc_data_structures := std log serialize
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
- rustc_trans rustc_privacy rustc_lint rustc_plugin \
- rustc_metadata syntax_ext rustc_passes rustc_save_analysis rustc_const_eval \
+ rustc_trans rustc_privacy rustc_lint rustc_plugin \
+ rustc_metadata syntax_ext proc_macro \
+ rustc_passes rustc_save_analysis rustc_const_eval \
rustc_incremental syntax_pos rustc_errors
DEPS_rustc_errors := log libc serialize syntax_pos
DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
use core::mem;
use core::ops::{Index, IndexMut};
use core::ptr;
+use core::ptr::Shared;
use core::slice;
use core::hash::{Hash, Hasher};
self.head = drain_tail;
Drain {
- deque: self as *mut _,
+ deque: unsafe { Shared::new(self as *mut _) },
after_tail: drain_head,
after_head: head,
iter: Iter {
after_tail: usize,
after_head: usize,
iter: Iter<'a, T>,
- deque: *mut VecDeque<T>,
+ deque: Shared<VecDeque<T>>,
}
#[stable(feature = "drain", since = "1.6.0")]
fn drop(&mut self) {
for _ in self.by_ref() {}
- let source_deque = unsafe { &mut *self.deque };
+ let source_deque = unsafe { &mut **self.deque };
// T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head
//
assert_eq!(xs.iter_mut().size_hint(), (5, Some(5)));
}
+#[test]
+fn test_iter_as_slice() {
+ let xs = [1, 2, 5, 10, 11];
+ let mut iter = xs.iter();
+ assert_eq!(iter.as_slice(), &[1, 2, 5, 10, 11]);
+ iter.next();
+ assert_eq!(iter.as_slice(), &[2, 5, 10, 11]);
+}
+
+#[test]
+fn test_iter_as_ref() {
+ let xs = [1, 2, 5, 10, 11];
+ let mut iter = xs.iter();
+ assert_eq!(iter.as_ref(), &[1, 2, 5, 10, 11]);
+ iter.next();
+ assert_eq!(iter.as_ref(), &[2, 5, 10, 11]);
+}
+
#[test]
fn test_iter_clone() {
let xs = [1, 2, 5];
use std::collections::VecDeque;
use std::fmt::Debug;
+use std::collections::vec_deque::Drain;
use test;
assert!(!v.contains(&3));
}
+
+#[allow(dead_code)]
+fn assert_covariance() {
+ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
+}
use cmp::{Ordering, PartialEq, PartialOrd, Eq, Ord};
use cmp::Ordering::{Less, Equal, Greater};
use cmp;
+use convert::AsRef;
use default::Default;
use fmt;
use intrinsics::assume;
fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
}
+#[stable(feature = "slice_iter_as_ref", since = "1.12.0")]
+impl<'a, T> AsRef<[T]> for Iter<'a, T> {
+ fn as_ref(&self) -> &[T] {
+ self.as_slice()
+ }
+}
+
/// Mutable slice iterator.
///
/// This struct is created by the [`iter_mut`] method on [slices].
--- /dev/null
+[package]
+authors = ["The Rust Project Developers"]
+name = "proc_macro"
+version = "0.0.0"
+
+[lib]
+name = "proc_macro"
+path = "lib.rs"
+crate-type = ["dylib"]
+
+[dependencies]
+log = { path = "../liblog" }
+rustc_plugin = { path = "../librustc_plugin" }
+syntax = { path = "../libsyntax" }
+syntax_pos = { path = "../libsyntax_pos" }
--- /dev/null
+// Copyright 2016 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.
+
+extern crate syntax;
+extern crate syntax_pos;
+
+use syntax::ast::Ident;
+use syntax::codemap::DUMMY_SP;
+use syntax::parse::token::{self, Token, keywords, str_to_ident};
+use syntax::tokenstream::{self, TokenTree, TokenStream};
+use std::rc::Rc;
+
+/// A wrapper around `TokenStream::concat` to avoid extra namespace specification and
+/// provide TokenStream concatenation as a generic operator.
+pub fn concat(ts1: TokenStream, ts2: TokenStream) -> TokenStream {
+ TokenStream::concat(ts1, ts2)
+}
+
+/// Checks if two identifiers have the same name, disregarding context. This allows us to
+/// fake 'reserved' keywords.
+// FIXME We really want `free-identifier-=?` (a la Dybvig 1993). von Tander 2007 is
+// probably the easiest way to do that.
+pub fn ident_eq(tident: &TokenTree, id: Ident) -> bool {
+ let tid = match *tident {
+ TokenTree::Token(_, Token::Ident(ref id)) => id,
+ _ => {
+ return false;
+ }
+ };
+
+ tid.name == id.name
+}
+
+// ____________________________________________________________________________________________
+// Conversion operators
+
+/// Convert a `&str` into a Token.
+pub fn str_to_token_ident(s: &str) -> Token {
+ Token::Ident(str_to_ident(s))
+}
+
+/// Converts a keyword (from `syntax::parse::token::keywords`) into a Token that
+/// corresponds to it.
+pub fn keyword_to_token_ident(kw: keywords::Keyword) -> Token {
+ Token::Ident(str_to_ident(&kw.name().as_str()[..]))
+}
+
+// ____________________________________________________________________________________________
+// Build Procedures
+
+/// Generically takes a `ts` and delimiter and returns `ts` delimited by the specified
+/// delimiter.
+pub fn build_delimited(ts: TokenStream, delim: token::DelimToken) -> TokenStream {
+ let tts = ts.to_tts();
+ TokenStream::from_tts(vec![TokenTree::Delimited(DUMMY_SP,
+ Rc::new(tokenstream::Delimited {
+ delim: delim,
+ open_span: DUMMY_SP,
+ tts: tts,
+ close_span: DUMMY_SP,
+ }))])
+}
+
+/// Takes `ts` and returns `[ts]`.
+pub fn build_bracket_delimited(ts: TokenStream) -> TokenStream {
+ build_delimited(ts, token::DelimToken::Bracket)
+}
+
+/// Takes `ts` and returns `{ts}`.
+pub fn build_brace_delimited(ts: TokenStream) -> TokenStream {
+ build_delimited(ts, token::DelimToken::Brace)
+}
+
+/// Takes `ts` and returns `(ts)`.
+pub fn build_paren_delimited(ts: TokenStream) -> TokenStream {
+ build_delimited(ts, token::DelimToken::Paren)
+}
+
+/// Constructs `()`.
+pub fn build_empty_args() -> TokenStream {
+ build_paren_delimited(TokenStream::mk_empty())
+}
--- /dev/null
+// Copyright 2016 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.
+
+//! # Proc_Macro
+//!
+//! A library for procedural macro writers.
+//!
+//! ## Usage
+//! This package provides the `qquote!` macro for syntax creation, and the prelude
+//! (at libproc_macro::prelude) provides a number of operations:
+//! - `concat`, for concatenating two TokenStreams.
+//! - `ident_eq`, for checking if two identifiers are equal regardless of syntax context.
+//! - `str_to_token_ident`, for converting an `&str` into a Token.
+//! - `keyword_to_token_delim`, for converting a `parse::token::keywords::Keyword` into a
+//! Token.
+//! - `build_delimited`, for creating a new TokenStream from an existing one and a delimiter
+//! by wrapping the TokenStream in the delimiter.
+//! - `build_bracket_delimited`, `build_brace_delimited`, and `build_paren_delimited`, for
+//! easing the above.
+//! - `build_empty_args`, which returns a TokenStream containing `()`.
+//! - `lex`, which takes an `&str` and returns the TokenStream it represents.
+//!
+//! The `qquote!` macro also imports `syntax::ext::proc_macro_shim::prelude::*`, so you
+//! will need to `extern crate syntax` for usage. (This is a temporary solution until more
+//! of the external API in libproc_macro is stabilized to support the token construction
+//! operations that the qausiquoter relies on.) The shim file also provides additional
+//! operations, such as `build_block_emitter` (as used in the `cond` example below).
+//!
+//! ## TokenStreams
+//!
+//! TokenStreams serve as the basis of the macro system. They are, in essence, vectors of
+//! TokenTrees, where indexing treats delimited values as a single term. That is, the term
+//! `even(a+c) && even(b)` will be indexibly encoded as `even | (a+c) | even | (b)` where,
+//! in reality, `(a+c)` is actually a decorated pointer to `a | + | c`.
+//!
+//! If a user has a TokenStream that is a single, delimited value, they can use
+//! `maybe_delimited` to destruct it and receive the internal vector as a new TokenStream
+//! as:
+//! ```
+//! `(a+c)`.maybe_delimited() ~> Some(a | + | c)`
+//! ```
+//!
+//! Check the TokenStream documentation for more information; the structure also provides
+//! cheap concatenation and slicing.
+//!
+//! ## Quasiquotation
+//!
+//! The quasiquoter creates output that, when run, constructs the tokenstream specified as
+//! input. For example, `qquote!(5 + 5)` will produce a program, that, when run, will
+//! construct the TokenStream `5 | + | 5`.
+//!
+//! ### Unquoting
+//!
+//! Unquoting is currently done as `unquote`, and works by taking the single next
+//! TokenTree in the TokenStream as the unquoted term. Ergonomically, `unquote(foo)` works
+//! fine, but `unquote foo` is also supported.
+//!
+//! A simple example might be:
+//!
+//!```
+//!fn double(tmp: TokenStream) -> TokenStream {
+//! qquote!(unquote(tmp) * 2)
+//!}
+//!```
+//!
+//! ### Large Example: Implementing Scheme's `cond`
+//!
+//! Below is the full implementation of Scheme's `cond` operator.
+//!
+//! ```
+//! fn cond_rec(input: TokenStream) -> TokenStream {
+//! if input.is_empty() { return quote!(); }
+//!
+//! let next = input.slice(0..1);
+//! let rest = input.slice_from(1..);
+//!
+//! let clause : TokenStream = match next.maybe_delimited() {
+//! Some(ts) => ts,
+//! _ => panic!("Invalid input"),
+//! };
+//!
+//! // clause is ([test]) [rhs]
+//! if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) }
+//!
+//! let test: TokenStream = clause.slice(0..1);
+//! let rhs: TokenStream = clause.slice_from(1..);
+//!
+//! if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
+//! quote!({unquote(rhs)})
+//! } else {
+//! quote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
+//! }
+//! }
+//! ```
+//!
+
+#![crate_name = "proc_macro"]
+#![unstable(feature = "rustc_private", issue = "27812")]
+#![feature(plugin_registrar)]
+#![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/")]
+#![cfg_attr(not(stage0), deny(warnings))]
+
+#![feature(staged_api)]
+#![feature(rustc_diagnostic_macros)]
+#![feature(rustc_private)]
+
+extern crate rustc_plugin;
+extern crate syntax;
+extern crate syntax_pos;
+#[macro_use] extern crate log;
+
+mod qquote;
+pub mod build;
+pub mod parse;
+pub mod prelude;
+use qquote::qquote;
+
+use rustc_plugin::Registry;
+
+// ____________________________________________________________________________________________
+// Main macro definition
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("qquote", qquote);
+}
--- /dev/null
+// Copyright 2016 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.
+
+//! Parsing utilities for writing procedural macros.
+
+extern crate syntax;
+
+use syntax::parse::{ParseSess, filemap_to_tts};
+use syntax::tokenstream::TokenStream;
+
+/// Map a string to tts, using a made-up filename. For example, `lex(15)` will return a
+/// TokenStream containing the literal 15.
+pub fn lex(source_str: &str) -> TokenStream {
+ let ps = ParseSess::new();
+ TokenStream::from_tts(filemap_to_tts(&ps,
+ ps.codemap().new_filemap("procmacro_lex".to_string(),
+ None,
+ source_str.to_owned())))
+}
--- /dev/null
+// Copyright 2016 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.
+
+pub use build::*;
+pub use parse::*;
--- /dev/null
+// Copyright 2016 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.
+
+//! # Quasiquoter
+//! This file contains the implementation internals of the quasiquoter provided by `quote!`.
+//!
+//! ## Ouput
+//! The quasiquoter produces output of the form:
+//! let tmp0 = ...;
+//! let tmp1 = ...;
+//! ...
+//! concat(from_tokens(...), concat(...))
+//!
+//! To the more explicit, the quasiquoter produces a series of bindings that each
+//! construct TokenStreams via constructing Tokens and using `from_tokens`, ultimately
+//! invoking `concat` on these bindings (and inlined expressions) to construct a
+//! TokenStream that resembles the output syntax.
+//!
+
+extern crate rustc_plugin;
+extern crate syntax;
+extern crate syntax_pos;
+
+use build::*;
+use parse::lex;
+use qquote::int_build::*;
+
+use syntax::ast::Ident;
+use syntax::codemap::Span;
+use syntax::ext::base::*;
+use syntax::ext::base;
+use syntax::ext::proc_macro_shim::build_block_emitter;
+use syntax::parse::token::{self, Token, gensym_ident, str_to_ident};
+use syntax::print::pprust;
+use syntax::tokenstream::{TokenTree, TokenStream};
+
+// ____________________________________________________________________________________________
+// Main definition
+/// The user should use the macro, not this procedure.
+pub fn qquote<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
+ -> Box<base::MacResult + 'cx> {
+
+ debug!("\nTTs in: {:?}\n", pprust::tts_to_string(&tts[..]));
+ let output = qquoter(cx, TokenStream::from_tts(tts.clone().to_owned()));
+ debug!("\nQQ out: {}\n", pprust::tts_to_string(&output.to_tts()[..]));
+ let imports = concat(lex("use syntax::ext::proc_macro_shim::prelude::*;"),
+ lex("use proc_macro::prelude::*;"));
+ build_block_emitter(cx, sp, build_brace_delimited(concat(imports, output)))
+}
+
+// ____________________________________________________________________________________________
+// Datatype Definitions
+
+#[derive(Debug)]
+struct QDelimited {
+ delim: token::DelimToken,
+ open_span: Span,
+ tts: Vec<QTT>,
+ close_span: Span,
+}
+
+#[derive(Debug)]
+enum QTT {
+ TT(TokenTree),
+ QDL(QDelimited),
+ QIdent(TokenTree),
+}
+
+type Bindings = Vec<(Ident, TokenStream)>;
+
+// ____________________________________________________________________________________________
+// Quasiquoter Algorithm
+// This algorithm works as follows:
+// Input: TokenStream
+// 1. Walk the TokenStream, gathering up the unquoted expressions and marking them separately.
+// 2. Hoist any unquoted term into its own let-binding via a gensym'd identifier
+// 3. Convert the body from a `complex expression` into a simplified one via `convert_complex_tts
+// 4. Stitch everything together with `concat`.
+fn qquoter<'cx>(cx: &'cx mut ExtCtxt, ts: TokenStream) -> TokenStream {
+ if ts.is_empty() {
+ return lex("TokenStream::mk_empty()");
+ }
+ let qq_res = qquote_iter(cx, 0, ts);
+ let mut bindings = qq_res.0;
+ let body = qq_res.1;
+ let mut cct_res = convert_complex_tts(cx, body);
+
+ bindings.append(&mut cct_res.0);
+
+ if bindings.is_empty() {
+ cct_res.1
+ } else {
+ debug!("BINDINGS");
+ for b in bindings.clone() {
+ debug!("{:?} = {}", b.0, pprust::tts_to_string(&b.1.to_tts()[..]));
+ }
+ TokenStream::concat(unravel(bindings), cct_res.1)
+ }
+}
+
+fn qquote_iter<'cx>(cx: &'cx mut ExtCtxt, depth: i64, ts: TokenStream) -> (Bindings, Vec<QTT>) {
+ let mut depth = depth;
+ let mut bindings: Bindings = Vec::new();
+ let mut output: Vec<QTT> = Vec::new();
+
+ let mut iter = ts.iter();
+
+ loop {
+ let next = iter.next();
+ if next.is_none() {
+ break;
+ }
+ let next = next.unwrap().clone();
+ match next {
+ TokenTree::Token(_, Token::Ident(id)) if is_unquote(id) => {
+ if depth == 0 {
+ let exp = iter.next();
+ if exp.is_none() {
+ break;
+ } // produce an error or something first
+ let exp = vec![exp.unwrap().to_owned()];
+ debug!("RHS: {:?}", exp.clone());
+ let new_id = gensym_ident("tmp");
+ debug!("RHS TS: {:?}", TokenStream::from_tts(exp.clone()));
+ debug!("RHS TS TT: {:?}", TokenStream::from_tts(exp.clone()).to_vec());
+ bindings.push((new_id, TokenStream::from_tts(exp)));
+ debug!("BINDINGS");
+ for b in bindings.clone() {
+ debug!("{:?} = {}", b.0, pprust::tts_to_string(&b.1.to_tts()[..]));
+ }
+ output.push(QTT::QIdent(as_tt(Token::Ident(new_id.clone()))));
+ } else {
+ depth = depth - 1;
+ output.push(QTT::TT(next.clone()));
+ }
+ }
+ TokenTree::Token(_, Token::Ident(id)) if is_qquote(id) => {
+ depth = depth + 1;
+ }
+ TokenTree::Delimited(_, ref dl) => {
+ let br = qquote_iter(cx, depth, TokenStream::from_tts(dl.tts.clone().to_owned()));
+ let mut bind_ = br.0;
+ let res_ = br.1;
+ bindings.append(&mut bind_);
+
+ let new_dl = QDelimited {
+ delim: dl.delim,
+ open_span: dl.open_span,
+ tts: res_,
+ close_span: dl.close_span,
+ };
+
+ output.push(QTT::QDL(new_dl));
+ }
+ t => {
+ output.push(QTT::TT(t));
+ }
+ }
+ }
+
+ (bindings, output)
+}
+
+// ____________________________________________________________________________________________
+// Turns QQTs into a TokenStream and some Bindings.
+/// Construct a chain of concatenations.
+fn unravel_concats(tss: Vec<TokenStream>) -> TokenStream {
+ let mut pushes: Vec<TokenStream> =
+ tss.into_iter().filter(|&ref ts| !ts.is_empty()).collect();
+ let mut output = match pushes.pop() {
+ Some(ts) => ts,
+ None => {
+ return TokenStream::mk_empty();
+ }
+ };
+
+ while let Some(ts) = pushes.pop() {
+ output = build_fn_call(str_to_ident("concat"),
+ concat(concat(ts,
+ from_tokens(vec![Token::Comma])),
+ output));
+ }
+ output
+}
+
+/// This converts the vector of QTTs into a seet of Bindings for construction and the main
+/// body as a TokenStream.
+fn convert_complex_tts<'cx>(cx: &'cx mut ExtCtxt, tts: Vec<QTT>) -> (Bindings, TokenStream) {
+ let mut pushes: Vec<TokenStream> = Vec::new();
+ let mut bindings: Bindings = Vec::new();
+
+ let mut iter = tts.into_iter();
+
+ loop {
+ let next = iter.next();
+ if next.is_none() {
+ break;
+ }
+ let next = next.unwrap();
+ match next {
+ QTT::TT(TokenTree::Token(_, t)) => {
+ let token_out = emit_token(t);
+ pushes.push(token_out);
+ }
+ // FIXME handle sequence repetition tokens
+ QTT::QDL(qdl) => {
+ debug!(" QDL: {:?} ", qdl.tts);
+ let new_id = gensym_ident("qdl_tmp");
+ let mut cct_rec = convert_complex_tts(cx, qdl.tts);
+ bindings.append(&mut cct_rec.0);
+ bindings.push((new_id, cct_rec.1));
+
+ let sep = build_delim_tok(qdl.delim);
+
+ pushes.push(build_mod_call(vec![str_to_ident("proc_macro"),
+ str_to_ident("build"),
+ str_to_ident("build_delimited")],
+ concat(from_tokens(vec![Token::Ident(new_id)]),
+ concat(lex(","), sep))));
+ }
+ QTT::QIdent(t) => {
+ pushes.push(TokenStream::from_tts(vec![t]));
+ pushes.push(TokenStream::mk_empty());
+ }
+ _ => panic!("Unhandled case!"),
+ }
+
+ }
+
+ (bindings, unravel_concats(pushes))
+}
+
+// ____________________________________________________________________________________________
+// Utilities
+
+/// Unravels Bindings into a TokenStream of `let` declarations.
+fn unravel(binds: Bindings) -> TokenStream {
+ let mut output = TokenStream::mk_empty();
+
+ for b in binds {
+ output = concat(output, build_let(b.0, b.1));
+ }
+
+ output
+}
+
+/// Checks if the Ident is `unquote`.
+fn is_unquote(id: Ident) -> bool {
+ let qq = str_to_ident("unquote");
+ id.name == qq.name // We disregard context; unquote is _reserved_
+}
+
+/// Checks if the Ident is `quote`.
+fn is_qquote(id: Ident) -> bool {
+ let qq = str_to_ident("qquote");
+ id.name == qq.name // We disregard context; qquote is _reserved_
+}
+
+mod int_build {
+ extern crate syntax;
+ extern crate syntax_pos;
+
+ use parse::*;
+ use build::*;
+
+ use syntax::ast::{self, Ident};
+ use syntax::codemap::{DUMMY_SP};
+ use syntax::parse::token::{self, Token, keywords, str_to_ident};
+ use syntax::tokenstream::{TokenTree, TokenStream};
+
+ // ____________________________________________________________________________________________
+ // Emitters
+
+ pub fn emit_token(t: Token) -> TokenStream {
+ concat(lex("TokenStream::from_tokens"),
+ build_paren_delimited(build_vec(build_token_tt(t))))
+ }
+
+ pub fn emit_lit(l: token::Lit, n: Option<ast::Name>) -> TokenStream {
+ let suf = match n {
+ Some(n) => format!("Some(ast::Name({}))", n.0),
+ None => "None".to_string(),
+ };
+
+ let lit = match l {
+ token::Lit::Byte(n) => format!("Lit::Byte(token::intern(\"{}\"))", n.to_string()),
+ token::Lit::Char(n) => format!("Lit::Char(token::intern(\"{}\"))", n.to_string()),
+ token::Lit::Integer(n) => format!("Lit::Integer(token::intern(\"{}\"))", n.to_string()),
+ token::Lit::Float(n) => format!("Lit::Float(token::intern(\"{}\"))", n.to_string()),
+ token::Lit::Str_(n) => format!("Lit::Str_(token::intern(\"{}\"))", n.to_string()),
+ token::Lit::ByteStr(n) => format!("Lit::ByteStr(token::intern(\"{}\"))", n.to_string()),
+ _ => panic!("Unsupported literal"),
+ };
+
+ let res = format!("Token::Literal({},{})", lit, suf);
+ debug!("{}", res);
+ lex(&res)
+ }
+
+ // ____________________________________________________________________________________________
+ // Token Builders
+
+ pub fn build_binop_tok(bot: token::BinOpToken) -> TokenStream {
+ match bot {
+ token::BinOpToken::Plus => lex("Token::BinOp(BinOpToken::Plus)"),
+ token::BinOpToken::Minus => lex("Token::BinOp(BinOpToken::Minus)"),
+ token::BinOpToken::Star => lex("Token::BinOp(BinOpToken::Star)"),
+ token::BinOpToken::Slash => lex("Token::BinOp(BinOpToken::Slash)"),
+ token::BinOpToken::Percent => lex("Token::BinOp(BinOpToken::Percent)"),
+ token::BinOpToken::Caret => lex("Token::BinOp(BinOpToken::Caret)"),
+ token::BinOpToken::And => lex("Token::BinOp(BinOpToken::And)"),
+ token::BinOpToken::Or => lex("Token::BinOp(BinOpToken::Or)"),
+ token::BinOpToken::Shl => lex("Token::BinOp(BinOpToken::Shl)"),
+ token::BinOpToken::Shr => lex("Token::BinOp(BinOpToken::Shr)"),
+ }
+ }
+
+ pub fn build_binopeq_tok(bot: token::BinOpToken) -> TokenStream {
+ match bot {
+ token::BinOpToken::Plus => lex("Token::BinOpEq(BinOpToken::Plus)"),
+ token::BinOpToken::Minus => lex("Token::BinOpEq(BinOpToken::Minus)"),
+ token::BinOpToken::Star => lex("Token::BinOpEq(BinOpToken::Star)"),
+ token::BinOpToken::Slash => lex("Token::BinOpEq(BinOpToken::Slash)"),
+ token::BinOpToken::Percent => lex("Token::BinOpEq(BinOpToken::Percent)"),
+ token::BinOpToken::Caret => lex("Token::BinOpEq(BinOpToken::Caret)"),
+ token::BinOpToken::And => lex("Token::BinOpEq(BinOpToken::And)"),
+ token::BinOpToken::Or => lex("Token::BinOpEq(BinOpToken::Or)"),
+ token::BinOpToken::Shl => lex("Token::BinOpEq(BinOpToken::Shl)"),
+ token::BinOpToken::Shr => lex("Token::BinOpEq(BinOpToken::Shr)"),
+ }
+ }
+
+ pub fn build_delim_tok(dt: token::DelimToken) -> TokenStream {
+ match dt {
+ token::DelimToken::Paren => lex("DelimToken::Paren"),
+ token::DelimToken::Bracket => lex("DelimToken::Bracket"),
+ token::DelimToken::Brace => lex("DelimToken::Brace"),
+ token::DelimToken::NoDelim => lex("DelimToken::NoDelim"),
+ }
+ }
+
+ pub fn build_token_tt(t: Token) -> TokenStream {
+ match t {
+ Token::Eq => lex("Token::Eq"),
+ Token::Lt => lex("Token::Lt"),
+ Token::Le => lex("Token::Le"),
+ Token::EqEq => lex("Token::EqEq"),
+ Token::Ne => lex("Token::Ne"),
+ Token::Ge => lex("Token::Ge"),
+ Token::Gt => lex("Token::Gt"),
+ Token::AndAnd => lex("Token::AndAnd"),
+ Token::OrOr => lex("Token::OrOr"),
+ Token::Not => lex("Token::Not"),
+ Token::Tilde => lex("Token::Tilde"),
+ Token::BinOp(tok) => build_binop_tok(tok),
+ Token::BinOpEq(tok) => build_binopeq_tok(tok),
+ Token::At => lex("Token::At"),
+ Token::Dot => lex("Token::Dot"),
+ Token::DotDot => lex("Token::DotDot"),
+ Token::DotDotDot => lex("Token::DotDotDot"),
+ Token::Comma => lex("Token::Comma"),
+ Token::Semi => lex("Token::Semi"),
+ Token::Colon => lex("Token::Colon"),
+ Token::ModSep => lex("Token::ModSep"),
+ Token::RArrow => lex("Token::RArrow"),
+ Token::LArrow => lex("Token::LArrow"),
+ Token::FatArrow => lex("Token::FatArrow"),
+ Token::Pound => lex("Token::Pound"),
+ Token::Dollar => lex("Token::Dollar"),
+ Token::Question => lex("Token::Question"),
+ Token::OpenDelim(dt) => {
+ match dt {
+ token::DelimToken::Paren => lex("Token::OpenDelim(DelimToken::Paren)"),
+ token::DelimToken::Bracket => lex("Token::OpenDelim(DelimToken::Bracket)"),
+ token::DelimToken::Brace => lex("Token::OpenDelim(DelimToken::Brace)"),
+ token::DelimToken::NoDelim => lex("DelimToken::NoDelim"),
+ }
+ }
+ Token::CloseDelim(dt) => {
+ match dt {
+ token::DelimToken::Paren => lex("Token::CloseDelim(DelimToken::Paren)"),
+ token::DelimToken::Bracket => lex("Token::CloseDelim(DelimToken::Bracket)"),
+ token::DelimToken::Brace => lex("Token::CloseDelim(DelimToken::Brace)"),
+ token::DelimToken::NoDelim => lex("DelimToken::NoDelim"),
+ }
+ }
+ Token::Underscore => lex("_"),
+ Token::Literal(lit, sfx) => emit_lit(lit, sfx),
+ // fix ident expansion information... somehow
+ Token::Ident(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))", ident.name)),
+ Token::Lifetime(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))",
+ ident.name)),
+ _ => panic!("Unhandled case!"),
+ }
+ }
+
+ // ____________________________________________________________________________________________
+ // Conversion operators
+
+ pub fn as_tt(t: Token) -> TokenTree {
+ // FIXME do something nicer with the spans
+ TokenTree::Token(DUMMY_SP, t)
+ }
+
+ // ____________________________________________________________________________________________
+ // Build Procedures
+
+ /// Takes `input` and returns `vec![input]`.
+ pub fn build_vec(ts: TokenStream) -> TokenStream {
+ build_mac_call(str_to_ident("vec"), ts)
+ // tts.clone().to_owned()
+ }
+
+ /// Takes `ident` and `rhs` and produces `let ident = rhs;`.
+ pub fn build_let(id: Ident, tts: TokenStream) -> TokenStream {
+ concat(from_tokens(vec![keyword_to_token_ident(keywords::Let),
+ Token::Ident(id),
+ Token::Eq]),
+ concat(tts, from_tokens(vec![Token::Semi])))
+ }
+
+ /// Takes `ident ...`, and `args ...` and produces `ident::...(args ...)`.
+ pub fn build_mod_call(ids: Vec<Ident>, args: TokenStream) -> TokenStream {
+ let call = from_tokens(intersperse(ids.into_iter().map(|id| Token::Ident(id)).collect(),
+ Token::ModSep));
+ concat(call, build_paren_delimited(args))
+ }
+
+ /// Takes `ident` and `args ...` and produces `ident(args ...)`.
+ pub fn build_fn_call(name: Ident, args: TokenStream) -> TokenStream {
+ concat(from_tokens(vec![Token::Ident(name)]), build_paren_delimited(args))
+ }
+
+ /// Takes `ident` and `args ...` and produces `ident!(args ...)`.
+ pub fn build_mac_call(name: Ident, args: TokenStream) -> TokenStream {
+ concat(from_tokens(vec![Token::Ident(name), Token::Not]),
+ build_paren_delimited(args))
+ }
+
+ // ____________________________________________________________________________________________
+ // Utilities
+
+ /// A wrapper around `TokenStream::from_tokens` to avoid extra namespace specification and
+ /// provide it as a generic operator.
+ pub fn from_tokens(tokens: Vec<Token>) -> TokenStream {
+ TokenStream::from_tokens(tokens)
+ }
+
+ pub fn intersperse<T>(vs: Vec<T>, t: T) -> Vec<T>
+ where T: Clone
+ {
+ if vs.len() < 2 {
+ return vs;
+ }
+ let mut output = vec![vs.get(0).unwrap().to_owned()];
+
+ for v in vs.into_iter().skip(1) {
+ output.push(t.clone());
+ output.push(v);
+ }
+ output
+ }
+}
// except according to those terms.
use hir::def_id::DefId;
-use ty::subst::ParamSpace;
use util::nodemap::NodeMap;
use syntax::ast;
use hir;
AssociatedTy(DefId /* trait */, DefId),
Trait(DefId),
PrimTy(hir::PrimTy),
- TyParam(ParamSpace, u32, DefId, ast::Name),
+ TyParam(DefId),
Upvar(DefId, // def id of closed over local
ast::NodeId, // node id of closed over local
usize, // index in the freevars list of the closure
match *self {
Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) |
Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) |
- Def::TyParam(_, _, id, _) | Def::Struct(id) | Def::Trait(id) |
+ Def::TyParam(id) | Def::Struct(id) | Def::Trait(id) |
Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) |
Def::Local(id, _) | Def::Upvar(id, _, _, _) => {
id
use hir::def_id::DefId;
use infer::{self, TypeOrigin};
use middle::region;
-use ty::subst;
use ty::{self, TyCtxt, TypeFoldable};
use ty::{Region, ReFree};
use ty::error::TypeError;
hir::TyPath(ref maybe_qself, ref path) => {
match self.tcx.expect_def(cur_ty.id) {
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
- let generics = self.tcx.lookup_item_type(did).generics;
+ let generics = self.tcx.lookup_generics(did);
let expected =
- generics.regions.len(subst::TypeSpace) as u32;
+ generics.regions.len() as u32;
let lifetimes =
path.segments.last().unwrap().parameters.lifetimes();
let mut insert = Vec::new();
use middle::mem_categorization::McResult;
use middle::region::CodeExtent;
use mir::tcx::LvalueTy;
-use ty::subst;
-use ty::subst::Substs;
-use ty::subst::Subst;
+use ty::subst::{Subst, Substs};
use ty::adjustment;
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
self.tcx.mk_var(self.next_ty_var_id(false))
}
- pub fn next_ty_var_with_default(&self,
- default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> {
- let ty_var_id = self.type_variables
- .borrow_mut()
- .new_var(false, default);
-
- self.tcx.mk_var(ty_var_id)
- }
-
pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
self.tcx.mk_var(self.next_ty_var_id(true))
}
ty::ReVar(self.region_vars.new_region_var(origin))
}
- pub fn region_vars_for_defs(&self,
- span: Span,
- defs: &[ty::RegionParameterDef])
- -> Vec<ty::Region> {
- defs.iter()
- .map(|d| self.next_region_var(EarlyBoundRegion(span, d.name)))
- .collect()
- }
-
- // We have to take `&mut Substs` in order to provide the correct substitutions for defaults
- // along the way, for this reason we don't return them.
- pub fn type_vars_for_defs(&self,
+ /// Create a region inference variable for the given
+ /// region parameter definition.
+ pub fn region_var_for_def(&self,
span: Span,
- space: subst::ParamSpace,
- substs: &mut Substs<'tcx>,
- defs: &[ty::TypeParameterDef<'tcx>]) {
-
- for def in defs.iter() {
- let default = def.default.map(|default| {
- type_variable::Default {
- ty: default.subst_spanned(self.tcx, substs, Some(span)),
- origin_span: span,
- def_id: def.default_def_id
- }
- });
-
- let ty_var = self.next_ty_var_with_default(default);
- substs.types.push(space, ty_var);
- }
- }
-
- /// Given a set of generics defined on a type or impl, returns a substitution mapping each
- /// type/region parameter to a fresh inference variable.
- pub fn fresh_substs_for_generics(&self,
- span: Span,
- generics: &ty::Generics<'tcx>)
- -> &'tcx subst::Substs<'tcx>
- {
- let type_params = subst::VecPerParamSpace::empty();
-
- let region_params =
- generics.regions.map(
- |d| self.next_region_var(EarlyBoundRegion(span, d.name)));
+ def: &ty::RegionParameterDef)
+ -> ty::Region {
+ self.next_region_var(EarlyBoundRegion(span, def.name))
+ }
+
+ /// Create a type inference variable for the given
+ /// type parameter definition. The substitutions are
+ /// for actual parameters that may be referred to by
+ /// the default of this type parameter, if it exists.
+ /// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
+ /// used in a path such as `Foo::<T, U>::new()` will
+ /// use an inference variable for `C` with `[T, U]`
+ /// as the substitutions for the default, `(T, U)`.
+ pub fn type_var_for_def(&self,
+ span: Span,
+ def: &ty::TypeParameterDef<'tcx>,
+ substs: &Substs<'tcx>)
+ -> Ty<'tcx> {
+ let default = def.default.map(|default| {
+ type_variable::Default {
+ ty: default.subst_spanned(self.tcx, substs, Some(span)),
+ origin_span: span,
+ def_id: def.default_def_id
+ }
+ });
- let mut substs = subst::Substs::new(type_params, region_params);
- for space in subst::ParamSpace::all().iter() {
- self.type_vars_for_defs(
- span,
- *space,
- &mut substs,
- generics.types.get_slice(*space));
- }
+ let ty_var_id = self.type_variables
+ .borrow_mut()
+ .new_var(false, default);
- self.tcx.mk_substs(substs)
+ self.tcx.mk_var(ty_var_id)
}
- /// Given a set of generics defined on a trait, returns a substitution mapping each output
- /// type/region parameter to a fresh inference variable, and mapping the self type to
- /// `self_ty`.
- pub fn fresh_substs_for_trait(&self,
- span: Span,
- generics: &ty::Generics<'tcx>,
- self_ty: Ty<'tcx>)
- -> subst::Substs<'tcx>
- {
-
- assert!(generics.types.len(subst::SelfSpace) == 1);
- assert!(generics.types.len(subst::FnSpace) == 0);
- assert!(generics.regions.len(subst::SelfSpace) == 0);
- assert!(generics.regions.len(subst::FnSpace) == 0);
-
- let type_params = Vec::new();
-
- let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
- let regions = self.region_vars_for_defs(span, region_param_defs);
-
- let mut substs = subst::Substs::new_trait(type_params, regions, self_ty);
-
- let type_parameter_defs = generics.types.get_slice(subst::TypeSpace);
- self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs);
-
- return substs;
+ /// Given a set of generics defined on a type or impl, returns a substitution mapping each
+ /// type/region parameter to a fresh inference variable.
+ pub fn fresh_substs_for_item(&self,
+ span: Span,
+ def_id: DefId)
+ -> &'tcx Substs<'tcx> {
+ Substs::for_item(self.tcx, def_id, |def, _| {
+ self.region_var_for_def(span, def)
+ }, |def, substs| {
+ self.type_var_for_def(span, def, substs)
+ })
}
pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
fn item_variances(&self, def: DefId) -> ty::ItemVariances;
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr>;
fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> ty::TypeScheme<'tcx>;
+ -> Ty<'tcx>;
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>;
fn item_name(&self, def: DefId) -> ast::Name;
fn opt_item_name(&self, def: DefId) -> Option<ast::Name>;
-> ty::GenericPredicates<'tcx>;
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx>;
+ fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
+ -> &'tcx ty::Generics<'tcx>;
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>;
fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>;
fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
// trait/impl-item info
- fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
- -> Option<DefId>;
+ fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>>;
fn item_variances(&self, def: DefId) -> ty::ItemVariances { bug!("item_variances") }
fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { bug!("repr_attrs") }
fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> ty::TypeScheme<'tcx> { bug!("item_type") }
+ -> Ty<'tcx> { bug!("item_type") }
fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
bug!("visible_parent_map")
}
-> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
+ fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
+ -> &'tcx ty::Generics<'tcx> { bug!("item_generics") }
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>
{ bug!("trait_def") }
fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
// trait/impl-item info
- fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
- -> Option<DefId> { bug!("trait_of_item") }
+ fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { bug!("trait_of_item") }
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>> { bug!("impl_or_trait_item") }
pub trait DecodingContext<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>;
- fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>;
+ fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx>;
fn translate_def_id(&self, def_id: DefId) -> DefId;
}
fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
use ty::TypeVariants::{TyEnum, TyStruct};
+ let def = self.tcx.expect_def(id);
+
// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
- self.tcx.tables.borrow().item_substs.get(&id)
- .and_then(|substs| substs.substs.self_ty())
- .map(|ty| match ty.sty {
- TyEnum(tyid, _) | TyStruct(tyid, _) => self.check_def_id(tyid.did),
- _ => (),
- });
+ match def {
+ Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
+ if self.tcx.trait_of_item(def.def_id()).is_some() => {
+ if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) {
+ match substs.substs.types[0].sty {
+ TyEnum(tyid, _) | TyStruct(tyid, _) => {
+ self.check_def_id(tyid.did)
+ }
+ _ => {}
+ }
+ }
+ }
+ _ => {}
+ }
- let def = self.tcx.expect_def(id);
match def {
Def::Const(_) | Def::AssociatedConst(..) => {
self.check_def_id(def.def_id());
use hir::def::{Def, DefMap};
use hir::def_id::DefId;
use middle::region;
-use ty::subst;
use ty;
-use std::fmt;
use std::mem::replace;
use syntax::ast;
use syntax::parse::token::keywords;
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub enum DefRegion {
DefStaticRegion,
- DefEarlyBoundRegion(/* space */ subst::ParamSpace,
- /* index */ u32,
+ DefEarlyBoundRegion(/* index */ u32,
/* lifetime decl */ ast::NodeId),
DefLateBoundRegion(ty::DebruijnIndex,
/* lifetime decl */ ast::NodeId),
labels_in_fn: Vec<(ast::Name, Span)>,
}
+#[derive(PartialEq, Debug)]
enum ScopeChain<'a> {
- /// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
- /// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
- EarlyScope(subst::ParamSpace, &'a [hir::LifetimeDef], Scope<'a>),
+ /// EarlyScope(['a, 'b, ...], s) extends s with early-bound
+ /// lifetimes.
+ EarlyScope(&'a [hir::LifetimeDef], Scope<'a>),
/// LateScope(['a, 'b, ...], s) extends s with late-bound
/// lifetimes introduced by the declaration binder_id.
LateScope(&'a [hir::LifetimeDef], Scope<'a>),
hir::ItemImpl(_, _, ref generics, _, _, _) => {
// These kinds of items have only early bound lifetime parameters.
let lifetimes = &generics.lifetimes;
- let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE);
- this.with(early_scope, |old_scope, this| {
+ this.with(EarlyScope(lifetimes, &ROOT_SCOPE), |old_scope, this| {
this.check_lifetime_defs(old_scope, lifetimes);
intravisit::walk_item(this, item);
});
self.with(RootScope, |_, this| {
match item.node {
hir::ForeignItemFn(ref decl, ref generics) => {
- this.visit_early_late(item.id,
- subst::FnSpace,
- decl,
- generics,
- |this| {
+ this.visit_early_late(item.id, decl, generics, |this| {
intravisit::walk_foreign_item(this, item);
})
}
b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
match fk {
FnKind::ItemFn(_, generics, _, _, _, _, _) => {
- self.visit_early_late(fn_id, subst::FnSpace, decl, generics, |this| {
+ self.visit_early_late(fn_id,decl, generics, |this| {
this.add_scope_and_walk_fn(fk, decl, b, s, fn_id)
})
}
FnKind::Method(_, sig, _, _) => {
self.visit_early_late(
fn_id,
- subst::FnSpace,
decl,
&sig.generics,
|this| this.add_scope_and_walk_fn(fk, decl, b, s, fn_id));
if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
self.visit_early_late(
- trait_item.id, subst::FnSpace,
+ trait_item.id,
&sig.decl, &sig.generics,
|this| intravisit::walk_trait_item(this, trait_item))
} else {
FnScope { s, .. } => { scope = s; }
RootScope => { return; }
- EarlyScope(_, lifetimes, s) |
+ EarlyScope(lifetimes, s) |
LateScope(lifetimes, s) => {
for lifetime_def in lifetimes {
// FIXME (#24278): non-hygienic comparison
/// ordering is not important there.
fn visit_early_late<F>(&mut self,
fn_id: ast::NodeId,
- early_space: subst::ParamSpace,
decl: &hir::FnDecl,
generics: &hir::Generics,
walk: F) where
.partition(|l| self.map.late_bound.contains_key(&l.lifetime.id));
let this = self;
- this.with(EarlyScope(early_space, &early, this.scope), move |old_scope, this| {
+ this.with(EarlyScope(&early, this.scope), move |old_scope, this| {
this.with(LateScope(&late, this.scope), move |_, this| {
this.check_lifetime_defs(old_scope, &generics.lifetimes);
walk(this);
break;
}
- EarlyScope(space, lifetimes, s) => {
+ EarlyScope(lifetimes, s) => {
match search_lifetimes(lifetimes, lifetime_ref) {
- Some((index, lifetime_def)) => {
+ Some((mut index, lifetime_def)) => {
+ // Adjust for nested early scopes, e.g. in methods.
+ let mut parent = s;
+ while let EarlyScope(lifetimes, s) = *parent {
+ index += lifetimes.len() as u32;
+ parent = s;
+ }
+ assert_eq!(*parent, RootScope);
+
let decl_id = lifetime_def.id;
- let def = DefEarlyBoundRegion(space, index, decl_id);
+ let def = DefEarlyBoundRegion(index, decl_id);
self.insert_lifetime(lifetime_ref, def);
return;
}
break;
}
- EarlyScope(_, lifetimes, s) |
+ EarlyScope(lifetimes, s) |
LateScope(lifetimes, s) => {
search_result = search_lifetimes(lifetimes, lifetime_ref);
if search_result.is_some() {
return;
}
- EarlyScope(_, lifetimes, s) |
+ EarlyScope(lifetimes, s) |
LateScope(lifetimes, s) => {
if let Some((_, lifetime_def)) = search_lifetimes(lifetimes, lifetime) {
signal_shadowing_problem(
}
}
}
-
-impl<'a> fmt::Debug for ScopeChain<'a> {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({:?}, {:?})", space, defs),
- LateScope(defs, _) => write!(fmt, "LateScope({:?})", defs),
- FnScope { fn_id, body_id, s: _ } => write!(fmt, "FnScope({:?}, {:?})", fn_id, body_id),
- RootScope => write!(fmt, "RootScope"),
- }
- }
-}
let variant_def = &adt_def.variants[variant];
ppaux::parameterized(fmt, substs, variant_def.did,
- ppaux::Ns::Value, &[],
- |tcx| {
- Some(tcx.lookup_item_type(variant_def.did).generics)
- })?;
+ ppaux::Ns::Value, &[])?;
match variant_def.kind {
ty::VariantKind::Unit => Ok(()),
use self::Literal::*;
match *self {
Item { def_id, substs } => {
- ppaux::parameterized(
- fmt, substs, def_id, ppaux::Ns::Value, &[],
- |tcx| Some(tcx.lookup_item_type(def_id).generics))
+ ppaux::parameterized(fmt, substs, def_id, ppaux::Ns::Value, &[])
}
Value { ref value } => {
write!(fmt, "const ")?;
use middle::cstore::LOCAL_CRATE;
use hir::def_id::DefId;
-use ty::subst::TypeSpace;
use ty::{self, Ty, TyCtxt};
use infer::{InferCtxt, TypeOrigin};
use syntax_pos::DUMMY_SP;
// First, create an ordered iterator over all the type parameters to the trait, with the self
// type appearing first.
- let input_tys = Some(trait_ref.self_ty());
- let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace));
-
// Find the first input type that either references a type parameter OR
// some local type.
- for input_ty in input_tys {
+ for input_ty in trait_ref.input_types() {
if ty_is_local(tcx, input_ty, infer_is_local) {
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
ty::TyEnum(def, _) | ty::TyStruct(def, _) =>
def.is_fundamental(),
ty::TyTrait(ref data) =>
- tcx.has_attr(data.principal_def_id(), "fundamental"),
+ tcx.has_attr(data.principal.def_id(), "fundamental"),
_ =>
false
}
}
ty::TyTrait(ref tt) => {
- tt.principal_def_id().is_local()
+ tt.principal.def_id().is_local()
}
ty::TyError => {
use ty::error::ExpectedFound;
use ty::fast_reject;
use ty::fold::TypeFolder;
-use ty::subst::{self, Subst, TypeSpace};
+use ty::subst::Subst;
use util::nodemap::{FnvHashMap, FnvHashSet};
use std::cmp;
});
}
- fn impl_substs(&self,
- did: DefId,
- obligation: PredicateObligation<'tcx>)
- -> subst::Substs<'tcx> {
- let tcx = self.tcx;
-
- let ity = tcx.lookup_item_type(did);
- let (tps, rps, _) =
- (ity.generics.types.get_slice(TypeSpace),
- ity.generics.regions.get_slice(TypeSpace),
- ity.ty);
-
- let rps = self.region_vars_for_defs(obligation.cause.span, rps);
- let mut substs = subst::Substs::new(
- subst::VecPerParamSpace::empty(),
- subst::VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
- self.type_vars_for_defs(obligation.cause.span,
- TypeSpace,
- &mut substs,
- tps);
- substs
- }
-
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
/// returns the fuzzy category of a given type, or None
/// if the type can be equated to any type.
self.tcx.lookup_trait_def(trait_ref.def_id)
.for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
+ let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
let impl_trait_ref = tcx
.impl_trait_ref(def_id)
.unwrap()
- .subst(tcx, &self.impl_substs(def_id, obligation.clone()));
+ .subst(tcx, impl_substs);
let impl_self_ty = impl_trait_ref.self_ty();
if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) {
self_match_impls.push(def_id);
- if trait_ref.substs.types.get_slice(TypeSpace).iter()
- .zip(impl_trait_ref.substs.types.get_slice(TypeSpace))
+ if trait_ref.substs.types[1..].iter()
+ .zip(&impl_trait_ref.substs.types[1..])
.all(|(u,v)| self.fuzzy_match_tys(u, v))
{
fuzzy_match_impls.push(def_id);
let def = self.tcx.lookup_trait_def(trait_ref.def_id);
let trait_str = def.trait_ref.to_string();
if let Some(ref istring) = item.value_str() {
- let mut generic_map = def.generics.types.iter_enumerated()
- .map(|(param, i, gen)| {
- (gen.name.as_str().to_string(),
- trait_ref.substs.types.get(param, i)
- .to_string())
- }).collect::<FnvHashMap<String, String>>();
- generic_map.insert("Self".to_string(),
- trait_ref.self_ty().to_string());
+ let generic_map = def.generics.types.iter().map(|param| {
+ (param.name.as_str().to_string(),
+ trait_ref.substs.type_for_def(param).to_string())
+ }).collect::<FnvHashMap<String, String>>();
let parser = Parser::new(&istring);
let mut errored = false;
let err: String = parser.filter_map(|p| {
// Auto trait obligations on `impl Trait`.
if tcx.trait_has_default_impl(predicate.def_id()) {
let substs = predicate.skip_binder().trait_ref.substs;
- if substs.types.as_slice().len() == 1 && substs.regions.is_empty() {
+ if substs.types.len() == 1 && substs.regions.is_empty() {
if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty {
return true;
}
// We can resolve the `impl Trait` to its concrete type.
if let Some(ty_scheme) = tcx.opt_lookup_item_type(def_id) {
let concrete_ty = ty_scheme.ty.subst(tcx, substs);
- let concrete_substs = Substs::new_trait(vec![], vec![], concrete_ty);
let predicate = ty::TraitRef {
def_id: self.predicate.def_id(),
- substs: tcx.mk_substs(concrete_substs)
+ substs: Substs::new_trait(tcx, vec![], vec![], concrete_ty)
}.to_predicate();
let original_obligation = Obligation::new(self.cause.clone(),
use hir::def_id::DefId;
use middle::free_region::FreeRegionMap;
-use ty::subst;
+use ty::subst::Substs;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use infer::InferCtxt;
#[derive(Clone, PartialEq, Eq)]
pub struct VtableImplData<'tcx, N> {
pub impl_def_id: DefId,
- pub substs: &'tcx subst::Substs<'tcx>,
+ pub substs: &'tcx Substs<'tcx>,
pub nested: Vec<N>
}
use super::elaborate_predicates;
use hir::def_id::DefId;
-use ty::subst::{self, SelfSpace, TypeSpace};
use traits;
use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use std::rc::Rc;
match predicate {
ty::Predicate::Trait(ref data) => {
// In the case of a trait predicate, we can skip the "self" type.
- data.0.trait_ref.substs.types.get_slice(TypeSpace)
- .iter()
- .cloned()
- .any(|t| t.has_self_ty())
+ data.0.trait_ref.input_types()[1..].iter().any(|t| t.has_self_ty())
}
ty::Predicate::Projection(..) |
ty::Predicate::WellFormed(..) |
}
fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
- let trait_def = self.lookup_trait_def(trait_def_id);
- let trait_predicates = self.lookup_predicates(trait_def_id);
- self.generics_require_sized_self(&trait_def.generics, &trait_predicates)
+ self.generics_require_sized_self(trait_def_id)
}
- fn generics_require_sized_self(self,
- generics: &ty::Generics<'gcx>,
- predicates: &ty::GenericPredicates<'gcx>)
- -> bool
- {
+ fn generics_require_sized_self(self, def_id: DefId) -> bool {
let sized_def_id = match self.lang_items.sized_trait() {
Some(def_id) => def_id,
None => { return false; /* No Sized trait, can't require it! */ }
};
// Search for a predicate like `Self : Sized` amongst the trait bounds.
- let free_substs = self.construct_free_substs(generics,
+ let free_substs = self.construct_free_substs(def_id,
self.region_maps.node_extent(ast::DUMMY_NODE_ID));
- let predicates = predicates.instantiate(self, &free_substs).predicates.into_vec();
+ let predicates = self.lookup_predicates(def_id);
+ let predicates = predicates.instantiate(self, free_substs).predicates;
elaborate_predicates(self, predicates)
.any(|predicate| {
match predicate {
{
// Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations.
- if self.generics_require_sized_self(&method.generics, &method.predicates) {
+ if self.generics_require_sized_self(method.def_id) {
return None;
}
-> bool
{
// Any method that has a `Self : Sized` requisite can't be called.
- if self.generics_require_sized_self(&method.generics, &method.predicates) {
+ if self.generics_require_sized_self(method.def_id) {
return false;
}
}
// We can't monomorphize things like `fn foo<A>(...)`.
- if !method.generics.types.is_empty_in(subst::FnSpace) {
+ if !method.generics.types.is_empty() {
return Some(MethodViolationCode::Generic);
}
ty.maybe_walk(|ty| {
match ty.sty {
ty::TyParam(ref param_ty) => {
- if param_ty.space == SelfSpace {
+ if param_ty.is_self() {
error = true;
}
// If so, extract what we know from the trait and try to come up with a good answer.
let trait_predicates = selcx.tcx().lookup_predicates(def_id);
let bounds = trait_predicates.instantiate(selcx.tcx(), substs);
- let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec());
+ let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates);
assemble_candidates_from_predicates(selcx,
obligation,
obligation_trait_ref,
object_ty)
}
};
- let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty);
- let env_predicates = projection_bounds.iter()
- .map(|p| p.to_predicate())
- .collect();
+ let env_predicates = data.projection_bounds.iter().map(|p| {
+ p.with_self_ty(selcx.tcx(), object_ty).to_predicate()
+ }).collect();
let env_predicate = {
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
use hir::def_id::DefId;
use infer;
use infer::{InferCtxt, InferOk, TypeFreshener, TypeOrigin};
-use ty::subst::{Subst, Substs, TypeSpace};
+use ty::subst::{Subst, Substs};
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use traits;
use ty::fast_reject;
use ty::relate::TypeRelation;
+use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec};
use std::cell::RefCell;
use std::fmt;
bounds);
let matching_bound =
- util::elaborate_predicates(self.tcx(), bounds.predicates.into_vec())
+ util::elaborate_predicates(self.tcx(), bounds.predicates)
.filter_to_traits()
.find(
|bound| self.probe(
ty::TyTrait(ref data) => {
match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => {
- if data.bounds.builtin_bounds.contains(&bound) {
+ if data.builtin_bounds.contains(&bound) {
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
pushing candidate");
candidates.vec.push(BuiltinObjectCandidate);
_ => {}
}
- data.principal_trait_ref_with_self_ty(this.tcx(), self_ty)
+ data.principal.with_self_ty(this.tcx(), self_ty)
}
ty::TyInfer(ty::TyVar(_)) => {
debug!("assemble_candidates_from_object_ty: ambiguous");
return;
}
};
- let target = obligation.predicate.0.input_types()[0];
+ let target = obligation.predicate.skip_binder().input_types()[1];
debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})",
source, target);
// We always upcast when we can because of reason
// #2 (region bounds).
data_a.principal.def_id() == data_a.principal.def_id() &&
- data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds)
+ data_a.builtin_bounds.is_superset(&data_b.builtin_bounds)
}
// T -> Trait.
// for `PhantomData<T>`, we pass `T`
ty::TyStruct(def, substs) if def.is_phantom_data() => {
- substs.types.get_slice(TypeSpace).to_vec()
+ substs.types.to_vec()
}
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
match self_ty.sty {
ty::TyTrait(ref data) => {
// OK to skip the binder, it is reintroduced below
- let input_types = data.principal.skip_binder().substs.types.get_slice(TypeSpace);
- let assoc_types = data.bounds.projection_bounds
- .iter()
- .map(|pb| pb.skip_binder().ty);
+ let input_types = data.principal.skip_binder().input_types();
+ let assoc_types = data.projection_bounds.iter()
+ .map(|pb| pb.skip_binder().ty);
let all_types: Vec<_> = input_types.iter().cloned()
.chain(assoc_types)
.collect();
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty {
ty::TyTrait(ref data) => {
- data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
+ data.principal.with_self_ty(self.tcx(), self_ty)
}
_ => {
span_bug!(obligation.cause.span,
// regions here. See the comment there for more details.
let source = self.infcx.shallow_resolve(
tcx.no_late_bound_regions(&obligation.self_ty()).unwrap());
- let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
+ let target = obligation.predicate.skip_binder().input_types()[1];
+ let target = self.infcx.shallow_resolve(target);
debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})",
source, target);
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
(&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
// See assemble_candidates_for_unsizing for more info.
- let bounds = ty::ExistentialBounds {
- region_bound: data_b.bounds.region_bound,
- builtin_bounds: data_b.bounds.builtin_bounds,
- projection_bounds: data_a.bounds.projection_bounds.clone(),
- };
-
- let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds);
+ let new_trait = tcx.mk_trait(ty::TraitObject {
+ principal: data_a.principal,
+ region_bound: data_b.region_bound,
+ builtin_bounds: data_b.builtin_bounds,
+ projection_bounds: data_a.projection_bounds.clone(),
+ });
let origin = TypeOrigin::Misc(obligation.cause.span);
let InferOk { obligations, .. } =
self.infcx.sub_types(false, origin, new_trait, target)
let cause = ObligationCause::new(obligation.cause.span,
obligation.cause.body_id,
ObjectCastObligation(target));
- let outlives = ty::OutlivesPredicate(data_a.bounds.region_bound,
- data_b.bounds.region_bound);
+ let outlives = ty::OutlivesPredicate(data_a.region_bound,
+ data_b.region_bound);
nested.push(Obligation::with_depth(cause,
obligation.recursion_depth + 1,
ty::Binder(outlives).to_predicate()));
// T -> Trait.
(_, &ty::TyTrait(ref data)) => {
- let mut object_dids = Some(data.principal_def_id()).into_iter();
+ let mut object_dids = Some(data.principal.def_id()).into_iter();
// FIXME(#33243)
-// data.bounds.builtin_bounds.iter().flat_map(|bound| {
+// data.builtin_bounds.iter().flat_map(|bound| {
// tcx.lang_items.from_builtin_kind(bound).ok()
// })
-// .chain(Some(data.principal_def_id()));
+// .chain(Some(data.principal.def_id()));
if let Some(did) = object_dids.find(|did| {
!tcx.is_object_safe(*did)
}) {
};
// Create the obligation for casting from T to Trait.
- push(data.principal_trait_ref_with_self_ty(tcx, source).to_predicate());
+ push(data.principal.with_self_ty(tcx, source).to_predicate());
// We can only make objects from sized types.
- let mut builtin_bounds = data.bounds.builtin_bounds;
+ let mut builtin_bounds = data.builtin_bounds;
builtin_bounds.insert(ty::BoundSized);
// Create additional obligations for all the various builtin
}
// Create obligations for the projection predicates.
- for bound in data.projection_bounds_with_self_ty(tcx, source) {
- push(bound.to_predicate());
+ for bound in &data.projection_bounds {
+ push(bound.with_self_ty(tcx, source).to_predicate());
}
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` outlives `'a`:
- let outlives = ty::OutlivesPredicate(source,
- data.bounds.region_bound);
+ let outlives = ty::OutlivesPredicate(source, data.region_bound);
push(ty::Binder(outlives).to_predicate());
}
} else {
return Err(Unimplemented);
};
- let mut ty_params = vec![];
+ let mut ty_params = BitVector::new(substs_a.types.len());
+ let mut found = false;
for ty in field.walk() {
if let ty::TyParam(p) = ty.sty {
- assert!(p.space == TypeSpace);
- let idx = p.idx as usize;
- if !ty_params.contains(&idx) {
- ty_params.push(idx);
- }
+ ty_params.insert(p.idx as usize);
+ found = true;
}
}
- if ty_params.is_empty() {
+ if !found {
return Err(Unimplemented);
}
// TyError and ensure they do not affect any other fields.
// This could be checked after type collection for any struct
// with a potentially unsized trailing field.
- let mut new_substs = substs_a.clone();
- for &i in &ty_params {
- new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
- }
+ let types = substs_a.types.iter().enumerate().map(|(i, ty)| {
+ if ty_params.contains(i) {
+ tcx.types.err
+ } else {
+ ty
+ }
+ }).collect();
+ let substs = Substs::new(tcx, types, substs_a.regions.clone());
for &ty in fields.split_last().unwrap().1 {
- if ty.subst(tcx, &new_substs).references_error() {
+ if ty.subst(tcx, substs).references_error() {
return Err(Unimplemented);
}
}
// Check that the source structure with the target's
// type parameters is a subtype of the target.
- for &i in &ty_params {
- let param_b = *substs_b.types.get(TypeSpace, i);
- new_substs.types.get_mut_slice(TypeSpace)[i] = param_b;
- }
- let new_struct = tcx.mk_struct(def, tcx.mk_substs(new_substs));
+ let types = substs_a.types.iter().enumerate().map(|(i, ty)| {
+ if ty_params.contains(i) {
+ substs_b.types[i]
+ } else {
+ ty
+ }
+ }).collect();
+ let substs = Substs::new(tcx, types, substs_a.regions.clone());
+ let new_struct = tcx.mk_struct(def, substs);
let origin = TypeOrigin::Misc(obligation.cause.span);
let InferOk { obligations, .. } =
self.infcx.sub_types(false, origin, new_struct, target)
snapshot);
let skol_obligation_trait_ref = skol_obligation.trait_ref;
- let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
- obligation.cause.span,
- impl_def_id);
+ let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span,
+ impl_def_id);
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
- &impl_substs);
+ impl_substs);
let impl_trait_ref =
project::normalize_with_depth(self,
// obligation will normalize to `<$0 as Iterator>::Item = $1` and
// `$1: Copy`, so we must ensure the obligations are emitted in
// that order.
- let predicates = tcx
- .lookup_predicates(def_id)
- .predicates.iter()
- .flat_map(|predicate| {
- let predicate =
- normalize_with_depth(self, cause.clone(), recursion_depth,
- &predicate.subst(tcx, substs));
- predicate.obligations.into_iter().chain(
- Some(Obligation {
- cause: cause.clone(),
- recursion_depth: recursion_depth,
- predicate: predicate.value
- }))
- }).collect();
+ let predicates = tcx.lookup_predicates(def_id);
+ assert_eq!(predicates.parent, None);
+ let predicates = predicates.predicates.iter().flat_map(|predicate| {
+ let predicate = normalize_with_depth(self, cause.clone(), recursion_depth,
+ &predicate.subst(tcx, substs));
+ predicate.obligations.into_iter().chain(
+ Some(Obligation {
+ cause: cause.clone(),
+ recursion_depth: recursion_depth,
+ predicate: predicate.value
+ }))
+ }).collect();
self.infcx().plug_leaks(skol_map, snapshot, &predicates)
}
}
// fits together with the rest of the trait machinery.
use super::{SelectionContext, FulfillmentContext};
-use super::util::{fresh_type_vars_for_impl, impl_trait_ref_and_oblig};
+use super::util::impl_trait_ref_and_oblig;
use rustc_data_structures::fnv::FnvHashMap;
use hir::def_id::DefId;
/// When we have selected one impl, but are actually using item definitions from
/// a parent impl providing a default, we need a way to translate between the
/// type parameters of the two impls. Here the `source_impl` is the one we've
-/// selected, and `source_substs` is a substitution of its generics (and
-/// possibly some relevant `FnSpace` variables as well). And `target_node` is
-/// the impl/trait we're actually going to get the definition from. The resulting
-/// substitution will map from `target_node`'s generics to `source_impl`'s
-/// generics as instantiated by `source_subst`.
+/// selected, and `source_substs` is a substitution of its generics.
+/// And `target_node` is the impl/trait we're actually going to get the
+/// definition from. The resulting substitution will map from `target_node`'s
+/// generics to `source_impl`'s generics as instantiated by `source_subst`.
///
/// For example, consider the following scenario:
///
};
// directly inherent the method generics, since those do not vary across impls
- infcx.tcx.mk_substs(target_substs.with_method_from_subst(source_substs))
+ source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
}
/// Is impl1 a specialization of impl2?
}
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
- let scheme = tcx.lookup_item_type(impl1_def_id);
- let predicates = tcx.lookup_predicates(impl1_def_id);
let mut penv = tcx.construct_parameter_environment(DUMMY_SP,
- &scheme.generics,
- &predicates,
+ impl1_def_id,
region::DUMMY_CODE_EXTENT);
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id)
.unwrap()
target_impl: DefId)
-> Result<&'tcx Substs<'tcx>, ()> {
let selcx = &mut SelectionContext::new(&infcx);
- let target_substs = fresh_type_vars_for_impl(&infcx, DUMMY_SP, target_impl);
+ let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx,
target_impl,
- &target_substs);
+ target_substs);
// do the impls unify? If not, no specialization.
if let Err(_) = infcx.eq_trait_refs(true,
if le == ge {
// overlap, but no specialization; error out
let trait_ref = impl_header.trait_ref.unwrap();
+ let self_ty = trait_ref.self_ty();
Err(OverlapError {
with_impl: possible_sibling,
trait_desc: trait_ref.to_string(),
- self_desc: trait_ref.substs.self_ty().and_then(|ty| {
- // only report the Self type if it has at least
- // some outer concrete shell; otherwise, it's
- // not adding much information.
- if ty.has_concrete_skeleton() {
- Some(ty.to_string())
- } else {
- None
- }
- })
+ // only report the Self type if it has at least
+ // some outer concrete shell; otherwise, it's
+ // not adding much information.
+ self_desc: if self_ty.has_concrete_skeleton() {
+ Some(self_ty.to_string())
+ } else {
+ None
+ }
})
} else {
Ok((le, ge))
// except according to those terms.
use hir::def_id::DefId;
-use infer::InferCtxt;
use ty::subst::{Subst, Substs};
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
-use syntax_pos::Span;
use util::common::ErrorReported;
use util::nodemap::FnvHashSet;
(impl_trait_ref, impl_obligations)
}
-// determine the `self` type, using fresh variables for all variables
-// declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
-// would return ($0, $1) where $0 and $1 are freshly instantiated type
-// variables.
-pub fn fresh_type_vars_for_impl<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
- span: Span,
- impl_def_id: DefId)
- -> &'tcx Substs<'tcx>
-{
- let tcx = infcx.tcx;
- let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
- infcx.fresh_substs_for_generics(span, &impl_generics)
-}
-
/// See `super::obligations_for_generics`
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
recursion_depth: usize,
Ok(def_id) => {
Ok(ty::TraitRef {
def_id: def_id,
- substs: self.mk_substs(Substs::empty().with_self_ty(param_ty))
+ substs: Substs::new_trait(self, vec![], vec![], param_ty)
})
}
Err(e) => {
{
let trait_ref = ty::TraitRef {
def_id: trait_def_id,
- substs: self.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
+ substs: Substs::new_trait(self, ty_params, vec![], param_ty)
};
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
}
TupleArgumentsFlag::No => sig.0.inputs[0],
TupleArgumentsFlag::Yes => self.mk_tup(sig.0.inputs.to_vec()),
};
- let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
let trait_ref = ty::TraitRef {
def_id: fn_trait_def_id,
- substs: self.mk_substs(trait_substs),
+ substs: Substs::new_trait(self, vec![arguments_tuple], vec![], self_ty),
};
ty::Binder((trait_ref, sig.0.output))
}
use middle::region::RegionMaps;
use middle::resolve_lifetime;
use middle::stability;
-use ty::subst::{self, Substs};
+use ty::subst::Substs;
use traits;
use ty::{self, TraitRef, Ty, TypeAndMut};
use ty::{TyS, TypeVariants};
-use ty::{AdtDef, ClosureSubsts, ExistentialBounds, Region};
+use ty::{AdtDef, ClosureSubsts, Region};
use hir::FreevarMap;
-use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy};
+use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject};
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*;
use ty::layout::{Layout, TargetDataLayout};
layout: TypedArena<Layout>,
// references
+ generics: TypedArena<ty::Generics<'tcx>>,
trait_defs: TypedArena<ty::TraitDef<'tcx>>,
adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
}
stability: TypedArena::new(),
layout: TypedArena::new(),
+ generics: TypedArena::new(),
trait_defs: TypedArena::new(),
adt_defs: TypedArena::new()
}
pub adt_defs: RefCell<DepTrackingMap<maps::AdtDefs<'tcx>>>,
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
- /// associated predicates.
+ /// associated generics and predicates.
+ pub generics: RefCell<DepTrackingMap<maps::Generics<'tcx>>>,
pub predicates: RefCell<DepTrackingMap<maps::Predicates<'tcx>>>,
/// Maps from the def-id of a trait to the list of
self.tables.borrow_mut().node_types.insert(id, ty);
}
+ pub fn alloc_generics(self, generics: ty::Generics<'gcx>)
+ -> &'gcx ty::Generics<'gcx> {
+ self.global_interners.arenas.generics.alloc(generics)
+ }
+
pub fn intern_trait_def(self, def: ty::TraitDef<'gcx>)
-> &'gcx ty::TraitDef<'gcx> {
let did = def.trait_ref.def_id;
- let interned = self.global_interners.arenas.trait_defs.alloc(def);
+ let interned = self.alloc_trait_def(def);
if let Some(prev) = self.trait_defs.borrow_mut().insert(did, interned) {
bug!("Tried to overwrite interned TraitDef: {:?}", prev)
}
+ self.generics.borrow_mut().insert(did, interned.generics);
interned
}
impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
+ generics: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
fulfilled_predicates: RefCell::new(fulfilled_predicates),
region: mk_region(Region, keep_local) -> Region
);
-fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
- bounds.is_empty() ||
- bounds[1..].iter().enumerate().all(
- |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
-}
-
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Create an unsafe fn ty based on a safe fn ty.
pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
self.mk_ty(TyFnPtr(fty))
}
- pub fn mk_trait(self,
- principal: ty::PolyTraitRef<'tcx>,
- bounds: ExistentialBounds<'tcx>)
- -> Ty<'tcx>
- {
- assert!(bound_list_is_sorted(&bounds.projection_bounds));
-
- let inner = box TraitTy {
- principal: principal,
- bounds: bounds
- };
- self.mk_ty(TyTrait(inner))
+ pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> {
+ obj.projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
+ self.mk_ty(TyTrait(box obj))
}
pub fn mk_projection(self,
}
pub fn mk_param(self,
- space: subst::ParamSpace,
index: u32,
name: Name) -> Ty<'tcx> {
- self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
+ self.mk_ty(TyParam(ParamTy { idx: index, name: name }))
}
pub fn mk_self_type(self) -> Ty<'tcx> {
- self.mk_param(subst::SelfSpace, 0, keywords::SelfType.name())
+ self.mk_param(0, keywords::SelfType.name())
}
pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
- self.mk_param(def.space, def.index, def.name)
+ self.mk_param(def.index, def.name)
}
pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
// except according to those terms.
use hir::def_id::DefId;
-use ty::subst;
use infer::type_variable;
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
ty::TyFnDef(..) => format!("fn item"),
ty::TyFnPtr(_) => "fn pointer".to_string(),
ty::TyTrait(ref inner) => {
- format!("trait {}", tcx.item_path_str(inner.principal_def_id()))
+ format!("trait {}", tcx.item_path_str(inner.principal.def_id()))
}
ty::TyStruct(def, _) => {
format!("struct `{}`", tcx.item_path_str(def.did))
ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
ty::TyProjection(_) => "associated type".to_string(),
ty::TyParam(ref p) => {
- if p.space == subst::SelfSpace {
+ if p.is_self() {
"Self".to_string()
} else {
"type parameter".to_string()
ty::TyArray(..) | ty::TySlice(_) => Some(VecSimplifiedType),
ty::TyRawPtr(_) => Some(PtrSimplifiedType),
ty::TyTrait(ref trait_info) => {
- Some(TraitSimplifiedType(trait_info.principal_def_id()))
+ Some(TraitSimplifiedType(trait_info.principal.def_id()))
}
ty::TyStruct(def, _) => {
Some(StructSimplifiedType(def.did))
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ty::subst;
+use ty::subst::Substs;
use ty::{self, Ty, TypeFlags, TypeFoldable};
pub struct FlagComputation {
&ty::TyParam(ref p) => {
self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
- if p.space == subst::SelfSpace {
+ if p.is_self() {
self.add_flags(TypeFlags::HAS_SELF);
} else {
self.add_flags(TypeFlags::HAS_PARAMS);
self.add_substs(substs);
}
- &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
+ &ty::TyTrait(ref obj) => {
let mut computation = FlagComputation::new();
- computation.add_substs(principal.0.substs);
- for projection_bound in &bounds.projection_bounds {
+ computation.add_substs(obj.principal.skip_binder().substs);
+ for projection_bound in &obj.projection_bounds {
let mut proj_computation = FlagComputation::new();
- proj_computation.add_projection_predicate(&projection_bound.0);
+ proj_computation.add_existential_projection(&projection_bound.0);
self.add_bound_computation(&proj_computation);
}
self.add_bound_computation(&computation);
-
- self.add_bounds(bounds);
+ self.add_region(obj.region_bound);
}
&ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => {
}
}
- fn add_projection_predicate(&mut self, projection_predicate: &ty::ProjectionPredicate) {
- self.add_projection_ty(&projection_predicate.projection_ty);
- self.add_ty(projection_predicate.ty);
+ fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) {
+ self.add_substs(projection.trait_ref.substs);
+ self.add_ty(projection.ty);
}
fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) {
self.add_substs(projection_ty.trait_ref.substs);
}
- fn add_substs(&mut self, substs: &subst::Substs) {
- self.add_tys(substs.types.as_slice());
+ fn add_substs(&mut self, substs: &Substs) {
+ self.add_tys(&substs.types);
for &r in &substs.regions {
self.add_region(r);
}
}
-
- fn add_bounds(&mut self, bounds: &ty::ExistentialBounds) {
- self.add_region(bounds.region_bound);
- }
}
//! and does not need to visit anything else.
use middle::region;
-use ty::subst;
+use ty::subst::Substs;
use ty::adjustment;
use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
t.super_fold_with(self)
}
- fn fold_trait_ref(&mut self, t: &ty::TraitRef<'tcx>) -> ty::TraitRef<'tcx> {
- t.super_fold_with(self)
- }
-
fn fold_impl_header(&mut self, imp: &ty::ImplHeader<'tcx>) -> ty::ImplHeader<'tcx> {
imp.super_fold_with(self)
}
fn fold_substs(&mut self,
- substs: &'tcx subst::Substs<'tcx>)
- -> &'tcx subst::Substs<'tcx> {
+ substs: &'tcx Substs<'tcx>)
+ -> &'tcx Substs<'tcx> {
substs.super_fold_with(self)
}
r.super_fold_with(self)
}
- fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
- -> ty::ExistentialBounds<'tcx> {
- s.super_fold_with(self)
- }
-
fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>)
-> adjustment::AutoRef<'tcx> {
ar.super_fold_with(self)
ty::TyStruct(adt_def, _) |
ty::TyEnum(adt_def, _) => Some(adt_def.did),
- ty::TyTrait(ref data) => Some(data.principal_def_id()),
+ ty::TyTrait(ref data) => Some(data.principal.def_id()),
ty::TyArray(subty, _) |
ty::TySlice(subty) |
use dep_graph::{DepNode, DepTrackingMapConfig};
use hir::def_id::DefId;
-use ty;
+use ty::{self, Ty};
use std::marker::PhantomData;
use std::rc::Rc;
use syntax::{attr, ast};
}
dep_map_ty! { ImplOrTraitItems: ImplOrTraitItems(DefId) -> ty::ImplOrTraitItem<'tcx> }
-dep_map_ty! { Tcache: ItemSignature(DefId) -> ty::TypeScheme<'tcx> }
+dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> }
+dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> }
dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
dep_map_ty! { TraitItemDefIds: TraitItemDefIds(DefId) -> Rc<Vec<ty::ImplOrTraitItemId>> }
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
use traits;
use ty;
-use ty::subst::{Subst, Substs, VecPerParamSpace};
+use ty::subst::{Subst, Substs};
use ty::walk::TypeWalker;
use util::common::MemoizationMap;
use util::nodemap::NodeSet;
use hir::intravisit::Visitor;
pub use self::sty::{Binder, DebruijnIndex};
-pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds};
+pub use self::sty::{BuiltinBound, BuiltinBounds};
pub use self::sty::{BareFnTy, FnSig, PolyFnSig};
-pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitTy};
+pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject};
pub use self::sty::{ClosureSubsts, TypeAndMut};
pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
+pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
+pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::Issue32330;
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
-> ImplHeader<'tcx>
{
let tcx = selcx.tcx();
- let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
- let impl_substs = selcx.infcx().fresh_substs_for_generics(DUMMY_SP, &impl_generics);
+ let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
let header = ImplHeader {
impl_def_id: impl_def_id,
self_ty: tcx.lookup_item_type(impl_def_id).ty,
trait_ref: tcx.impl_trait_ref(impl_def_id),
- predicates: tcx.lookup_predicates(impl_def_id).predicates.into_vec(),
- }.subst(tcx, &impl_substs);
+ predicates: tcx.lookup_predicates(impl_def_id).predicates
+ }.subst(tcx, impl_substs);
let traits::Normalized { value: mut header, obligations } =
traits::normalize(selcx, traits::ObligationCause::dummy(), &header);
#[derive(Clone, Debug)]
pub struct Method<'tcx> {
pub name: Name,
- pub generics: Generics<'tcx>,
+ pub generics: &'tcx Generics<'tcx>,
pub predicates: GenericPredicates<'tcx>,
pub fty: &'tcx BareFnTy<'tcx>,
pub explicit_self: ExplicitSelfCategory,
impl<'tcx> Method<'tcx> {
pub fn new(name: Name,
- generics: ty::Generics<'tcx>,
+ generics: &'tcx ty::Generics<'tcx>,
predicates: GenericPredicates<'tcx>,
fty: &'tcx BareFnTy<'tcx>,
explicit_self: ExplicitSelfCategory,
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)]
pub struct ItemVariances {
- pub types: VecPerParamSpace<Variance>,
- pub regions: VecPerParamSpace<Variance>,
+ pub types: Vec<Variance>,
+ pub regions: Vec<Variance>,
+}
+
+impl ItemVariances {
+ pub fn empty() -> ItemVariances {
+ ItemVariances {
+ types: vec![],
+ regions: vec![],
+ }
+ }
}
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
/// Impl method ID, for inherent methods, or trait method ID, otherwise.
pub def_id: DefId,
pub ty: Ty<'tcx>,
- pub substs: &'tcx subst::Substs<'tcx>
+ pub substs: &'tcx Substs<'tcx>
}
/// With method calls, we store some extra information in
pub struct TypeParameterDef<'tcx> {
pub name: Name,
pub def_id: DefId,
- pub space: subst::ParamSpace,
pub index: u32,
pub default_def_id: DefId, // for use in error reporing about defaults
pub default: Option<Ty<'tcx>>,
pub struct RegionParameterDef {
pub name: Name,
pub def_id: DefId,
- pub space: subst::ParamSpace,
pub index: u32,
pub bounds: Vec<ty::Region>,
}
impl RegionParameterDef {
pub fn to_early_bound_region(&self) -> ty::Region {
ty::ReEarlyBound(ty::EarlyBoundRegion {
- space: self.space,
index: self.index,
name: self.name,
})
/// with an item or method. Analogous to hir::Generics.
#[derive(Clone, Debug)]
pub struct Generics<'tcx> {
- pub types: VecPerParamSpace<TypeParameterDef<'tcx>>,
- pub regions: VecPerParamSpace<RegionParameterDef>,
-}
-
-impl<'tcx> Generics<'tcx> {
- pub fn empty() -> Generics<'tcx> {
- Generics {
- types: VecPerParamSpace::empty(),
- regions: VecPerParamSpace::empty(),
- }
- }
-
- pub fn is_empty(&self) -> bool {
- self.types.is_empty() && self.regions.is_empty()
- }
-
- pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
- !self.types.is_empty_in(space)
- }
-
- pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
- !self.regions.is_empty_in(space)
- }
+ pub parent: Option<DefId>,
+ pub parent_regions: u32,
+ pub parent_types: u32,
+ pub regions: Vec<RegionParameterDef>,
+ pub types: Vec<TypeParameterDef<'tcx>>,
+ pub has_self: bool,
}
/// Bounds on generics.
#[derive(Clone)]
pub struct GenericPredicates<'tcx> {
- pub predicates: VecPerParamSpace<Predicate<'tcx>>,
+ pub parent: Option<DefId>,
+ pub predicates: Vec<Predicate<'tcx>>,
}
impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
- pub fn empty() -> GenericPredicates<'tcx> {
- GenericPredicates {
- predicates: VecPerParamSpace::empty(),
- }
- }
-
pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
-> InstantiatedPredicates<'tcx> {
+ let mut instantiated = InstantiatedPredicates::empty();
+ self.instantiate_into(tcx, &mut instantiated, substs);
+ instantiated
+ }
+ pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
+ -> InstantiatedPredicates<'tcx> {
InstantiatedPredicates {
- predicates: self.predicates.subst(tcx, substs),
+ predicates: self.predicates.subst(tcx, substs)
+ }
+ }
+
+ fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ instantiated: &mut InstantiatedPredicates<'tcx>,
+ substs: &Substs<'tcx>) {
+ if let Some(def_id) = self.parent {
+ tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs);
}
+ instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
}
pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
poly_trait_ref: &ty::PolyTraitRef<'tcx>)
-> InstantiatedPredicates<'tcx>
{
+ assert_eq!(self.parent, None);
InstantiatedPredicates {
- predicates: self.predicates.map(|pred| {
+ predicates: self.predicates.iter().map(|pred| {
pred.subst_supertrait(tcx, poly_trait_ref)
- })
+ }).collect()
}
}
}
pub enum Predicate<'tcx> {
/// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
- /// would be the parameters in the `TypeSpace`.
+ /// would be the type parameters.
Trait(PolyTraitPredicate<'tcx>),
/// A predicate created by RFC1592
/// trait must be object-safe
ObjectSafe(DefId),
- /// No direct syntax. May be thought of as `where T : FnFoo<...>` for some 'TypeSpace'
- /// substitutions `...` and T being a closure type. Satisfied (or refuted) once we know the
- /// closure's kind.
+ /// No direct syntax. May be thought of as `where T : FnFoo<...>`
+ /// for some substitutions `...` and T being a closure type.
+ /// Satisfied (or refuted) once we know the closure's kind.
ClosureKind(DefId, ClosureKind),
}
}
pub fn input_types(&self) -> &[Ty<'tcx>] {
- self.trait_ref.substs.types.as_slice()
+ &self.trait_ref.substs.types
}
pub fn self_ty(&self) -> Ty<'tcx> {
pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
let vec: Vec<_> = match *self {
ty::Predicate::Trait(ref data) => {
- data.0.trait_ref.substs.types.as_slice().to_vec()
+ data.0.trait_ref.input_types().to_vec()
}
ty::Predicate::Rfc1592(ref data) => {
return data.walk_tys()
vec![]
}
ty::Predicate::Projection(ref data) => {
- let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice();
+ let trait_inputs = data.0.projection_ty.trait_ref.input_types();
trait_inputs.iter()
.cloned()
.chain(Some(data.0.ty))
/// [usize:Bar<isize>]]`.
#[derive(Clone)]
pub struct InstantiatedPredicates<'tcx> {
- pub predicates: VecPerParamSpace<Predicate<'tcx>>,
+ pub predicates: Vec<Predicate<'tcx>>,
}
impl<'tcx> InstantiatedPredicates<'tcx> {
pub fn empty() -> InstantiatedPredicates<'tcx> {
- InstantiatedPredicates { predicates: VecPerParamSpace::empty() }
+ InstantiatedPredicates { predicates: vec![] }
}
pub fn is_empty(&self) -> bool {
}
pub fn self_ty(&self) -> Ty<'tcx> {
- self.substs.self_ty().unwrap()
+ self.substs.types[0]
}
pub fn input_types(&self) -> &[Ty<'tcx>] {
// now this is all the types that appear in the
// trait-reference, but it should eventually exclude
// associated types.
- self.substs.types.as_slice()
+ &self.substs.types
}
}
// so for now just grab environment for the impl
let impl_id = tcx.map.get_parent(id);
let impl_def_id = tcx.map.local_def_id(impl_id);
- let scheme = tcx.lookup_item_type(impl_def_id);
- let predicates = tcx.lookup_predicates(impl_def_id);
tcx.construct_parameter_environment(impl_item.span,
- &scheme.generics,
- &predicates,
+ impl_def_id,
tcx.region_maps.item_extent(id))
}
hir::ImplItemKind::Method(_, ref body) => {
let method_def_id = tcx.map.local_def_id(id);
match tcx.impl_or_trait_item(method_def_id) {
MethodTraitItem(ref method_ty) => {
- let method_generics = &method_ty.generics;
- let method_bounds = &method_ty.predicates;
tcx.construct_parameter_environment(
impl_item.span,
- method_generics,
- method_bounds,
+ method_ty.def_id,
tcx.region_maps.call_site_extent(id, body.id))
}
_ => {
// so for now just grab environment for the trait
let trait_id = tcx.map.get_parent(id);
let trait_def_id = tcx.map.local_def_id(trait_id);
- let trait_def = tcx.lookup_trait_def(trait_def_id);
- let predicates = tcx.lookup_predicates(trait_def_id);
tcx.construct_parameter_environment(trait_item.span,
- &trait_def.generics,
- &predicates,
+ trait_def_id,
tcx.region_maps.item_extent(id))
}
hir::MethodTraitItem(_, ref body) => {
let method_def_id = tcx.map.local_def_id(id);
match tcx.impl_or_trait_item(method_def_id) {
MethodTraitItem(ref method_ty) => {
- let method_generics = &method_ty.generics;
- let method_bounds = &method_ty.predicates;
let extent = if let Some(ref body) = *body {
// default impl: use call_site extent as free_id_outlive bound.
tcx.region_maps.call_site_extent(id, body.id)
};
tcx.construct_parameter_environment(
trait_item.span,
- method_generics,
- method_bounds,
+ method_ty.def_id,
extent)
}
_ => {
hir::ItemFn(_, _, _, _, _, ref body) => {
// We assume this is a function.
let fn_def_id = tcx.map.local_def_id(id);
- let fn_scheme = tcx.lookup_item_type(fn_def_id);
- let fn_predicates = tcx.lookup_predicates(fn_def_id);
tcx.construct_parameter_environment(
item.span,
- &fn_scheme.generics,
- &fn_predicates,
+ fn_def_id,
tcx.region_maps.call_site_extent(id, body.id))
}
hir::ItemEnum(..) |
hir::ItemConst(..) |
hir::ItemStatic(..) => {
let def_id = tcx.map.local_def_id(id);
- let scheme = tcx.lookup_item_type(def_id);
- let predicates = tcx.lookup_predicates(def_id);
tcx.construct_parameter_environment(item.span,
- &scheme.generics,
- &predicates,
+ def_id,
tcx.region_maps.item_extent(id))
}
hir::ItemTrait(..) => {
let def_id = tcx.map.local_def_id(id);
- let trait_def = tcx.lookup_trait_def(def_id);
- let predicates = tcx.lookup_predicates(def_id);
tcx.construct_parameter_environment(item.span,
- &trait_def.generics,
- &predicates,
+ def_id,
tcx.region_maps.item_extent(id))
}
_ => {
}
Some(ast_map::NodeForeignItem(item)) => {
let def_id = tcx.map.local_def_id(id);
- let scheme = tcx.lookup_item_type(def_id);
- let predicates = tcx.lookup_predicates(def_id);
tcx.construct_parameter_environment(item.span,
- &scheme.generics,
- &predicates,
+ def_id,
ROOT_CODE_EXTENT)
}
_ => {
/// `lookup_predicates`.
#[derive(Clone, Debug)]
pub struct TypeScheme<'tcx> {
- pub generics: Generics<'tcx>,
+ pub generics: &'tcx Generics<'tcx>,
pub ty: Ty<'tcx>,
}
};
let sized_predicate = Binder(TraitRef {
def_id: sized_trait,
- substs: tcx.mk_substs(Substs::new_trait(
- vec![], vec![], ty
- ))
+ substs: Substs::new_trait(tcx, vec![], vec![], ty)
}).to_predicate();
let predicates = tcx.lookup_predicates(self.did).predicates;
if predicates.into_iter().any(|p| p == sized_predicate) {
pub fn node_id_item_substs(self, id: NodeId) -> ItemSubsts<'gcx> {
match self.tables.borrow().item_substs.get(&id) {
None => ItemSubsts {
- substs: self.global_tcx().mk_substs(Substs::empty())
+ substs: Substs::empty(self.global_tcx())
},
Some(ts) => ts.clone(),
}
}
// Register a given item type
- pub fn register_item_type(self, did: DefId, ty: TypeScheme<'gcx>) {
- self.tcache.borrow_mut().insert(did, ty);
+ pub fn register_item_type(self, did: DefId, scheme: TypeScheme<'gcx>) {
+ self.tcache.borrow_mut().insert(did, scheme.ty);
+ self.generics.borrow_mut().insert(did, scheme.generics);
}
// If the given item is in an external crate, looks up its type and adds it to
// the type cache. Returns the type parameters and type.
pub fn lookup_item_type(self, did: DefId) -> TypeScheme<'gcx> {
- lookup_locally_or_in_crate_store(
+ let ty = lookup_locally_or_in_crate_store(
"tcache", did, &self.tcache,
- || self.sess.cstore.item_type(self.global_tcx(), did))
+ || self.sess.cstore.item_type(self.global_tcx(), did));
+
+ TypeScheme {
+ ty: ty,
+ generics: self.lookup_generics(did)
+ }
}
pub fn opt_lookup_item_type(self, did: DefId) -> Option<TypeScheme<'gcx>> {
- if let Some(scheme) = self.tcache.borrow_mut().get(&did) {
- return Some(scheme.clone());
+ if did.krate != LOCAL_CRATE {
+ return Some(self.lookup_item_type(did));
}
- if did.krate == LOCAL_CRATE {
- None
+ if let Some(ty) = self.tcache.borrow().get(&did).cloned() {
+ Some(TypeScheme {
+ ty: ty,
+ generics: self.lookup_generics(did)
+ })
} else {
- Some(self.sess.cstore.item_type(self.global_tcx(), did))
+ None
}
}
self.lookup_adt_def_master(did)
}
+ /// Given the did of an item, returns its generics.
+ pub fn lookup_generics(self, did: DefId) -> &'gcx Generics<'gcx> {
+ lookup_locally_or_in_crate_store(
+ "generics", did, &self.generics,
+ || self.sess.cstore.item_generics(self.global_tcx(), did))
+ }
+
/// Given the did of an item, returns its full set of predicates.
pub fn lookup_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
lookup_locally_or_in_crate_store(
}
}
- /// If the given def ID describes an item belonging to a trait (either a
- /// default method or an implementation of a trait method), return the ID of
- /// the trait that the method belongs to. Otherwise, return `None`.
+ /// If the given def ID describes an item belonging to a trait,
+ /// return the ID of the trait that the trait item belongs to.
+ /// Otherwise, return `None`.
pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> {
if def_id.krate != LOCAL_CRATE {
- return self.sess.cstore.trait_of_item(self.global_tcx(), def_id);
+ return self.sess.cstore.trait_of_item(def_id);
}
- match self.impl_or_trait_items.borrow().get(&def_id).cloned() {
+ match self.impl_or_trait_items.borrow().get(&def_id) {
Some(impl_or_trait_item) => {
match impl_or_trait_item.container() {
TraitContainer(def_id) => Some(def_id),
- ImplContainer(def_id) => self.trait_id_of_impl(def_id),
+ ImplContainer(_) => None
}
}
None => None
/// the same).
/// Otherwise, return `None`.
pub fn trait_item_of_item(self, def_id: DefId) -> Option<ImplOrTraitItemId> {
- let impl_item = match self.impl_or_trait_items.borrow().get(&def_id) {
+ let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) {
Some(m) => m.clone(),
None => return None,
};
- let name = impl_item.name();
- match self.trait_of_item(def_id) {
- Some(trait_did) => {
- self.trait_items(trait_did).iter()
- .find(|item| item.name() == name)
- .map(|item| item.id())
+ match impl_or_trait_item.container() {
+ TraitContainer(_) => Some(impl_or_trait_item.id()),
+ ImplContainer(def_id) => {
+ self.trait_id_of_impl(def_id).and_then(|trait_did| {
+ let name = impl_or_trait_item.name();
+ self.trait_items(trait_did).iter()
+ .find(|item| item.name() == name)
+ .map(|item| item.id())
+ })
}
- None => None
}
}
// regions, so it shouldn't matter what we use for the free id
let free_id_outlive = self.region_maps.node_extent(ast::DUMMY_NODE_ID);
ty::ParameterEnvironment {
- free_substs: self.mk_substs(Substs::empty()),
+ free_substs: Substs::empty(self),
caller_bounds: Vec::new(),
implicit_region_bound: ty::ReEmpty,
free_id_outlive: free_id_outlive
/// In general, this means converting from bound parameters to
/// free parameters. Since we currently represent bound/free type
/// parameters in the same way, this only has an effect on regions.
- pub fn construct_free_substs(self, generics: &Generics<'gcx>,
- free_id_outlive: CodeExtent) -> Substs<'gcx> {
- // map T => T
- let mut types = VecPerParamSpace::empty();
- for def in generics.types.as_slice() {
- debug!("construct_parameter_environment(): push_types_from_defs: def={:?}",
- def);
- types.push(def.space, self.global_tcx().mk_param_from_def(def));
- }
+ pub fn construct_free_substs(self, def_id: DefId,
+ free_id_outlive: CodeExtent)
+ -> &'gcx Substs<'gcx> {
- // map bound 'a => free 'a
- let mut regions = VecPerParamSpace::empty();
- for def in generics.regions.as_slice() {
- let region =
- ReFree(FreeRegion { scope: free_id_outlive,
- bound_region: def.to_bound_region() });
- debug!("push_region_params {:?}", region);
- regions.push(def.space, region);
- }
+ let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| {
+ // map bound 'a => free 'a
+ ReFree(FreeRegion { scope: free_id_outlive,
+ bound_region: def.to_bound_region() })
+ }, |def, _| {
+ // map T => T
+ self.global_tcx().mk_param_from_def(def)
+ });
- Substs {
- types: types,
- regions: regions,
- }
+ debug!("construct_parameter_environment: {:?}", substs);
+ substs
}
/// See `ParameterEnvironment` struct def'n for details.
/// for the `free_id_outlive` parameter. (But note that that is not always quite right.)
pub fn construct_parameter_environment(self,
span: Span,
- generics: &ty::Generics<'gcx>,
- generic_predicates: &ty::GenericPredicates<'gcx>,
+ def_id: DefId,
free_id_outlive: CodeExtent)
-> ParameterEnvironment<'gcx>
{
// Construct the free substs.
//
- let free_substs = self.construct_free_substs(generics, free_id_outlive);
+ let free_substs = self.construct_free_substs(def_id, free_id_outlive);
//
// Compute the bounds on Self and the type parameters.
//
let tcx = self.global_tcx();
- let bounds = generic_predicates.instantiate(tcx, &free_substs);
+ let generic_predicates = tcx.lookup_predicates(def_id);
+ let bounds = generic_predicates.instantiate(tcx, free_substs);
let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
- let predicates = bounds.predicates.into_vec();
+ let predicates = bounds.predicates;
// Finally, we have to normalize the bounds in the environment, in
// case they contain any associated type projections. This process
//
let unnormalized_env = ty::ParameterEnvironment {
- free_substs: tcx.mk_substs(free_substs),
+ free_substs: free_substs,
implicit_region_bound: ty::ReScope(free_id_outlive),
caller_bounds: predicates,
free_id_outlive: free_id_outlive,
//! type equality, etc.
use hir::def_id::DefId;
-use ty::subst::{ParamSpace, Substs};
+use ty::subst::Substs;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::error::{ExpectedFound, TypeError};
use std::rc::Rc;
-> RelateResult<'tcx, &'tcx Substs<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
- let mut substs = Substs::empty();
-
- for &space in &ParamSpace::all() {
- let a_tps = a_subst.types.get_slice(space);
- let b_tps = b_subst.types.get_slice(space);
- let t_variances = variances.map(|v| v.types.get_slice(space));
- let tps = relate_type_params(relation, t_variances, a_tps, b_tps)?;
- substs.types.replace(space, tps);
- }
-
- for &space in &ParamSpace::all() {
- let a_regions = a_subst.regions.get_slice(space);
- let b_regions = b_subst.regions.get_slice(space);
- let r_variances = variances.map(|v| v.regions.get_slice(space));
- let regions = relate_region_params(relation,
- r_variances,
- a_regions,
- b_regions)?;
- substs.regions.replace(space, regions);
- }
+ let tcx = relation.tcx();
- Ok(relation.tcx().mk_substs(substs))
-}
+ let types = a_subst.types.iter().enumerate().map(|(i, a_ty)| {
+ let b_ty = &b_subst.types[i];
+ let variance = variances.map_or(ty::Invariant, |v| v.types[i]);
+ relation.relate_with_variance(variance, a_ty, b_ty)
+ }).collect()?;
-fn relate_type_params<'a, 'gcx, 'tcx, R>(relation: &mut R,
- variances: Option<&[ty::Variance]>,
- a_tys: &[Ty<'tcx>],
- b_tys: &[Ty<'tcx>])
- -> RelateResult<'tcx, Vec<Ty<'tcx>>>
- where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
-{
- if a_tys.len() != b_tys.len() {
- return Err(TypeError::TyParamSize(expected_found(relation,
- &a_tys.len(),
- &b_tys.len())));
- }
+ let regions = a_subst.regions.iter().enumerate().map(|(i, a_r)| {
+ let b_r = &b_subst.regions[i];
+ let variance = variances.map_or(ty::Invariant, |v| v.regions[i]);
+ relation.relate_with_variance(variance, a_r, b_r)
+ }).collect()?;
- (0 .. a_tys.len())
- .map(|i| {
- let a_ty = a_tys[i];
- let b_ty = b_tys[i];
- let v = variances.map_or(ty::Invariant, |v| v[i]);
- relation.relate_with_variance(v, &a_ty, &b_ty)
- })
- .collect()
-}
-
-fn relate_region_params<'a, 'gcx, 'tcx, R>(relation: &mut R,
- variances: Option<&[ty::Variance]>,
- a_rs: &[ty::Region],
- b_rs: &[ty::Region])
- -> RelateResult<'tcx, Vec<ty::Region>>
- where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
-{
- let num_region_params = a_rs.len();
-
- debug!("relate_region_params(a_rs={:?}, \
- b_rs={:?}, variances={:?})",
- a_rs,
- b_rs,
- variances);
-
- assert_eq!(num_region_params,
- variances.map_or(num_region_params,
- |v| v.len()));
-
- assert_eq!(num_region_params, b_rs.len());
-
- (0..a_rs.len())
- .map(|i| {
- let a_r = a_rs[i];
- let b_r = b_rs[i];
- let variance = variances.map_or(ty::Invariant, |v| v[i]);
- relation.relate_with_variance(variance, &a_r, &b_r)
- })
- .collect()
+ Ok(Substs::new(tcx, types, regions))
}
impl<'tcx> Relate<'tcx> for &'tcx ty::BareFnTy<'tcx> {
}
}
-impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
- a: &ty::ProjectionPredicate<'tcx>,
- b: &ty::ProjectionPredicate<'tcx>)
- -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>>
+ a: &ty::ExistentialProjection<'tcx>,
+ b: &ty::ExistentialProjection<'tcx>)
+ -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
- let projection_ty = relation.relate(&a.projection_ty, &b.projection_ty)?;
- let ty = relation.relate(&a.ty, &b.ty)?;
- Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty })
+ if a.item_name != b.item_name {
+ Err(TypeError::ProjectionNameMismatched(
+ expected_found(relation, &a.item_name, &b.item_name)))
+ } else {
+ let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?;
+ let ty = relation.relate(&a.ty, &b.ty)?;
+ Ok(ty::ExistentialProjection {
+ trait_ref: trait_ref,
+ item_name: a.item_name,
+ ty: ty
+ })
+ }
}
}
-impl<'tcx> Relate<'tcx> for Vec<ty::PolyProjectionPredicate<'tcx>> {
+impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> {
fn relate<'a, 'gcx, R>(relation: &mut R,
- a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
- b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
- -> RelateResult<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
+ a: &Vec<ty::PolyExistentialProjection<'tcx>>,
+ b: &Vec<ty::PolyExistentialProjection<'tcx>>)
+ -> RelateResult<'tcx, Vec<ty::PolyExistentialProjection<'tcx>>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
// To be compatible, `a` and `b` must be for precisely the
}
}
-impl<'tcx> Relate<'tcx> for ty::ExistentialBounds<'tcx> {
- fn relate<'a, 'gcx, R>(relation: &mut R,
- a: &ty::ExistentialBounds<'tcx>,
- b: &ty::ExistentialBounds<'tcx>)
- -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>>
- where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
- {
- let r =
- relation.with_cause(
- Cause::ExistentialRegionBound,
- |relation| relation.relate_with_variance(ty::Contravariant,
- &a.region_bound,
- &b.region_bound))?;
- let nb = relation.relate(&a.builtin_bounds, &b.builtin_bounds)?;
- let pb = relation.relate(&a.projection_bounds, &b.projection_bounds)?;
- Ok(ty::ExistentialBounds { region_bound: r,
- builtin_bounds: nb,
- projection_bounds: pb })
- }
-}
-
impl<'tcx> Relate<'tcx> for ty::BuiltinBounds {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::BuiltinBounds,
}
}
+impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
+ fn relate<'a, 'gcx, R>(relation: &mut R,
+ a: &ty::ExistentialTraitRef<'tcx>,
+ b: &ty::ExistentialTraitRef<'tcx>)
+ -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>>
+ where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
+ {
+ // Different traits cannot be related
+ if a.def_id != b.def_id {
+ Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
+ } else {
+ let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?;
+ Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
+ }
+ }
+}
+
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &Ty<'tcx>,
}
(&ty::TyParam(ref a_p), &ty::TyParam(ref b_p))
- if a_p.idx == b_p.idx && a_p.space == b_p.space =>
+ if a_p.idx == b_p.idx =>
{
Ok(a)
}
Ok(tcx.mk_enum(a_def, substs))
}
- (&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) =>
+ (&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) =>
{
- let principal = relation.relate(&a_.principal, &b_.principal)?;
- let bounds = relation.relate(&a_.bounds, &b_.bounds)?;
- Ok(tcx.mk_trait(principal, bounds))
+ let principal = relation.relate(&a_obj.principal, &b_obj.principal)?;
+ let r =
+ relation.with_cause(
+ Cause::ExistentialRegionBound,
+ |relation| relation.relate_with_variance(ty::Contravariant,
+ &a_obj.region_bound,
+ &b_obj.region_bound))?;
+ let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?;
+ let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?;
+ Ok(tcx.mk_trait(ty::TraitObject {
+ principal: principal,
+ region_bound: r,
+ builtin_bounds: nb,
+ projection_bounds: pb
+ }))
}
(&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs))
// except according to those terms.
use infer::type_variable;
-use ty::subst::{self, VecPerParamSpace};
-use ty::{self, Lift, TraitRef, Ty, TyCtxt};
+use ty::subst::Substs;
+use ty::{self, Lift, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use std::rc::Rc;
}
}
-impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> {
- type Lifted = TraitRef<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<TraitRef<'tcx>> {
- tcx.lift(&self.substs).map(|substs| TraitRef {
+impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
+ type Lifted = ty::TraitRef<'tcx>;
+ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ tcx.lift(&self.substs).map(|substs| ty::TraitRef {
+ def_id: self.def_id,
+ substs: substs
+ })
+ }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialTraitRef<'a> {
+ type Lifted = ty::ExistentialTraitRef<'tcx>;
+ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ tcx.lift(&self.substs).map(|substs| ty::ExistentialTraitRef {
def_id: self.def_id,
substs: substs
})
}
}
+impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> {
+ type Lifted = ty::ExistentialProjection<'tcx>;
+ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ tcx.lift(&(self.trait_ref, self.ty)).map(|(trait_ref, ty)| {
+ ty::ExistentialProjection {
+ trait_ref: trait_ref,
+ item_name: self.item_name,
+ ty: ty
+ }
+ })
+ }
+}
+
impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> {
type Lifted = ty::Predicate<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
}
}
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
- fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- self.map(|elem| elem.fold_with(folder))
- }
-
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.iter().any(|elem| elem.visit_with(visitor))
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::TraitTy<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- ty::TraitTy {
+ ty::TraitObject {
principal: self.principal.fold_with(folder),
- bounds: self.bounds.fold_with(folder),
+ region_bound: self.region_bound.fold_with(folder),
+ builtin_bounds: self.builtin_bounds,
+ projection_bounds: self.projection_bounds.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.principal.visit_with(visitor) || self.bounds.visit_with(visitor)
+ self.principal.visit_with(visitor) ||
+ self.region_bound.visit_with(visitor) ||
+ self.projection_bounds.visit_with(visitor)
}
}
}
}
- fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- folder.fold_trait_ref(self)
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ self.substs.visit_with(visitor)
+ }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+ ty::ExistentialTraitRef {
+ def_id: self.def_id,
+ substs: self.substs.fold_with(folder),
+ }
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx subst::Substs<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- let substs = subst::Substs {
- regions: self.regions.fold_with(folder),
- types: self.types.fold_with(folder)
- };
- folder.tcx().mk_substs(substs)
+ let types = self.types.fold_with(folder);
+ let regions = self.regions.fold_with(folder);
+ Substs::new(folder.tcx(), types, regions)
}
fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
- fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- ty::ExistentialBounds {
- region_bound: self.region_bound.fold_with(folder),
- builtin_bounds: self.builtin_bounds,
- projection_bounds: self.projection_bounds.fold_with(folder),
- }
- }
-
- fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- folder.fold_existential_bounds(self)
- }
-
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.region_bound.visit_with(visitor) || self.projection_bounds.visit_with(visitor)
- }
-}
-
impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TypeParameterDef {
name: self.name,
def_id: self.def_id,
- space: self.space,
index: self.index,
default: self.default.fold_with(folder),
default_def_id: self.default_def_id,
ty::RegionParameterDef {
name: self.name,
def_id: self.def_id,
- space: self.space,
index: self.index,
bounds: self.bounds.fold_with(folder),
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
- fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- ty::Generics {
- types: self.types.fold_with(folder),
- regions: self.regions.fold_with(folder),
- }
- }
-
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.types.visit_with(visitor) || self.regions.visit_with(visitor)
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
- fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- ty::GenericPredicates {
- predicates: self.predicates.fold_with(folder),
- }
- }
-
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.predicates.visit_with(visitor)
- }
-}
-
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match *self {
}
}
+impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+ ty::ExistentialProjection {
+ trait_ref: self.trait_ref.fold_with(folder),
+ item_name: self.item_name,
+ ty: self.ty.fold_with(folder),
+ }
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ self.trait_ref.visit_with(visitor) || self.ty.visit_with(visitor)
+ }
+}
+
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ProjectionTy {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::TypeScheme<'tcx> {
- fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- ty::TypeScheme {
- generics: self.generics.fold_with(folder),
- ty: self.ty.fold_with(folder),
- }
- }
-
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.generics.visit_with(visitor) || self.ty.visit_with(visitor)
- }
-}
-
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound<T> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::error::ExpectedFound {
use middle::cstore;
use hir::def_id::DefId;
use middle::region;
-use ty::subst::{self, Substs};
+use ty::subst::Substs;
use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TyS, TypeFoldable};
use util::common::ErrorReported;
TyFnPtr(&'tcx BareFnTy<'tcx>),
/// A trait, defined with `trait`.
- TyTrait(Box<TraitTy<'tcx>>),
+ TyTrait(Box<TraitObject<'tcx>>),
/// The anonymous type of a closure. Used to represent the type of
/// `|a| a`.
}
#[derive(Clone, PartialEq, Eq, Hash)]
-pub struct TraitTy<'tcx> {
- pub principal: ty::PolyTraitRef<'tcx>,
- pub bounds: ExistentialBounds<'tcx>,
-}
-
-impl<'a, 'gcx, 'tcx> TraitTy<'tcx> {
- pub fn principal_def_id(&self) -> DefId {
- self.principal.0.def_id
- }
-
- /// Object types don't have a self-type specified. Therefore, when
- /// we convert the principal trait-ref into a normal trait-ref,
- /// you must give *some* self-type. A common choice is `mk_err()`
- /// or some skolemized type.
- pub fn principal_trait_ref_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
- self_ty: Ty<'tcx>)
- -> ty::PolyTraitRef<'tcx>
- {
- // otherwise the escaping regions would be captured by the binder
- assert!(!self_ty.has_escaping_regions());
-
- ty::Binder(TraitRef {
- def_id: self.principal.0.def_id,
- substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)),
- })
- }
-
- pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
- self_ty: Ty<'tcx>)
- -> Vec<ty::PolyProjectionPredicate<'tcx>>
- {
- // otherwise the escaping regions would be captured by the binders
- assert!(!self_ty.has_escaping_regions());
-
- self.bounds.projection_bounds.iter()
- .map(|in_poly_projection_predicate| {
- let in_projection_ty = &in_poly_projection_predicate.0.projection_ty;
- let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty));
- let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id,
- substs);
- let projection_ty = ty::ProjectionTy {
- trait_ref: trait_ref,
- item_name: in_projection_ty.item_name
- };
- ty::Binder(ty::ProjectionPredicate {
- projection_ty: projection_ty,
- ty: in_poly_projection_predicate.0.ty
- })
- })
- .collect()
- }
+pub struct TraitObject<'tcx> {
+ pub principal: PolyExistentialTraitRef<'tcx>,
+ pub region_bound: ty::Region,
+ pub builtin_bounds: BuiltinBounds,
+ pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
}
/// A complete reference to a trait. These take numerous guises in syntax,
/// T : Foo<U>
///
/// This would be represented by a trait-reference where the def-id is the
-/// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
-/// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
+/// def-id for the trait `Foo` and the substs define `T` as parameter 0,
+/// and `U` as parameter 1.
///
/// Trait references also appear in object types like `Foo<U>`, but in
/// that case the `Self` parameter is absent from the substitutions.
}
}
+/// An existential reference to a trait, where `Self` is erased.
+/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
+///
+/// exists T. T: Trait<'a, 'b, X, Y>
+///
+/// The substitutions don't include the erased `Self`, only trait
+/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct ExistentialTraitRef<'tcx> {
+ pub def_id: DefId,
+ pub substs: &'tcx Substs<'tcx>,
+}
+
+impl<'tcx> ExistentialTraitRef<'tcx> {
+ pub fn input_types(&self) -> &[Ty<'tcx>] {
+ // Select only the "input types" from a trait-reference. For
+ // now this is all the types that appear in the
+ // trait-reference, but it should eventually exclude
+ // associated types.
+ &self.substs.types
+ }
+}
+
+pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>;
+
+impl<'tcx> PolyExistentialTraitRef<'tcx> {
+ pub fn def_id(&self) -> DefId {
+ self.0.def_id
+ }
+
+ pub fn input_types(&self) -> &[Ty<'tcx>] {
+ // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
+ self.0.input_types()
+ }
+}
+
/// Binder is a binder for higher-ranked lifetimes. It is part of the
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
/// (which would be represented by the type `PolyTraitRef ==
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ParamTy {
- pub space: subst::ParamSpace,
pub idx: u32,
pub name: Name,
}
impl<'a, 'gcx, 'tcx> ParamTy {
- pub fn new(space: subst::ParamSpace,
- index: u32,
- name: Name)
- -> ParamTy {
- ParamTy { space: space, idx: index, name: name }
+ pub fn new(index: u32, name: Name) -> ParamTy {
+ ParamTy { idx: index, name: name }
}
pub fn for_self() -> ParamTy {
- ParamTy::new(subst::SelfSpace, 0, keywords::SelfType.name())
+ ParamTy::new(0, keywords::SelfType.name())
}
pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
- ParamTy::new(def.space, def.index, def.name)
+ ParamTy::new(def.index, def.name)
}
pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
- tcx.mk_param(self.space, self.idx, self.name)
+ tcx.mk_param(self.idx, self.name)
}
pub fn is_self(&self) -> bool {
- self.space == subst::SelfSpace && self.idx == 0
+ if self.name == keywords::SelfType.name() {
+ assert_eq!(self.idx, 0);
+ true
+ } else {
+ false
+ }
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub struct EarlyBoundRegion {
- pub space: subst::ParamSpace,
pub index: u32,
pub name: Name,
}
FreshFloatTy(u32)
}
-/// Bounds suitable for an existentially quantified type parameter
-/// such as those that appear in object types or closure types.
-#[derive(PartialEq, Eq, Hash, Clone)]
-pub struct ExistentialBounds<'tcx> {
- pub region_bound: ty::Region,
- pub builtin_bounds: BuiltinBounds,
- pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
+/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub struct ExistentialProjection<'tcx> {
+ pub trait_ref: ExistentialTraitRef<'tcx>,
+ pub item_name: Name,
+ pub ty: Ty<'tcx>
}
-impl<'tcx> ExistentialBounds<'tcx> {
- pub fn new(region_bound: ty::Region,
- builtin_bounds: BuiltinBounds,
- projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>)
- -> Self {
- let mut projection_bounds = projection_bounds;
- projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
- ExistentialBounds {
- region_bound: region_bound,
- builtin_bounds: builtin_bounds,
- projection_bounds: projection_bounds
- }
+pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
+
+impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
+ pub fn item_name(&self) -> Name {
+ self.0.item_name // safe to skip the binder to access a name
+ }
+
+ pub fn sort_key(&self) -> (DefId, Name) {
+ (self.0.trait_ref.def_id, self.0.item_name)
+ }
+
+ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ self_ty: Ty<'tcx>)
+ -> ty::PolyProjectionPredicate<'tcx>
+ {
+ // otherwise the escaping regions would be captured by the binders
+ assert!(!self_ty.has_escaping_regions());
+
+ let trait_ref = self.map_bound(|proj| proj.trait_ref);
+ self.map_bound(|proj| ty::ProjectionPredicate {
+ projection_ty: ty::ProjectionTy {
+ trait_ref: trait_ref.with_self_ty(tcx, self_ty).0,
+ item_name: proj.item_name
+ },
+ ty: proj.ty
+ })
}
}
pub fn is_bool(&self) -> bool { self.sty == TyBool }
- pub fn is_param(&self, space: subst::ParamSpace, index: u32) -> bool {
+ pub fn is_param(&self, index: u32) -> bool {
match self.sty {
- ty::TyParam(ref data) => data.space == space && data.idx == index,
+ ty::TyParam(ref data) => data.idx == index,
_ => false,
}
}
pub fn is_self(&self) -> bool {
match self.sty {
- TyParam(ref p) => p.space == subst::SelfSpace,
+ TyParam(ref p) => p.is_self(),
_ => false
}
}
pub fn ty_to_def_id(&self) -> Option<DefId> {
match self.sty {
- TyTrait(ref tt) => Some(tt.principal_def_id()),
+ TyTrait(ref tt) => Some(tt.principal.def_id()),
TyStruct(def, _) |
TyEnum(def, _) => Some(def.did),
TyClosure(id, _) => Some(id),
vec![*region]
}
TyTrait(ref obj) => {
- let mut v = vec![obj.bounds.region_bound];
- v.extend_from_slice(obj.principal.skip_binder()
- .substs.regions.as_slice());
+ let mut v = vec![obj.region_bound];
+ v.extend_from_slice(&obj.principal.skip_binder().substs.regions);
v
}
TyEnum(_, substs) |
TyStruct(_, substs) |
TyAnon(_, substs) => {
- substs.regions.as_slice().to_vec()
+ substs.regions.to_vec()
}
TyClosure(_, ref substs) => {
- substs.func_substs.regions.as_slice().to_vec()
+ substs.func_substs.regions.to_vec()
}
TyProjection(ref data) => {
- data.trait_ref.substs.regions.as_slice().to_vec()
+ data.trait_ref.substs.regions.to_vec()
}
TyFnDef(..) |
TyFnPtr(_) |
// Type substitutions.
-pub use self::ParamSpace::*;
-
use middle::cstore;
use hir::def_id::DefId;
use ty::{self, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
use serialize::{Encodable, Encoder, Decodable, Decoder};
-use std::fmt;
-use std::iter::IntoIterator;
-use std::slice::Iter;
-use std::vec::{Vec, IntoIter};
use syntax_pos::{Span, DUMMY_SP};
///////////////////////////////////////////////////////////////////////////
-/// A substitution mapping type/region parameters to new values. We
-/// identify each in-scope parameter by an *index* and a *parameter
-/// space* (which indices where the parameter is defined; see
-/// `ParamSpace`).
+/// A substitution mapping type/region parameters to new values.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Substs<'tcx> {
- pub types: VecPerParamSpace<Ty<'tcx>>,
- pub regions: VecPerParamSpace<ty::Region>,
+ pub types: Vec<Ty<'tcx>>,
+ pub regions: Vec<ty::Region>,
}
impl<'a, 'gcx, 'tcx> Substs<'tcx> {
- pub fn new(t: VecPerParamSpace<Ty<'tcx>>,
- r: VecPerParamSpace<ty::Region>)
- -> Substs<'tcx>
- {
- Substs { types: t, regions: r }
- }
-
- pub fn new_type(t: Vec<Ty<'tcx>>,
- r: Vec<ty::Region>)
- -> Substs<'tcx>
+ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ t: Vec<Ty<'tcx>>,
+ r: Vec<ty::Region>)
+ -> &'tcx Substs<'tcx>
{
- Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
- VecPerParamSpace::new(r, Vec::new(), Vec::new()))
+ tcx.mk_substs(Substs { types: t, regions: r })
}
- pub fn new_trait(t: Vec<Ty<'tcx>>,
+ pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ mut t: Vec<Ty<'tcx>>,
r: Vec<ty::Region>,
s: Ty<'tcx>)
- -> Substs<'tcx>
+ -> &'tcx Substs<'tcx>
{
- Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
- VecPerParamSpace::new(r, Vec::new(), Vec::new()))
- }
-
- pub fn empty() -> Substs<'tcx> {
- Substs {
- types: VecPerParamSpace::empty(),
- regions: VecPerParamSpace::empty(),
- }
- }
+ t.insert(0, s);
+ Substs::new(tcx, t, r)
+ }
+
+ pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> {
+ Substs::new(tcx, vec![], vec![])
+ }
+
+ /// Creates a Substs for generic parameter definitions,
+ /// by calling closures to obtain each region and type.
+ /// The closures get to observe the Substs as they're
+ /// being built, which can be used to correctly
+ /// substitute defaults of type parameters.
+ pub fn for_item<FR, FT>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ def_id: DefId,
+ mut mk_region: FR,
+ mut mk_type: FT)
+ -> &'tcx Substs<'tcx>
+ where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
+ FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
+ let defs = tcx.lookup_generics(def_id);
+ let num_regions = defs.parent_regions as usize + defs.regions.len();
+ let num_types = defs.parent_types as usize + defs.types.len();
+ let mut substs = Substs {
+ regions: Vec::with_capacity(num_regions),
+ types: Vec::with_capacity(num_types)
+ };
- pub fn is_noop(&self) -> bool {
- self.regions.is_empty() && self.types.is_empty()
- }
+ substs.fill_item(tcx, defs, &mut mk_region, &mut mk_type);
- pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
- *self.types.get(ty_param_def.space, ty_param_def.index as usize)
+ Substs::new(tcx, substs.types, substs.regions)
}
- pub fn self_ty(&self) -> Option<Ty<'tcx>> {
- self.types.get_self().cloned()
- }
+ fn fill_item<FR, FT>(&mut self,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ defs: &ty::Generics<'tcx>,
+ mk_region: &mut FR,
+ mk_type: &mut FT)
+ where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
+ FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
+ if let Some(def_id) = defs.parent {
+ let parent_defs = tcx.lookup_generics(def_id);
+ self.fill_item(tcx, parent_defs, mk_region, mk_type);
+ }
- pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> {
- assert!(self.self_ty().is_none());
- let mut s = (*self).clone();
- s.types.push(SelfSpace, self_ty);
- s
- }
+ for def in &defs.regions {
+ let region = mk_region(def, self);
+ assert_eq!(def.index as usize, self.regions.len());
+ self.regions.push(region);
+ }
- pub fn erase_regions(self) -> Substs<'tcx> {
- let Substs { types, regions } = self;
- let regions = regions.map(|_| ty::ReErased);
- Substs { types: types, regions: regions }
+ for def in &defs.types {
+ let ty = mk_type(def, self);
+ assert_eq!(def.index as usize, self.types.len());
+ self.types.push(ty);
+ }
}
- pub fn with_method(self,
- m_types: Vec<Ty<'tcx>>,
- m_regions: Vec<ty::Region>)
- -> Substs<'tcx>
- {
- let Substs { types, regions } = self;
- let types = types.with_slice(FnSpace, &m_types);
- let regions = regions.with_slice(FnSpace, &m_regions);
- Substs { types: types, regions: regions }
+ pub fn is_noop(&self) -> bool {
+ self.regions.is_empty() && self.types.is_empty()
}
- pub fn with_method_from(&self,
- meth_substs: &Substs<'tcx>)
- -> Substs<'tcx>
- {
- let Substs { types, regions } = self.clone();
- let types = types.with_slice(FnSpace, meth_substs.types.get_slice(FnSpace));
- let regions = regions.with_slice(FnSpace, meth_substs.regions.get_slice(FnSpace));
- Substs { types: types, regions: regions }
+ pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
+ self.types[ty_param_def.index as usize]
}
- pub fn with_method_from_subst(&self, other: &Substs<'tcx>) -> Substs<'tcx> {
- let Substs { types, regions } = self.clone();
- let types = types.with_slice(FnSpace, other.types.get_slice(FnSpace));
- let regions = regions.with_slice(FnSpace, other.regions.get_slice(FnSpace));
- Substs { types: types, regions: regions }
+ pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region {
+ self.regions[def.index as usize]
}
- /// Creates a trait-ref out of this substs, ignoring the FnSpace substs
- pub fn to_trait_ref(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_id: DefId)
- -> ty::TraitRef<'tcx> {
- let Substs { mut types, mut regions } = self.clone();
- types.truncate(FnSpace, 0);
- regions.truncate(FnSpace, 0);
-
- ty::TraitRef {
- def_id: trait_id,
- substs: tcx.mk_substs(Substs { types: types, regions: regions })
- }
+ /// Transform from substitutions for a child of `source_ancestor`
+ /// (e.g. a trait or impl) to substitutions for the same child
+ /// in a different item, with `target_substs` as the base for
+ /// the target impl/trait, with the source child-specific
+ /// parameters (e.g. method parameters) on top of that base.
+ pub fn rebase_onto(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ source_ancestor: DefId,
+ target_substs: &Substs<'tcx>)
+ -> &'tcx Substs<'tcx> {
+ let defs = tcx.lookup_generics(source_ancestor);
+ let regions = target_substs.regions.iter()
+ .chain(&self.regions[defs.regions.len()..]).cloned().collect();
+ let types = target_substs.types.iter()
+ .chain(&self.types[defs.types.len()..]).cloned().collect();
+ Substs::new(tcx, types, regions)
}
}
-impl<'tcx> Encodable for Substs<'tcx> {
+impl<'tcx> Encodable for &'tcx Substs<'tcx> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
cstore::tls::with_encoding_context(s, |ecx, rbml_w| {
ecx.encode_substs(rbml_w, self);
}
}
-impl<'tcx> Decodable for Substs<'tcx> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Substs<'tcx>, D::Error> {
- cstore::tls::with_decoding_context(d, |dcx, rbml_r| {
- Ok(dcx.decode_substs(rbml_r))
- })
- }
-}
-
impl<'tcx> Decodable for &'tcx Substs<'tcx> {
fn decode<D: Decoder>(d: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error> {
let substs = cstore::tls::with_decoding_context(d, |dcx, rbml_r| {
- let substs = dcx.decode_substs(rbml_r);
- dcx.tcx().mk_substs(substs)
+ dcx.decode_substs(rbml_r)
});
Ok(substs)
}
}
-///////////////////////////////////////////////////////////////////////////
-// ParamSpace
-
-#[derive(PartialOrd, Ord, PartialEq, Eq, Copy,
- Clone, Hash, RustcEncodable, RustcDecodable, Debug)]
-pub enum ParamSpace {
- TypeSpace, // Type parameters attached to a type definition, trait, or impl
- SelfSpace, // Self parameter on a trait
- FnSpace, // Type parameters attached to a method or fn
-}
-
-impl ParamSpace {
- pub fn all() -> [ParamSpace; 3] {
- [TypeSpace, SelfSpace, FnSpace]
- }
-
- pub fn to_uint(self) -> usize {
- match self {
- TypeSpace => 0,
- SelfSpace => 1,
- FnSpace => 2,
- }
- }
-
- pub fn from_uint(u: usize) -> ParamSpace {
- match u {
- 0 => TypeSpace,
- 1 => SelfSpace,
- 2 => FnSpace,
- _ => bug!("Invalid ParamSpace: {}", u)
- }
- }
-}
-
-/// Vector of things sorted by param space. Used to keep
-/// the set of things declared on the type, self, or method
-/// distinct.
-#[derive(PartialEq, Eq, Clone, Hash, RustcEncodable, RustcDecodable)]
-pub struct VecPerParamSpace<T> {
- // This was originally represented as a tuple with one Vec<T> for
- // each variant of ParamSpace, and that remains the abstraction
- // that it provides to its clients.
- //
- // Here is how the representation corresponds to the abstraction
- // i.e. the "abstraction function" AF:
- //
- // AF(self) = (self.content[..self.type_limit],
- // self.content[self.type_limit..self.self_limit],
- // self.content[self.self_limit..])
- type_limit: usize,
- self_limit: usize,
- content: Vec<T>,
-}
-
-/// The `split` function converts one `VecPerParamSpace` into this
-/// `SeparateVecsPerParamSpace` structure.
-pub struct SeparateVecsPerParamSpace<T> {
- pub types: Vec<T>,
- pub selfs: Vec<T>,
- pub fns: Vec<T>,
-}
-
-impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "[{:?};{:?};{:?}]",
- self.get_slice(TypeSpace),
- self.get_slice(SelfSpace),
- self.get_slice(FnSpace))
- }
-}
-
-impl<T> VecPerParamSpace<T> {
- fn limits(&self, space: ParamSpace) -> (usize, usize) {
- match space {
- TypeSpace => (0, self.type_limit),
- SelfSpace => (self.type_limit, self.self_limit),
- FnSpace => (self.self_limit, self.content.len()),
- }
- }
-
- pub fn empty() -> VecPerParamSpace<T> {
- VecPerParamSpace {
- type_limit: 0,
- self_limit: 0,
- content: Vec::new()
- }
- }
-
- /// `t` is the type space.
- /// `s` is the self space.
- /// `f` is the fn space.
- pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
- let type_limit = t.len();
- let self_limit = type_limit + s.len();
-
- let mut content = t;
- content.extend(s);
- content.extend(f);
-
- VecPerParamSpace {
- type_limit: type_limit,
- self_limit: self_limit,
- content: content,
- }
- }
-
- fn new_internal(content: Vec<T>, type_limit: usize, self_limit: usize)
- -> VecPerParamSpace<T>
- {
- VecPerParamSpace {
- type_limit: type_limit,
- self_limit: self_limit,
- content: content,
- }
- }
-
- /// Appends `value` to the vector associated with `space`.
- ///
- /// Unlike the `push` method in `Vec`, this should not be assumed
- /// to be a cheap operation (even when amortized over many calls).
- pub fn push(&mut self, space: ParamSpace, value: T) {
- let (_, limit) = self.limits(space);
- match space {
- TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
- SelfSpace => { self.self_limit += 1; }
- FnSpace => { }
- }
- self.content.insert(limit, value);
- }
-
- /// Appends `values` to the vector associated with `space`.
- ///
- /// Unlike the `extend` method in `Vec`, this should not be assumed
- /// to be a cheap operation (even when amortized over many calls).
- pub fn extend<I:Iterator<Item=T>>(&mut self, space: ParamSpace, values: I) {
- // This could be made more efficient, obviously.
- for item in values {
- self.push(space, item);
- }
- }
-
- pub fn pop(&mut self, space: ParamSpace) -> Option<T> {
- let (start, limit) = self.limits(space);
- if start == limit {
- None
- } else {
- match space {
- TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
- SelfSpace => { self.self_limit -= 1; }
- FnSpace => {}
- }
- if self.content.is_empty() {
- None
- } else {
- Some(self.content.remove(limit - 1))
- }
- }
- }
-
- pub fn truncate(&mut self, space: ParamSpace, len: usize) {
- // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
- while self.len(space) > len {
- self.pop(space);
- }
- }
-
- pub fn replace(&mut self, space: ParamSpace, elems: Vec<T>) {
- // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
- self.truncate(space, 0);
- for t in elems {
- self.push(space, t);
- }
- }
-
- pub fn get_self<'a>(&'a self) -> Option<&'a T> {
- let v = self.get_slice(SelfSpace);
- assert!(v.len() <= 1);
- if v.is_empty() { None } else { Some(&v[0]) }
- }
-
- pub fn len(&self, space: ParamSpace) -> usize {
- self.get_slice(space).len()
- }
-
- pub fn is_empty_in(&self, space: ParamSpace) -> bool {
- self.len(space) == 0
- }
-
- pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] {
- let (start, limit) = self.limits(space);
- &self.content[start.. limit]
- }
-
- pub fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] {
- let (start, limit) = self.limits(space);
- &mut self.content[start.. limit]
- }
-
- pub fn opt_get<'a>(&'a self,
- space: ParamSpace,
- index: usize)
- -> Option<&'a T> {
- let v = self.get_slice(space);
- if index < v.len() { Some(&v[index]) } else { None }
- }
-
- pub fn get<'a>(&'a self, space: ParamSpace, index: usize) -> &'a T {
- &self.get_slice(space)[index]
- }
-
- pub fn iter<'a>(&'a self) -> Iter<'a,T> {
- self.content.iter()
- }
-
- pub fn into_iter(self) -> IntoIter<T> {
- self.content.into_iter()
- }
-
- pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> {
- EnumeratedItems::new(self)
- }
-
- pub fn as_slice(&self) -> &[T] {
- &self.content
- }
-
- pub fn into_vec(self) -> Vec<T> {
- self.content
- }
-
- pub fn all_vecs<P>(&self, mut pred: P) -> bool where
- P: FnMut(&[T]) -> bool,
- {
- let spaces = [TypeSpace, SelfSpace, FnSpace];
- spaces.iter().all(|&space| { pred(self.get_slice(space)) })
- }
-
- pub fn all<P>(&self, pred: P) -> bool where P: FnMut(&T) -> bool {
- self.iter().all(pred)
- }
-
- pub fn any<P>(&self, pred: P) -> bool where P: FnMut(&T) -> bool {
- self.iter().any(pred)
- }
-
- pub fn is_empty(&self) -> bool {
- self.all_vecs(|v| v.is_empty())
- }
-
- pub fn map<U, P>(&self, pred: P) -> VecPerParamSpace<U> where P: FnMut(&T) -> U {
- let result = self.iter().map(pred).collect();
- VecPerParamSpace::new_internal(result,
- self.type_limit,
- self.self_limit)
- }
-
- pub fn map_enumerated<U, P>(&self, pred: P) -> VecPerParamSpace<U> where
- P: FnMut((ParamSpace, usize, &T)) -> U,
- {
- let result = self.iter_enumerated().map(pred).collect();
- VecPerParamSpace::new_internal(result,
- self.type_limit,
- self.self_limit)
- }
-
- pub fn split(self) -> SeparateVecsPerParamSpace<T> {
- let VecPerParamSpace { type_limit, self_limit, content } = self;
-
- let mut content_iter = content.into_iter();
-
- SeparateVecsPerParamSpace {
- types: content_iter.by_ref().take(type_limit).collect(),
- selfs: content_iter.by_ref().take(self_limit - type_limit).collect(),
- fns: content_iter.collect()
- }
- }
-
- pub fn with_slice(mut self, space: ParamSpace, slice: &[T])
- -> VecPerParamSpace<T>
- where T: Clone
- {
- assert!(self.is_empty_in(space));
- for t in slice {
- self.push(space, t.clone());
- }
-
- self
- }
-}
-
-#[derive(Clone)]
-pub struct EnumeratedItems<'a,T:'a> {
- vec: &'a VecPerParamSpace<T>,
- space_index: usize,
- elem_index: usize
-}
-
-impl<'a,T> EnumeratedItems<'a,T> {
- fn new(v: &'a VecPerParamSpace<T>) -> EnumeratedItems<'a,T> {
- let mut result = EnumeratedItems { vec: v, space_index: 0, elem_index: 0 };
- result.adjust_space();
- result
- }
-
- fn adjust_space(&mut self) {
- let spaces = ParamSpace::all();
- while
- self.space_index < spaces.len() &&
- self.elem_index >= self.vec.len(spaces[self.space_index])
- {
- self.space_index += 1;
- self.elem_index = 0;
- }
- }
-}
-
-impl<'a,T> Iterator for EnumeratedItems<'a,T> {
- type Item = (ParamSpace, usize, &'a T);
-
- fn next(&mut self) -> Option<(ParamSpace, usize, &'a T)> {
- let spaces = ParamSpace::all();
- if self.space_index < spaces.len() {
- let space = spaces[self.space_index];
- let index = self.elem_index;
- let item = self.vec.get(space, index);
-
- self.elem_index += 1;
- self.adjust_space();
-
- Some((space, index, item))
- } else {
- None
- }
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- let size = self.vec.as_slice().len();
- (size, Some(size))
- }
-}
-
-impl<T> IntoIterator for VecPerParamSpace<T> {
- type Item = T;
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_vec().into_iter()
- }
-}
-
-impl<'a,T> IntoIterator for &'a VecPerParamSpace<T> {
- type Item = &'a T;
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.as_slice().into_iter()
- }
-}
-
///////////////////////////////////////////////////////////////////////////
// Public trait `Subst`
// the specialized routine `ty::replace_late_regions()`.
match r {
ty::ReEarlyBound(data) => {
- match self.substs.regions.opt_get(data.space, data.index as usize) {
+ match self.substs.regions.get(data.index as usize) {
Some(&r) => {
self.shift_region_through_binders(r)
}
span,
"Region parameter out of range \
when substituting in region {} (root type={:?}) \
- (space={:?}, index={})",
+ (index={})",
data.name,
self.root_ty,
- data.space,
data.index);
}
}
impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
// Look up the type in the substitutions. It really should be in there.
- let opt_ty = self.substs.types.opt_get(p.space, p.idx as usize);
+ let opt_ty = self.substs.types.get(p.idx as usize);
let ty = match opt_ty {
Some(t) => *t,
None => {
let span = self.span.unwrap_or(DUMMY_SP);
span_bug!(
span,
- "Type parameter `{:?}` ({:?}/{:?}/{}) out of range \
+ "Type parameter `{:?}` ({:?}/{}) out of range \
when substituting (root type={:?}) substs={:?}",
p,
source_ty,
- p.space,
p.idx,
self.root_ty,
self.substs);
ty::fold::shift_region(region, self.region_binders_passed)
}
}
+
+// Helper methods that modify substitutions.
+
+impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> {
+ pub fn from_method(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ trait_id: DefId,
+ substs: &Substs<'tcx>)
+ -> ty::TraitRef<'tcx> {
+ let defs = tcx.lookup_generics(trait_id);
+ let regions = substs.regions[..defs.regions.len()].to_vec();
+ let types = substs.types[..defs.types.len()].to_vec();
+
+ ty::TraitRef {
+ def_id: trait_id,
+ substs: Substs::new(tcx, types, regions)
+ }
+ }
+}
+
+impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> {
+ pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ trait_ref: ty::TraitRef<'tcx>)
+ -> ty::ExistentialTraitRef<'tcx> {
+ let Substs { mut types, regions } = trait_ref.substs.clone();
+
+ types.remove(0);
+
+ ty::ExistentialTraitRef {
+ def_id: trait_ref.def_id,
+ substs: Substs::new(tcx, types, regions)
+ }
+ }
+}
+
+impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> {
+ /// Object types don't have a self-type specified. Therefore, when
+ /// we convert the principal trait-ref into a normal trait-ref,
+ /// you must give *some* self-type. A common choice is `mk_err()`
+ /// or some skolemized type.
+ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ self_ty: Ty<'tcx>)
+ -> ty::PolyTraitRef<'tcx> {
+ // otherwise the escaping regions would be captured by the binder
+ assert!(!self_ty.has_escaping_regions());
+
+ self.map_bound(|trait_ref| {
+ let Substs { mut types, regions } = trait_ref.substs.clone();
+
+ types.insert(0, self_ty);
+
+ ty::TraitRef {
+ def_id: trait_ref.def_id,
+ substs: Substs::new(tcx, types, regions)
+ }
+ })
+ }
+}
/// `Eq`, there is a single bound `Self : Eq`). This is so that
/// default methods get to assume that the `Self` parameters
/// implements the trait.
- pub generics: ty::Generics<'tcx>,
+ pub generics: &'tcx ty::Generics<'tcx>,
pub trait_ref: ty::TraitRef<'tcx>,
impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
pub fn new(unsafety: hir::Unsafety,
paren_sugar: bool,
- generics: ty::Generics<'tcx>,
+ generics: &'tcx ty::Generics<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
associated_type_names: Vec<Name>)
-> TraitDef<'tcx> {
//! misc. type-system utilities too small to deserve their own file
use hir::def_id::DefId;
-use ty::subst;
use infer::InferCtxt;
use hir::pat_util;
use traits::{self, Reveal};
// to sort them again by the name, in string form.
// Hash the whole principal trait ref.
- self.def_id(data.principal_def_id());
+ self.def_id(data.principal.def_id());
data.principal.visit_with(self);
// Hash region and builtin bounds.
- data.bounds.region_bound.visit_with(self);
- self.hash(data.bounds.builtin_bounds);
+ data.region_bound.visit_with(self);
+ self.hash(data.builtin_bounds);
// Only projection bounds are left, sort and hash them.
- let mut projection_bounds: Vec<_> = data.bounds.projection_bounds
+ let mut projection_bounds: Vec<_> = data.projection_bounds
.iter()
.map(|b| (b.item_name().as_str(), b))
.collect();
projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
for (name, bound) in projection_bounds {
- self.def_id(bound.0.projection_ty.trait_ref.def_id);
+ self.def_id(bound.0.trait_ref.def_id);
self.hash(name);
bound.visit_with(self);
}
self.hash(tys.len());
}
TyParam(p) => {
- self.hash(p.space);
self.hash(p.idx);
self.hash(p.name.as_str());
}
return false;
}
- let types_a = substs_a.types.get_slice(subst::TypeSpace);
- let types_b = substs_b.types.get_slice(subst::TypeSpace);
+ let types_a = &substs_a.types;
+ let types_b = &substs_b.types;
- let mut pairs = types_a.iter().zip(types_b);
-
- pairs.all(|(&a, &b)| same_type(a, b))
+ types_a.iter().zip(types_b).all(|(&a, &b)| same_type(a, b))
}
_ => {
a == b
stack.push(mt.ty);
}
ty::TyProjection(ref data) => {
- push_reversed(stack, data.trait_ref.substs.types.as_slice());
+ push_reversed(stack, &data.trait_ref.substs.types);
}
- ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
- push_reversed(stack, principal.substs().types.as_slice());
- push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| {
+ ty::TyTrait(ref obj) => {
+ push_reversed(stack, obj.principal.input_types());
+ push_reversed(stack, &obj.projection_bounds.iter().map(|pred| {
pred.0.ty
}).collect::<Vec<_>>());
}
ty::TyEnum(_, ref substs) |
ty::TyStruct(_, ref substs) |
ty::TyAnon(_, ref substs) => {
- push_reversed(stack, substs.types.as_slice());
+ push_reversed(stack, &substs.types);
}
ty::TyClosure(_, ref substs) => {
- push_reversed(stack, substs.func_substs.types.as_slice());
+ push_reversed(stack, &substs.func_substs.types);
push_reversed(stack, &substs.upvar_tys);
}
ty::TyTuple(ref ts) => {
push_reversed(stack, ts);
}
ty::TyFnDef(_, substs, ref ft) => {
- push_reversed(stack, substs.types.as_slice());
+ push_reversed(stack, &substs.types);
push_sig_subtypes(stack, &ft.sig);
}
ty::TyFnPtr(ref ft) => {
let cause = self.cause(traits::MiscObligation);
self.out.extend(
trait_ref.substs.types
- .as_slice()
.iter()
.filter(|ty| !ty.has_escaping_regions())
.map(|ty| traits::Obligation::new(cause.clone(),
// FIXME(#33243): remove RFC1592
self.out.push(traits::Obligation::new(
cause.clone(),
- ty::Predicate::ObjectSafe(data.principal_def_id())
+ ty::Predicate::ObjectSafe(data.principal.def_id())
));
let component_traits =
- data.bounds.builtin_bounds.iter().flat_map(|bound| {
+ data.builtin_bounds.iter().flat_map(|bound| {
tcx.lang_items.from_builtin_kind(bound).ok()
});
-// .chain(Some(data.principal_def_id()));
+// .chain(Some(data.principal.def_id()));
self.out.extend(
component_traits.map(|did| { traits::Obligation::new(
cause.clone(),
.collect()
}
- fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) {
+ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) {
// Imagine a type like this:
//
// trait Foo { }
if !data.has_escaping_regions() {
let implicit_bounds =
object_region_bounds(self.infcx.tcx,
- &data.principal,
- data.bounds.builtin_bounds);
+ data.principal,
+ data.builtin_bounds);
- let explicit_bound = data.bounds.region_bound;
+ let explicit_bound = data.region_bound;
for implicit_bound in implicit_bounds {
let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
/// `ty::required_region_bounds`, see that for more information.
pub fn object_region_bounds<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- principal: &ty::PolyTraitRef<'tcx>,
+ principal: ty::PolyExistentialTraitRef<'tcx>,
others: ty::BuiltinBounds)
-> Vec<ty::Region>
{
// a skolemized type.
let open_ty = tcx.mk_infer(ty::FreshTy(0));
- // Note that we preserve the overall binding levels here.
- assert!(!open_ty.has_escaping_regions());
- let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
- let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs)));
-
let mut predicates = others.to_predicates(tcx, open_ty);
- predicates.extend(trait_refs.iter().map(|t| t.to_predicate()));
+ predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate());
tcx.required_region_bounds(open_ty, predicates)
}
use hir::def_id::DefId;
-use ty::subst::{self, Subst};
+use ty::subst::{self, Subst, Substs};
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
use ty::{TyBool, TyChar, TyStruct, TyEnum};
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
}
/// Namespace of the path given to parameterized to print.
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Ns {
Type,
Value
}
-fn number_of_supplied_defaults<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- substs: &subst::Substs,
- space: subst::ParamSpace,
- generics: ty::Generics<'tcx>)
- -> usize
-{
- let has_self = substs.self_ty().is_some();
- let ty_params = generics.types.get_slice(space);
- let tps = substs.types.get_slice(space);
- if ty_params.last().map_or(false, |def| def.default.is_some()) {
- let substs = tcx.lift(&substs);
- ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| {
- match def.default {
- Some(default) => {
- if !has_self && default.has_self_ty() {
- // In an object type, there is no `Self`, and
- // thus if the default value references Self,
- // the user will be required to give an
- // explicit value. We can't even do the
- // substitution below to check without causing
- // an ICE. (#18956).
- false
- } else {
- let default = tcx.lift(&default);
- substs.and_then(|substs| default.subst(tcx, substs))
- == Some(actual)
+pub fn parameterized(f: &mut fmt::Formatter,
+ substs: &subst::Substs,
+ did: DefId,
+ ns: Ns,
+ projections: &[ty::ProjectionPredicate])
+ -> fmt::Result {
+ let mut verbose = false;
+ let mut num_supplied_defaults = 0;
+ let mut has_self = false;
+ let mut num_regions = 0;
+ let mut num_types = 0;
+ let mut item_name = None;
+ let fn_trait_kind = ty::tls::with(|tcx| {
+ let mut generics = tcx.lookup_generics(did);
+ let mut path_def_id = did;
+ verbose = tcx.sess.verbose();
+ has_self = generics.has_self;
+
+ if let Some(def_id) = generics.parent {
+ // Methods.
+ assert_eq!(ns, Ns::Value);
+ generics = tcx.lookup_generics(def_id);
+ num_regions = generics.regions.len();
+ num_types = generics.types.len();
+
+ if has_self {
+ write!(f, "<{} as ", substs.types[0])?;
+ }
+
+ item_name = Some(tcx.item_name(did));
+ path_def_id = def_id;
+ } else {
+ if ns == Ns::Value {
+ // Functions.
+ assert_eq!(has_self, false);
+ } else {
+ // Types and traits.
+ num_regions = generics.regions.len();
+ num_types = generics.types.len();
+ }
+ }
+
+ if !verbose {
+ if generics.types.last().map_or(false, |def| def.default.is_some()) {
+ if let Some(substs) = tcx.lift(&substs) {
+ let tps = &substs.types[..num_types];
+ for (def, actual) in generics.types.iter().zip(tps).rev() {
+ if def.default.subst(tcx, substs) != Some(actual) {
+ break;
+ }
+ num_supplied_defaults += 1;
}
}
- None => false
}
- }).count()
- } else {
- 0
- }
-}
-
-pub fn parameterized<GG>(f: &mut fmt::Formatter,
- substs: &subst::Substs,
- did: DefId,
- ns: Ns,
- projections: &[ty::ProjectionPredicate],
- get_generics: GG)
- -> fmt::Result
- where GG: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>)
- -> Option<ty::Generics<'tcx>>
-{
- if let (Ns::Value, Some(self_ty)) = (ns, substs.self_ty()) {
- write!(f, "<{} as ", self_ty)?;
- }
+ }
- let (fn_trait_kind, verbose, item_name) = ty::tls::with(|tcx| {
- let (did, item_name) = if ns == Ns::Value {
- // Try to get the impl/trait parent, if this is an
- // associated value item (method or constant).
- tcx.trait_of_item(did).or_else(|| tcx.impl_of_method(did))
- .map_or((did, None), |parent| (parent, Some(tcx.item_name(did))))
- } else {
- (did, None)
- };
- write!(f, "{}", tcx.item_path_str(did))?;
- Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose(), item_name))
+ write!(f, "{}", tcx.item_path_str(path_def_id))?;
+ Ok(tcx.lang_items.fn_trait_kind(path_def_id))
})?;
if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
let projection_ty = projections[0].ty;
- if let TyTuple(ref args) = substs.types.get_slice(subst::TypeSpace)[0].sty {
+ if let TyTuple(ref args) = substs.types[1].sty {
return fn_sig(f, args, false, projection_ty);
}
}
Ok(())
};
- print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?;
-
- let num_supplied_defaults = if verbose {
- 0
- } else {
- ty::tls::with(|tcx| {
- if let Some(generics) = get_generics(tcx) {
- number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics)
- } else {
- 0
- }
- })
- };
+ print_regions(f, "<", &substs.regions[..num_regions])?;
- let tps = substs.types.get_slice(subst::TypeSpace);
+ let tps = &substs.types[..num_types];
- for &ty in &tps[..tps.len() - num_supplied_defaults] {
+ for &ty in &tps[has_self as usize..tps.len() - num_supplied_defaults] {
start_or_continue(f, "<", ", ")?;
write!(f, "{}", ty)?;
}
if ns == Ns::Value {
empty.set(true);
- if substs.self_ty().is_some() {
+ if has_self {
write!(f, ">")?;
}
write!(f, "::{}", item_name)?;
}
- print_regions(f, "::<", substs.regions.get_slice(subst::FnSpace))?;
+ print_regions(f, "::<", &substs.regions[num_regions..])?;
// FIXME: consider being smart with defaults here too
- for ty in substs.types.get_slice(subst::FnSpace) {
+ for ty in &substs.types[num_types..] {
start_or_continue(f, "::<", ", ")?;
write!(f, "{}", ty)?;
}
/// projection bounds, so we just stuff them altogether. But in
/// reality we should eventually sort things out better.
#[derive(Clone, Debug)]
-struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
+struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>,
+ Vec<ty::ProjectionPredicate<'tcx>>);
impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
parameterized(f, trait_ref.substs,
trait_ref.def_id,
Ns::Type,
- projection_bounds,
- |tcx| Some(tcx.lookup_trait_def(trait_ref.def_id).generics.clone()))
+ projection_bounds)
}
}
-impl<'tcx> fmt::Display for ty::TraitTy<'tcx> {
+impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let bounds = &self.bounds;
-
// Generate the main trait ref, including associated types.
ty::tls::with(|tcx| {
- let principal = tcx.lift(&self.principal.0)
- .expect("could not lift TraitRef for printing");
- let projections = tcx.lift(&bounds.projection_bounds[..])
- .expect("could not lift projections for printing");
- let projections = projections.into_iter().map(|p| p.0).collect();
+ // Use a type that can't appear in defaults of type parameters.
+ let dummy_self = tcx.mk_infer(ty::FreshTy(0));
+
+ let principal = tcx.lift(&self.principal)
+ .expect("could not lift TraitRef for printing")
+ .with_self_ty(tcx, dummy_self).0;
+ let projections = self.projection_bounds.iter().map(|p| {
+ tcx.lift(p)
+ .expect("could not lift projection for printing")
+ .with_self_ty(tcx, dummy_self).0
+ }).collect();
let tap = ty::Binder(TraitAndProjections(principal, projections));
in_binder(f, tcx, &ty::Binder(""), Some(tap))
})?;
// Builtin bounds.
- for bound in &bounds.builtin_bounds {
+ for bound in &self.builtin_bounds {
write!(f, " + {:?}", bound)?;
}
// use thread-local data of some kind? There are also
// advantages to just showing the region, since it makes
// people aware that it's there.
- let bound = bounds.region_bound.to_string();
+ let bound = self.region_bound.to_string();
if !bound.is_empty() {
write!(f, " + {}", bound)?;
}
impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "TypeParameterDef({}, {:?}, {:?}/{})",
+ write!(f, "TypeParameterDef({}, {:?}, {})",
self.name,
self.def_id,
- self.space, self.index)
+ self.index)
}
}
impl fmt::Debug for ty::RegionParameterDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "RegionParameterDef({}, {:?}, {:?}/{}, {:?})",
+ write!(f, "RegionParameterDef({}, {:?}, {}, {:?})",
self.name,
self.def_id,
- self.space, self.index,
+ self.index,
self.bounds)
}
}
}
}
-impl<'tcx> fmt::Debug for subst::Substs<'tcx> {
+impl<'tcx> fmt::Debug for Substs<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Substs[types={:?}, regions={:?}]",
self.types, self.regions)
// when printing out the debug representation, we don't need
// to enumerate the `for<...>` etc because the debruijn index
// tells you everything you need to know.
- match self.substs.self_ty() {
- None => write!(f, "{}", *self),
- Some(self_ty) => write!(f, "<{:?} as {}>", self_ty, *self)
- }
+ write!(f, "<{:?} as {}>", self.self_ty(), *self)
+ }
+}
+
+impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| {
+ let dummy_self = tcx.mk_infer(ty::FreshTy(0));
+
+ let trait_ref = tcx.lift(&ty::Binder(*self))
+ .expect("could not lift TraitRef for printing")
+ .with_self_ty(tcx, dummy_self).0;
+ parameterized(f, trait_ref.substs, trait_ref.def_id, Ns::Type, &[])
+ })
}
}
}
}
-impl<'tcx> fmt::Debug for ty::TraitTy<'tcx> {
+impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "TraitTy({:?},{:?})",
- self.principal,
- self.bounds)
+ let mut empty = true;
+ let mut maybe_continue = |f: &mut fmt::Formatter| {
+ if empty {
+ empty = false;
+ Ok(())
+ } else {
+ write!(f, " + ")
+ }
+ };
+
+ maybe_continue(f)?;
+ write!(f, "{:?}", self.principal)?;
+
+ let region_str = format!("{:?}", self.region_bound);
+ if !region_str.is_empty() {
+ maybe_continue(f)?;
+ write!(f, "{}", region_str)?;
+ }
+
+ for bound in &self.builtin_bounds {
+ maybe_continue(f)?;
+ write!(f, "{:?}", bound)?;
+ }
+
+ for projection_bound in &self.projection_bounds {
+ maybe_continue(f)?;
+ write!(f, "{:?}", projection_bound)?;
+ }
+
+ Ok(())
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::ReEarlyBound(ref data) => {
- write!(f, "ReEarlyBound({:?}, {}, {})",
- data.space,
+ write!(f, "ReEarlyBound({}, {})",
data.index,
data.name)
}
}
}
-impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut empty = true;
- let mut maybe_continue = |f: &mut fmt::Formatter| {
- if empty {
- empty = false;
- Ok(())
- } else {
- write!(f, " + ")
- }
- };
-
- let region_str = format!("{:?}", self.region_bound);
- if !region_str.is_empty() {
- maybe_continue(f)?;
- write!(f, "{}", region_str)?;
- }
-
- for bound in &self.builtin_bounds {
- maybe_continue(f)?;
- write!(f, "{:?}", bound)?;
- }
-
- for projection_bound in &self.projection_bounds {
- maybe_continue(f)?;
- write!(f, "{:?}", projection_bound)?;
- }
-
- Ok(())
- }
-}
-
impl fmt::Display for ty::BuiltinBounds {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut bounds = self.iter();
impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- parameterized(f, self.substs, self.def_id, Ns::Type, &[],
- |tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone()))
+ parameterized(f, self.substs, self.def_id, Ns::Type, &[])
}
}
}
write!(f, "{} {{", bare_fn.sig.0)?;
- parameterized(
- f, substs, def_id, Ns::Value, &[],
- |tcx| tcx.opt_lookup_item_type(def_id).map(|t| t.generics))?;
+ parameterized(f, substs, def_id, Ns::Value, &[])?;
write!(f, "}}")
}
TyFnPtr(ref bare_fn) => {
!tcx.tcache.borrow().contains_key(&def.did) {
write!(f, "{}<..>", tcx.item_path_str(def.did))
} else {
- parameterized(
- f, substs, def.did, Ns::Type, &[],
- |tcx| {
- tcx.opt_lookup_item_type(def.did).
- map(|t| t.generics)
- })
+ parameterized(f, substs, def.did, Ns::Type, &[])
}
})
}
// by looking up the projections associated with the def_id.
let item_predicates = tcx.lookup_predicates(def_id);
let substs = tcx.lift(&substs).unwrap_or_else(|| {
- tcx.mk_substs(subst::Substs::empty())
+ Substs::empty(tcx)
});
let bounds = item_predicates.instantiate(tcx, substs);
let mut first = true;
let mut is_sized = false;
write!(f, "impl")?;
- for predicate in bounds.predicates.into_vec() {
+ for predicate in bounds.predicates {
if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
// Don't print +Sized, but rather +?Sized if absent.
if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() {
impl fmt::Debug for ty::ParamTy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}/{:?}.{}", self, self.space, self.idx)
+ write!(f, "{}/#{}", self, self.idx)
}
}
use super::{DropFlagState, MoveDataParamEnv};
use super::patch::MirPatch;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::{Subst, Substs, VecPerParamSpace};
+use rustc::ty::subst::{Subst, Substs};
use rustc::mir::repr::*;
use rustc::mir::transform::{Pass, MirPass, MirSource};
use rustc::middle::const_val::ConstVal;
let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil()));
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
.unwrap_or_else(|e| tcx.sess.fatal(&e));
- let substs = tcx.mk_substs(Substs::new(
- VecPerParamSpace::new(vec![], vec![], vec![ty]),
- VecPerParamSpace::new(vec![], vec![], vec![])
- ));
+ let substs = Substs::new(tcx, vec![ty], vec![]);
let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs);
self.patch.new_block(BasicBlockData {
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def_id::DefId;
use rustc::hir::pat_util::def_to_path;
-use rustc::ty::{self, Ty, TyCtxt, subst};
+use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::util::IntTypeExt;
+use rustc::ty::subst::Substs;
use rustc::traits::Reveal;
use rustc::util::common::ErrorReported;
use rustc::util::nodemap::NodeMap;
/// This generally happens in late/trans const evaluation.
pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- substs: Option<&'tcx subst::Substs<'tcx>>)
+ substs: Option<&'tcx Substs<'tcx>>)
-> Option<(&'tcx Expr, Option<ty::Ty<'tcx>>)> {
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
match tcx.map.find(node_id) {
// If we have a trait item and the substitutions for it,
// `resolve_trait_associated_const` will select an impl
// or the default.
- let trait_id = tcx.trait_of_item(def_id).unwrap();
+ let trait_id = tcx.map.get_parent(node_id);
+ let trait_id = tcx.map.local_def_id(trait_id);
resolve_trait_associated_const(tcx, ti, trait_id, substs)
} else {
// Technically, without knowing anything about the
fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ti: &'tcx hir::TraitItem,
trait_id: DefId,
- rcvr_substs: &'tcx subst::Substs<'tcx>)
+ rcvr_substs: &'tcx Substs<'tcx>)
-> Option<(&'tcx Expr, Option<ty::Ty<'tcx>>)>
{
- let trait_ref = ty::Binder(
- rcvr_substs.clone().erase_regions().to_trait_ref(tcx, trait_id)
- );
+ let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs));
debug!("resolve_trait_associated_const: trait_ref={:?}",
trait_ref);
- tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
+ tcx.populate_implementations_for_trait_if_necessary(trait_id);
tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
let mut selcx = traits::SelectionContext::new(&infcx);
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
-syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
+syntax_pos = { path = "../libsyntax_pos" }
+proc_macro = { path = "../libproc_macro" }
use rustc::middle::region::CodeExtentData;
use rustc::middle::resolve_lifetime;
use rustc::middle::stability;
-use rustc::ty::subst;
-use rustc::ty::subst::Subst;
+use rustc::ty::subst::{Subst, Substs};
use rustc::traits::Reveal;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::infer::{self, InferOk, InferResult, TypeOrigin};
self.infcx.tcx.mk_tup(vec![ty1, ty2])
}
- pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> {
+ pub fn t_param(&self, index: u32) -> Ty<'tcx> {
let name = format!("T{}", index);
- self.infcx.tcx.mk_param(space, index, token::intern(&name[..]))
+ self.infcx.tcx.mk_param(index, token::intern(&name[..]))
}
pub fn re_early_bound(&self,
- space: subst::ParamSpace,
index: u32,
name: &'static str)
-> ty::Region {
let name = token::intern(name);
ty::ReEarlyBound(ty::EarlyBoundRegion {
- space: space,
index: index,
name: name,
})
// t_source = fn(A)
let t_source = {
- let t_param = env.t_param(subst::TypeSpace, 0);
+ let t_param = env.t_param(0);
env.t_fn(&[t_param], env.t_nil())
};
- let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]);
- let t_substituted = t_source.subst(env.infcx.tcx, &substs);
+ let substs = Substs::new(env.infcx.tcx, vec![t_rptr_bound1], vec![]);
+ let t_substituted = t_source.subst(env.infcx.tcx, substs);
// t_expected = fn(&'a isize)
let t_expected = {
// t_source = (A, fn(A))
let t_source = {
- let t_param = env.t_param(subst::TypeSpace, 0);
+ let t_param = env.t_param(0);
env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil()))
};
- let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]);
- let t_substituted = t_source.subst(env.infcx.tcx, &substs);
+ let substs = Substs::new(env.infcx.tcx, vec![t_rptr_bound1], vec![]);
+ let t_substituted = t_source.subst(env.infcx.tcx, substs);
// t_expected = (&'a isize, fn(&'a isize))
//
assert!(t_rptr_bound2.has_escaping_regions());
// t_fn = fn(A)
- let t_param = env.t_param(subst::TypeSpace, 0);
+ let t_param = env.t_param(0);
assert!(!t_param.has_escaping_regions());
let t_fn = env.t_fn(&[t_param], env.t_nil());
assert!(!t_fn.has_escaping_regions());
// type t_source<'a> = fn(&'a isize)
let t_source = {
- let re_early = env.re_early_bound(subst::TypeSpace, 0, "'a");
+ let re_early = env.re_early_bound(0, "'a");
env.t_fn(&[env.t_rptr(re_early)], env.t_nil())
};
- let substs = subst::Substs::new_type(vec![], vec![re_bound1]);
- let t_substituted = t_source.subst(env.infcx.tcx, &substs);
+ let substs = Substs::new(env.infcx.tcx, vec![], vec![re_bound1]);
+ let t_substituted = t_source.subst(env.infcx.tcx, substs);
// t_expected = fn(&'a isize)
//
return;
}
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
- (def, cx.tcx.mk_struct(def,
- cx.tcx.mk_substs(Substs::empty())))
+ (def, cx.tcx.mk_struct(def, Substs::empty(cx.tcx)))
}
hir::ItemEnum(_, ref ast_generics) => {
if ast_generics.is_parameterized() {
return;
}
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
- (def, cx.tcx.mk_enum(def,
- cx.tcx.mk_substs(Substs::empty())))
+ (def, cx.tcx.mk_enum(def, Substs::empty(cx.tcx)))
}
_ => return,
};
// A trait method, from any number of possible sources.
// Attempt to select a concrete impl before checking.
ty::TraitContainer(trait_def_id) => {
- let trait_ref = callee_substs.to_trait_ref(tcx, trait_def_id);
+ let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs);
let trait_ref = ty::Binder(trait_ref);
let span = tcx.map.span(expr_id);
let obligation =
// If `T` is `Self`, then this call is inside
// a default method definition.
Ok(Some(traits::VtableParam(_))) => {
- let self_ty = callee_substs.self_ty();
- let on_self = self_ty.map_or(false, |t| t.is_self());
+ let on_self = trait_ref.self_ty().is_self();
// We can only be recurring in a default
// method if we're being called literally
// on the `Self` type.
use rustc::hir::def::{self, Def};
use rustc::hir::def_id::DefId;
use middle::region;
-use rustc::ty::subst;
+use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use syntax::ast;
Def::AssociatedTy(trait_did, did) =>
Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
Def::PrimTy(p) => Def::PrimTy(p),
- Def::TyParam(s, index, def_id, n) => Def::TyParam(s, index, def_id.tr(dcx), n),
+ Def::TyParam(did) => Def::TyParam(did.tr(dcx)),
Def::Upvar(_, nid1, index, nid2) => {
let nid1 = dcx.tr_id(nid1);
let nid2 = dcx.tr_id(nid2);
Ok(this.read_ty(dcx))
}).unwrap(),
substs: this.read_struct_field("substs", 3, |this| {
- Ok(dcx.tcx.mk_substs(this.read_substs(dcx)))
+ Ok(this.read_substs(dcx))
}).unwrap()
}))
}).unwrap()
trait rbml_writer_helpers<'tcx> {
fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region);
fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
- fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]);
- fn emit_predicate<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
- predicate: &ty::Predicate<'tcx>);
- fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
- ty: &ty::TraitRef<'tcx>);
fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
- substs: &subst::Substs<'tcx>);
- fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
- bounds: &ty::ExistentialBounds<'tcx>);
- fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
+ substs: &Substs<'tcx>);
fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture);
fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
adj: &adjustment::AutoAdjustment<'tcx>);
ty)));
}
- fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) {
- self.emit_from_vec(tys, |this, ty| Ok(this.emit_ty(ecx, *ty)));
- }
-
- fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
- trait_ref: &ty::TraitRef<'tcx>) {
- self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor,
- &ecx.ty_str_ctxt(),
- *trait_ref)));
- }
-
- fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
- predicate: &ty::Predicate<'tcx>) {
- self.emit_opaque(|this| {
- Ok(tyencode::enc_predicate(&mut this.cursor,
- &ecx.ty_str_ctxt(),
- predicate))
- });
- }
-
- fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
- bounds: &ty::ExistentialBounds<'tcx>) {
- self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor,
- &ecx.ty_str_ctxt(),
- bounds)));
- }
-
- fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) {
- self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor,
- &ecx.ty_str_ctxt(),
- bounds)));
- }
-
fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture) {
use rustc_serialize::Encoder;
}
fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
- substs: &subst::Substs<'tcx>) {
+ substs: &Substs<'tcx>) {
self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor,
&ecx.ty_str_ctxt(),
substs)));
-> ty::PolyTraitRef<'tcx>;
fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::Predicate<'tcx>;
- fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
- -> ty::ExistentialBounds<'tcx>;
fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
- -> subst::Substs<'tcx>;
+ -> &'tcx Substs<'tcx>;
fn read_upvar_capture(&mut self, dcx: &DecodeContext)
-> ty::UpvarCapture;
fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>>;
fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
cdata: &cstore::CrateMetadata)
- -> subst::Substs<'tcx>;
+ -> &'tcx Substs<'tcx>;
}
impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
cdata: &cstore::CrateMetadata)
- -> subst::Substs<'tcx>
+ -> &'tcx Substs<'tcx>
{
self.read_opaque(|_, doc| {
Ok(
self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate())
}
- fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
- -> ty::ExistentialBounds<'tcx>
- {
- self.read_ty_encoded(dcx, |decoder| decoder.parse_existential_bounds())
- }
-
fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
- -> subst::Substs<'tcx> {
+ -> &'tcx Substs<'tcx> {
self.read_opaque(|_, doc| {
Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc,
&mut |d| convert_def_id(dcx, d))
}
c::tag_table_item_subst => {
let item_substs = ty::ItemSubsts {
- substs: dcx.tcx.mk_substs(val_dsr.read_substs(dcx))
+ substs: val_dsr.read_substs(dcx)
};
dcx.tcx.tables.borrow_mut().item_substs.insert(
id, item_substs);
// GAP 0x8d
pub const tag_items_data_region: usize = 0x8e;
-pub const tag_region_param_def: usize = 0x8f;
-pub const tag_region_param_def_ident: usize = 0x90;
-pub const tag_region_param_def_def_id: usize = 0x91;
-pub const tag_region_param_def_space: usize = 0x92;
-pub const tag_region_param_def_index: usize = 0x93;
+pub const tag_item_generics: usize = 0x8f;
+// GAP 0x90, 0x91, 0x92, 0x93, 0x94
-pub const tag_type_param_def: usize = 0x94;
+pub const tag_item_predicates: usize = 0x95;
+// GAP 0x96
-pub const tag_item_generics: usize = 0x95;
-pub const tag_method_ty_generics: usize = 0x96;
-
-pub const tag_type_predicate: usize = 0x97;
-pub const tag_self_predicate: usize = 0x98;
-pub const tag_fn_predicate: usize = 0x99;
+pub const tag_predicate: usize = 0x97;
+// GAP 0x98, 0x99
pub const tag_unsafety: usize = 0x9a;
}
fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
- -> ty::TypeScheme<'tcx>
+ -> Ty<'tcx>
{
self.dep_graph.read(DepNode::MetaData(def));
let cdata = self.get_crate_data(def.krate);
decoder::get_super_predicates(&cdata, def.index, tcx)
}
+ fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
+ -> &'tcx ty::Generics<'tcx>
+ {
+ self.dep_graph.read(DepNode::MetaData(def));
+ let cdata = self.get_crate_data(def.krate);
+ decoder::get_generics(&cdata, def.index, tcx)
+ }
+
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
{
self.dep_graph.read(DepNode::MetaData(def_id));
decoder::get_parent_impl(&*cdata, impl_def.index)
}
- fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option<DefId>
- {
+ fn trait_of_item(&self, def_id: DefId) -> Option<DefId> {
self.dep_graph.read(DepNode::MetaData(def_id));
let cdata = self.get_crate_data(def_id.krate);
- decoder::get_trait_of_item(&cdata, def_id.index, tcx)
+ decoder::get_trait_of_item(&cdata, def_id.index)
}
fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
use rustc::hir::def::Def;
use rustc::hir::def_id::{DefId, DefIndex};
use middle::lang_items;
-use rustc::ty::subst;
use rustc::ty::{ImplContainer, TraitContainer};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind};
})
}
-pub fn item_type<'a, 'tcx>(_item_id: DefId, item: rbml::Doc,
- tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
- doc_type(item, tcx, cdata)
-}
-
fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
-> ty::TraitRef<'tcx> {
TyDecoder::with_doc(tcx, cdata.cnum, doc,
tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx>
{
let item_doc = cdata.lookup_item(item_id);
- let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
+ let generics = doc_generics(item_doc, tcx, cdata);
let unsafety = parse_unsafety(item_doc);
let associated_type_names = parse_associated_type_names(item_doc);
let paren_sugar = parse_paren_sugar(item_doc);
// from the ctor.
debug!("evaluating the ctor-type of {:?}",
variant.name);
- let ctor_ty = get_type(cdata, variant.did.index, tcx).ty;
+ let ctor_ty = get_type(cdata, variant.did.index, tcx);
debug!("evaluating the ctor-type of {:?}.. {:?}",
variant.name,
ctor_ty);
} else {
for field in &variant.fields {
debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
- let ty = get_type(cdata, field.did.index, tcx).ty;
+ let ty = get_type(cdata, field.did.index, tcx);
field.fulfill_ty(ty);
debug!("evaluating the type of {:?}::{:?}: {:?}",
variant.name, field.name, ty);
-> ty::GenericPredicates<'tcx>
{
let item_doc = cdata.lookup_item(item_id);
- doc_predicates(item_doc, tcx, cdata, tag_item_generics)
+ doc_predicates(item_doc, tcx, cdata, tag_item_predicates)
}
pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd,
doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates)
}
+pub fn get_generics<'a, 'tcx>(cdata: Cmd,
+ item_id: DefIndex,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> &'tcx ty::Generics<'tcx>
+{
+ let item_doc = cdata.lookup_item(item_id);
+ doc_generics(item_doc, tcx, cdata)
+}
+
pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::TypeScheme<'tcx>
+ -> Ty<'tcx>
{
let item_doc = cdata.lookup_item(id);
- let t = item_type(DefId { krate: cdata.cnum, index: id }, item_doc, tcx,
- cdata);
- let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
- ty::TypeScheme {
- generics: generics,
- ty: t
- }
+ doc_type(item_doc, tcx, cdata)
}
pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> {
}))
}
Some('r') | Some('p') => {
- let generics = doc_generics(item_doc, tcx, cdata, tag_method_ty_generics);
- let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics);
+ let generics = doc_generics(item_doc, tcx, cdata);
+ let predicates = doc_predicates(item_doc, tcx, cdata, tag_item_predicates);
let ity = tcx.lookup_item_type(def_id).ty;
let fty = match ity.sty {
ty::TyFnDef(_, _, fty) => fty,
}
}
-pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd,
- id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> Option<DefId> {
+pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option<DefId> {
let item_doc = cdata.lookup_item(id);
let parent_item_id = match item_parent_item(cdata, item_doc) {
None => return None,
let parent_item_doc = cdata.lookup_item(parent_item_id.index);
match item_family(parent_item_doc) {
Trait => Some(item_def_id(parent_item_doc, cdata)),
- Impl | DefaultImpl => {
- reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref)
- .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id)
- }
_ => None
}
}
};
let applicable = match item_family(item_doc) {
ImmStatic | MutStatic => true,
- Fn => {
- let ty::TypeScheme { generics, .. } = get_type(cdata, id, tcx);
- let no_generics = generics.types.is_empty();
- no_generics
- },
+ Fn => get_generics(cdata, id, tcx).types.is_empty(),
_ => false,
};
fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- cdata: Cmd,
- tag: usize)
- -> ty::Generics<'tcx>
+ cdata: Cmd)
+ -> &'tcx ty::Generics<'tcx>
{
- let doc = reader::get_doc(base_doc, tag);
-
- let mut types = subst::VecPerParamSpace::empty();
- for p in reader::tagged_docs(doc, tag_type_param_def) {
- let bd =
- TyDecoder::with_doc(tcx, cdata.cnum, p,
- &mut |did| translate_def_id(cdata, did))
- .parse_type_param_def();
- types.push(bd.space, bd);
- }
-
- let mut regions = subst::VecPerParamSpace::empty();
- for p in reader::tagged_docs(doc, tag_region_param_def) {
- let bd =
- TyDecoder::with_doc(tcx, cdata.cnum, p,
- &mut |did| translate_def_id(cdata, did))
- .parse_region_param_def();
- regions.push(bd.space, bd);
- }
-
- ty::Generics { types: types, regions: regions }
+ let doc = reader::get_doc(base_doc, tag_item_generics);
+ TyDecoder::with_doc(tcx, cdata.cnum, doc,
+ &mut |did| translate_def_id(cdata, did))
+ .parse_generics()
}
fn doc_predicate<'a, 'tcx>(cdata: Cmd,
{
let doc = reader::get_doc(base_doc, tag);
- let mut predicates = subst::VecPerParamSpace::empty();
- for predicate_doc in reader::tagged_docs(doc, tag_type_predicate) {
- predicates.push(subst::TypeSpace,
- doc_predicate(cdata, predicate_doc, tcx));
- }
- for predicate_doc in reader::tagged_docs(doc, tag_self_predicate) {
- predicates.push(subst::SelfSpace,
- doc_predicate(cdata, predicate_doc, tcx));
- }
- for predicate_doc in reader::tagged_docs(doc, tag_fn_predicate) {
- predicates.push(subst::FnSpace,
- doc_predicate(cdata, predicate_doc, tcx));
+ ty::GenericPredicates {
+ parent: item_parent_item(cdata, doc),
+ predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| {
+ doc_predicate(cdata, predicate_doc, tcx)
+ }).collect()
}
-
- ty::GenericPredicates { predicates: predicates }
}
pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool {
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use middle::dependency_format::Linkage;
use rustc::dep_graph::{DepGraph, DepNode, DepTask};
-use rustc::ty::subst;
use rustc::traits::specialization_graph;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::util::IntTypeExt;
index: &mut CrateIndex<'a, 'tcx>,
scheme: &ty::TypeScheme<'tcx>,
predicates: &ty::GenericPredicates<'tcx>) {
- encode_generics(rbml_w, ecx, index,
- &scheme.generics, &predicates, tag_item_generics);
+ encode_generics(rbml_w, ecx, index, &scheme.generics, &predicates);
encode_type(ecx, rbml_w, scheme.ty);
}
ecx: &EncodeContext<'a, 'tcx>,
index: &mut CrateIndex<'a, 'tcx>,
generics: &ty::Generics<'tcx>,
- predicates: &ty::GenericPredicates<'tcx>,
- tag: usize)
+ predicates: &ty::GenericPredicates<'tcx>)
{
- rbml_w.start_tag(tag);
-
- for param in &generics.types {
- rbml_w.start_tag(tag_type_param_def);
- tyencode::enc_type_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param);
- rbml_w.mark_stable_position();
- rbml_w.end_tag();
- }
-
- // Region parameters
- for param in &generics.regions {
- rbml_w.start_tag(tag_region_param_def);
- tyencode::enc_region_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param);
- rbml_w.mark_stable_position();
- rbml_w.end_tag();
- }
-
- encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
-
+ rbml_w.start_tag(tag_item_generics);
+ tyencode::enc_generics(rbml_w.writer, &ecx.ty_str_ctxt(), generics);
+ rbml_w.mark_stable_position();
rbml_w.end_tag();
-}
-fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder,
- _ecx: &EncodeContext<'a,'tcx>,
- index: &mut CrateIndex<'a, 'tcx>,
- predicates: &ty::GenericPredicates<'tcx>)
-{
- for (space, _, predicate) in predicates.predicates.iter_enumerated() {
- let tag = match space {
- subst::TypeSpace => tag_type_predicate,
- subst::SelfSpace => tag_self_predicate,
- subst::FnSpace => tag_fn_predicate
- };
-
- rbml_w.wr_tagged_u32(tag,
- index.add_xref(XRef::Predicate(predicate.clone())));
- }
+ encode_predicates(rbml_w, index, predicates, tag_item_predicates);
}
fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
- ecx: &EncodeContext<'a,'tcx>,
index: &mut CrateIndex<'a, 'tcx>,
predicates: &ty::GenericPredicates<'tcx>,
tag: usize)
{
rbml_w.start_tag(tag);
- encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
+ if let Some(def_id) = predicates.parent {
+ rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id));
+ }
+ for predicate in &predicates.predicates {
+ rbml_w.wr_tagged_u32(tag_predicate,
+ index.add_xref(XRef::Predicate(predicate.clone())));
+ }
rbml_w.end_tag();
}
encode_def_id_and_key(ecx, rbml_w, method_ty.def_id);
encode_name(rbml_w, method_ty.name);
encode_generics(rbml_w, ecx, index,
- &method_ty.generics, &method_ty.predicates,
- tag_method_ty_generics);
+ &method_ty.generics, &method_ty.predicates);
encode_visibility(rbml_w, method_ty.vis);
encode_explicit_self(rbml_w, &method_ty.explicit_self);
match method_ty.explicit_self {
if let Some(impl_item) = impl_item_opt {
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
encode_attributes(rbml_w, &impl_item.attrs);
- let scheme = ecx.tcx.lookup_item_type(m.def_id);
- let any_types = !scheme.generics.types.is_empty();
- let needs_inline = any_types || is_default_impl ||
+ let generics = ecx.tcx.lookup_generics(m.def_id);
+ let types = generics.parent_types as usize + generics.types.len();
+ let needs_inline = types > 0 || is_default_impl ||
attr::requests_inline(&impl_item.attrs);
if needs_inline || sig.constness == hir::Constness::Const {
encode_inlined_item(ecx,
encode_attributes(rbml_w, &ii.attrs);
encode_defaultness(rbml_w, ii.defaultness);
} else {
- encode_predicates(rbml_w, ecx, index,
+ encode_predicates(rbml_w, index,
&ecx.tcx.lookup_predicates(associated_type.def_id),
tag_item_generics);
}
encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id));
encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
encode_generics(rbml_w, ecx, index,
- &trait_def.generics, &trait_predicates,
- tag_item_generics);
- encode_predicates(rbml_w, ecx, index,
+ &trait_def.generics, &trait_predicates);
+ encode_predicates(rbml_w, index,
&tcx.lookup_super_predicates(def_id),
tag_item_super_predicates);
encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
ty
}
- fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx> {
+ fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx> {
let def_id_convert = &mut |did| {
decoder::translate_def_id(self.crate_metadata, did)
};
use rustc::hir::def_id::{DefId, DefIndex};
use middle::region;
-use rustc::ty::subst;
-use rustc::ty::subst::VecPerParamSpace;
+use rustc::ty::subst::Substs;
use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rbml;
}
}
- fn parse_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
- F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T,
- {
- let mut r = VecPerParamSpace::empty();
- for &space in &subst::ParamSpace::all() {
- assert_eq!(self.next(), '[');
- while self.peek() != ']' {
- r.push(space, f(self));
- }
- assert_eq!(self.next(), ']');
+ pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> {
+ let mut regions = vec![];
+ let mut types = vec![];
+ assert_eq!(self.next(), '[');
+ while self.peek() != '|' {
+ regions.push(self.parse_region());
+ }
+ assert_eq!(self.next(), '|');
+ while self.peek() != ']' {
+ types.push(self.parse_ty());
}
- r
+ assert_eq!(self.next(), ']');
+
+ Substs::new(self.tcx, types, regions)
}
- pub fn parse_substs(&mut self) -> subst::Substs<'tcx> {
- let regions = self.parse_vec_per_param_space(|this| this.parse_region());
- let types = self.parse_vec_per_param_space(|this| this.parse_ty());
- subst::Substs { types: types, regions: regions }
+ pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> {
+ let parent = self.parse_opt(|this| this.parse_def());
+ let parent_regions = self.parse_u32();
+ assert_eq!(self.next(), '|');
+ let parent_types = self.parse_u32();
+
+ let mut regions = vec![];
+ let mut types = vec![];
+ assert_eq!(self.next(), '[');
+ while self.peek() != '|' {
+ regions.push(self.parse_region_param_def());
+ }
+ assert_eq!(self.next(), '|');
+ while self.peek() != ']' {
+ types.push(self.parse_type_param_def());
+ }
+ assert_eq!(self.next(), ']');
+
+ self.tcx.alloc_generics(ty::Generics {
+ parent: parent,
+ parent_regions: parent_regions,
+ parent_types: parent_types,
+ regions: regions,
+ types: types,
+ has_self: self.next() == 'S'
+ })
}
fn parse_bound_region(&mut self) -> ty::BoundRegion {
}
'B' => {
assert_eq!(self.next(), '[');
- let space = self.parse_param_space();
- assert_eq!(self.next(), '|');
let index = self.parse_u32();
assert_eq!(self.next(), '|');
let name = token::intern(&self.parse_str(']'));
ty::ReEarlyBound(ty::EarlyBoundRegion {
- space: space,
index: index,
name: name
})
}
pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
- let def = self.parse_def();
- let substs = self.tcx.mk_substs(self.parse_substs());
- ty::TraitRef {def_id: def, substs: substs}
+ ty::TraitRef {
+ def_id: self.parse_def(),
+ substs: self.parse_substs()
+ }
+ }
+
+ pub fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> {
+ ty::ExistentialTraitRef {
+ def_id: self.parse_def(),
+ substs: self.parse_substs()
+ }
}
pub fn parse_ty(&mut self) -> Ty<'tcx> {
let substs = self.parse_substs();
assert_eq!(self.next(), ']');
let def = self.tcx.lookup_adt_def(did);
- return tcx.mk_enum(def, self.tcx.mk_substs(substs));
+ return tcx.mk_enum(def, substs);
}
'x' => {
assert_eq!(self.next(), '[');
- let trait_ref = ty::Binder(self.parse_trait_ref());
- let bounds = self.parse_existential_bounds();
+ let trait_ref = ty::Binder(self.parse_existential_trait_ref());
+ let builtin_bounds = self.parse_builtin_bounds();
+ let region_bound = self.parse_region();
+ let mut projection_bounds = Vec::new();
+
+ loop {
+ match self.next() {
+ 'P' => {
+ let bound = self.parse_existential_projection();
+ projection_bounds.push(ty::Binder(bound));
+ }
+ '.' => { break; }
+ c => {
+ bug!("parse_bounds: bad bounds ('{}')", c)
+ }
+ }
+ }
assert_eq!(self.next(), ']');
- return tcx.mk_trait(trait_ref, bounds);
+ return tcx.mk_trait(ty::TraitObject {
+ principal: trait_ref,
+ region_bound: region_bound,
+ builtin_bounds: builtin_bounds,
+ projection_bounds: projection_bounds
+ });
}
'p' => {
assert_eq!(self.next(), '[');
let index = self.parse_u32();
assert_eq!(self.next(), '|');
- let space = self.parse_param_space();
- assert_eq!(self.next(), '|');
let name = token::intern(&self.parse_str(']'));
- return tcx.mk_param(space, index, name);
+ return tcx.mk_param(index, name);
}
'~' => return tcx.mk_box(self.parse_ty()),
'*' => return tcx.mk_ptr(self.parse_mt()),
}
'F' => {
let def_id = self.parse_def();
- let substs = self.tcx.mk_substs(self.parse_substs());
+ let substs = self.parse_substs();
return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty());
}
'G' => {
let substs = self.parse_substs();
assert_eq!(self.next(), ']');
let def = self.tcx.lookup_adt_def(did);
- return self.tcx.mk_struct(def, self.tcx.mk_substs(substs));
+ return self.tcx.mk_struct(def, substs);
}
'k' => {
assert_eq!(self.next(), '[');
}
assert_eq!(self.next(), '.');
assert_eq!(self.next(), ']');
- return self.tcx.mk_closure(did, self.tcx.mk_substs(substs), tys);
+ return self.tcx.mk_closure(did, substs, tys);
}
'P' => {
assert_eq!(self.next(), '[');
let def_id = self.parse_def();
let substs = self.parse_substs();
assert_eq!(self.next(), ']');
- return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs));
+ return self.tcx.mk_anon(def_id, substs);
}
'e' => {
return tcx.types.err;
m
}
- fn parse_param_space(&mut self) -> subst::ParamSpace {
- subst::ParamSpace::from_uint(self.parse_uint())
- }
-
fn parse_abi_set(&mut self) -> abi::Abi {
assert_eq!(self.next(), '[');
let bytes = self.scan(|c| c == ']');
}
}
- pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
+ fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> {
+ ty::ExistentialProjection {
+ trait_ref: self.parse_existential_trait_ref(),
+ item_name: token::intern(&self.parse_str('|')),
+ ty: self.parse_ty(),
+ }
+ }
+
+ fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
let name = self.parse_name(':');
let def_id = self.parse_def();
- let space = self.parse_param_space();
- assert_eq!(self.next(), '|');
let index = self.parse_u32();
assert_eq!(self.next(), '|');
let default_def_id = self.parse_def();
ty::TypeParameterDef {
name: name,
def_id: def_id,
- space: space,
index: index,
default_def_id: default_def_id,
default: default,
}
}
- pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
+ fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
let name = self.parse_name(':');
let def_id = self.parse_def();
- let space = self.parse_param_space();
- assert_eq!(self.next(), '|');
let index = self.parse_u32();
assert_eq!(self.next(), '|');
let mut bounds = vec![];
ty::RegionParameterDef {
name: name,
def_id: def_id,
- space: space,
index: index,
bounds: bounds,
}
}
}
- pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
- let builtin_bounds = self.parse_builtin_bounds();
- let region_bound = self.parse_region();
- let mut projection_bounds = Vec::new();
-
- loop {
- match self.next() {
- 'P' => {
- projection_bounds.push(ty::Binder(self.parse_projection_predicate()));
- }
- '.' => { break; }
- c => {
- bug!("parse_bounds: bad bounds ('{}')", c)
- }
- }
- }
-
- ty::ExistentialBounds::new(
- region_bound, builtin_bounds, projection_bounds)
- }
-
fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
let mut builtin_bounds = ty::BuiltinBounds::empty();
loop {
use rustc::hir::def_id::DefId;
use middle::region;
-use rustc::ty::subst;
-use rustc::ty::subst::VecPerParamSpace;
-use rustc::ty::ParamTy;
+use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::FnvHashMap;
enc_substs(w, cx, substs);
write!(w, "]");
}
- ty::TyTrait(box ty::TraitTy { ref principal,
- ref bounds }) => {
+ ty::TyTrait(ref obj) => {
write!(w, "x[");
- enc_trait_ref(w, cx, principal.0);
- enc_existential_bounds(w, cx, bounds);
+ enc_existential_trait_ref(w, cx, obj.principal.0);
+ enc_builtin_bounds(w, cx, &obj.builtin_bounds);
+
+ enc_region(w, cx, obj.region_bound);
+
+ // Encode projection_bounds in a stable order
+ let mut projection_bounds: Vec<_> = obj.projection_bounds
+ .iter()
+ .map(|b| (b.item_name().as_str(), b))
+ .collect();
+ projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
+
+ for tp in projection_bounds.iter().map(|&(_, tp)| tp) {
+ write!(w, "P");
+ enc_existential_projection(w, cx, &tp.0);
+ }
+
+ write!(w, ".");
write!(w, "]");
}
ty::TyTuple(ts) => {
ty::TyInfer(_) => {
bug!("cannot encode inference variable types");
}
- ty::TyParam(ParamTy {space, idx, name}) => {
- write!(w, "p[{}|{}|{}]", idx, space.to_uint(), name);
+ ty::TyParam(p) => {
+ write!(w, "p[{}|{}]", p.idx, p.name);
}
ty::TyStruct(def, substs) => {
write!(w, "a[{}|", (cx.ds)(cx.tcx, def.did));
}
}
-fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor<Vec<u8>>,
- cx: &ctxt<'a, 'tcx>,
- v: &VecPerParamSpace<T>,
- mut op: F) where
- F: FnMut(&mut Cursor<Vec<u8>>, &ctxt<'a, 'tcx>, &T),
-{
- for &space in &subst::ParamSpace::all() {
- write!(w, "[");
- for t in v.get_slice(space) {
- op(w, cx, t);
- }
- write!(w, "]");
+pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
+ substs: &Substs<'tcx>) {
+ write!(w, "[");
+ for &r in &substs.regions {
+ enc_region(w, cx, r);
+ }
+ write!(w, "|");
+ for &ty in &substs.types {
+ enc_ty(w, cx, ty);
}
+ write!(w, "]");
}
-pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
- substs: &subst::Substs<'tcx>) {
- enc_vec_per_param_space(w, cx, &substs.regions,
- |w, cx, &r| enc_region(w, cx, r));
- enc_vec_per_param_space(w, cx, &substs.types,
- |w, cx, &ty| enc_ty(w, cx, ty));
+pub fn enc_generics<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
+ generics: &ty::Generics<'tcx>) {
+ enc_opt(w, generics.parent, |w, def_id| {
+ write!(w, "{}|", (cx.ds)(cx.tcx, def_id));
+ });
+ write!(w, "{}|{}[",
+ generics.parent_regions,
+ generics.parent_types);
+
+ for r in &generics.regions {
+ enc_region_param_def(w, cx, r)
+ }
+ write!(w, "|");
+ for t in &generics.types {
+ enc_type_param_def(w, cx, t);
+ }
+ write!(w, "]");
+
+ if generics.has_self {
+ write!(w, "S");
+ } else {
+ write!(w, "N");
+ }
}
pub fn enc_region(w: &mut Cursor<Vec<u8>>, cx: &ctxt, r: ty::Region) {
write!(w, "]");
}
ty::ReEarlyBound(ref data) => {
- write!(w, "B[{}|{}|{}]",
- data.space.to_uint(),
+ write!(w, "B[{}|{}]",
data.index,
data.name);
}
enc_substs(w, cx, s.substs);
}
+fn enc_existential_trait_ref<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
+ s: ty::ExistentialTraitRef<'tcx>) {
+ write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id));
+ enc_substs(w, cx, s.substs);
+}
+
fn enc_unsafety(w: &mut Cursor<Vec<u8>>, p: hir::Unsafety) {
match p {
hir::Unsafety::Normal => write!(w, "n"),
enc_ty(w, cx, fsig.0.output);
}
-pub fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinBounds) {
+fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinBounds) {
for bound in bs {
match bound {
ty::BoundSend => write!(w, "S"),
write!(w, ".");
}
-pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor<Vec<u8>>,
- cx: &ctxt<'a,'tcx>,
- bs: &ty::ExistentialBounds<'tcx>) {
- enc_builtin_bounds(w, cx, &bs.builtin_bounds);
-
- enc_region(w, cx, bs.region_bound);
-
- // Encode projection_bounds in a stable order
- let mut projection_bounds: Vec<_> = bs.projection_bounds
- .iter()
- .map(|b| (b.item_name().as_str(), b))
- .collect();
- projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
-
- for tp in projection_bounds.iter().map(|&(_, tp)| tp) {
- write!(w, "P");
- enc_projection_predicate(w, cx, &tp.0);
- }
-
- write!(w, ".");
-}
-
-pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
- v: &ty::TypeParameterDef<'tcx>) {
- write!(w, "{}:{}|{}|{}|{}|",
- v.name, (cx.ds)(cx.tcx, v.def_id),
- v.space.to_uint(), v.index, (cx.ds)(cx.tcx, v.default_def_id));
+fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
+ v: &ty::TypeParameterDef<'tcx>) {
+ write!(w, "{}:{}|{}|{}|",
+ v.name, (cx.ds)(cx.tcx, v.def_id),
+ v.index, (cx.ds)(cx.tcx, v.default_def_id));
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
enc_object_lifetime_default(w, cx, v.object_lifetime_default);
}
-pub fn enc_region_param_def(w: &mut Cursor<Vec<u8>>, cx: &ctxt,
- v: &ty::RegionParameterDef) {
- write!(w, "{}:{}|{}|{}|",
- v.name, (cx.ds)(cx.tcx, v.def_id),
- v.space.to_uint(), v.index);
+fn enc_region_param_def(w: &mut Cursor<Vec<u8>>, cx: &ctxt,
+ v: &ty::RegionParameterDef) {
+ write!(w, "{}:{}|{}|",
+ v.name, (cx.ds)(cx.tcx, v.def_id), v.index);
for &r in &v.bounds {
write!(w, "R");
enc_region(w, cx, r);
}
ty::Predicate::Projection(ty::Binder(ref data)) => {
write!(w, "p");
- enc_projection_predicate(w, cx, data);
+ enc_trait_ref(w, cx, data.projection_ty.trait_ref);
+ write!(w, "{}|", data.projection_ty.item_name);
+ enc_ty(w, cx, data.ty);
}
ty::Predicate::WellFormed(data) => {
write!(w, "w");
}
}
-fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
- cx: &ctxt<'a, 'tcx>,
- data: &ty::ProjectionPredicate<'tcx>) {
- enc_trait_ref(w, cx, data.projection_ty.trait_ref);
- write!(w, "{}|", data.projection_ty.item_name);
+fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
+ cx: &ctxt<'a, 'tcx>,
+ data: &ty::ExistentialProjection<'tcx>) {
+ enc_existential_trait_ref(w, cx, data.trait_ref);
+ write!(w, "{}|", data.item_name);
enc_ty(w, cx, data.ty);
}
use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary, ScopeId};
use rustc::middle::region::{CodeExtent, CodeExtentData};
use rustc::middle::lang_items;
-use rustc::ty::subst::{Substs, Subst, VecPerParamSpace};
+use rustc::ty::subst::{Substs, Subst};
use rustc::ty::{Ty, TyCtxt};
use rustc::mir::repr::*;
use syntax_pos::Span;
-> TerminatorKind<'tcx> {
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
.unwrap_or_else(|e| tcx.sess.fatal(&e));
- let substs = tcx.mk_substs(Substs::new(
- VecPerParamSpace::new(vec![], vec![], vec![data.item_ty]),
- VecPerParamSpace::new(vec![], vec![], vec![])
- ));
+ let substs = Substs::new(tcx, vec![data.item_ty], vec![]);
TerminatorKind::Call {
func: Operand::Constant(Constant {
span: data.span,
params: Vec<Ty<'tcx>>)
-> (Ty<'tcx>, Literal<'tcx>) {
let method_name = token::intern(method_name);
- let substs = Substs::new_trait(params, vec![], self_ty);
+ let substs = Substs::new_trait(self.tcx, params, vec![], self_ty);
for trait_item in self.tcx.trait_items(trait_def_id).iter() {
match *trait_item {
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
if method.name == method_name {
let method_ty = self.tcx.lookup_item_type(method.def_id);
- let method_ty = method_ty.ty.subst(self.tcx, &substs);
+ let method_ty = method_ty.ty.subst(self.tcx, substs);
return (method_ty, Literal::Item {
def_id: method.def_id,
- substs: self.tcx.mk_substs(substs),
+ substs: substs,
});
}
}
use rustc::hir::def::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty;
-use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
let type_parameters = match foreign_item.node {
ForeignItemKind::Fn(_, ref generics) => {
- HasTypeParameters(generics, FnSpace, ItemRibKind)
+ HasTypeParameters(generics, ItemRibKind)
}
ForeignItemKind::Static(..) => NoTypeParameters,
};
HasTypeParameters(// Type parameters.
&'b Generics,
- // Identifies the things that these parameters
- // were declared on (type, fn, etc)
- ParamSpace,
-
// The kind of the rib used for type parameters.
RibKind<'a>),
}
match item.node {
ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) |
- ItemKind::Struct(_, ref generics) => {
- self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
- |this| visit::walk_item(this, item));
- }
+ ItemKind::Struct(_, ref generics) |
ItemKind::Fn(_, _, _, _, ref generics, _) => {
- self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind),
+ self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
|this| visit::walk_item(this, item));
}
ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
// Create a new rib for the trait-wide type parameters.
- self.with_type_parameter_rib(HasTypeParameters(generics,
- TypeSpace,
- ItemRibKind),
- |this| {
+ self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
let local_def_id = this.definitions.local_def_id(item.id);
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
this.visit_generics(generics);
TraitItemKind::Method(ref sig, _) => {
let type_parameters =
HasTypeParameters(&sig.generics,
- FnSpace,
MethodRibKind(!sig.decl.has_self()));
this.with_type_parameter_rib(type_parameters, |this| {
visit::walk_trait_item(this, trait_item)
where F: FnOnce(&mut Resolver)
{
match type_parameters {
- HasTypeParameters(generics, space, rib_kind) => {
+ HasTypeParameters(generics, rib_kind) => {
let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = HashSet::new();
- for (index, type_parameter) in generics.ty_params.iter().enumerate() {
+ for type_parameter in &generics.ty_params {
let name = type_parameter.ident.name;
debug!("with_type_parameter_rib: {}", type_parameter.id);
// plain insert (no renaming)
let def_id = self.definitions.local_def_id(type_parameter.id);
- let def = Def::TyParam(space, index as u32, def_id, name);
+ let def = Def::TyParam(def_id);
function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def);
self.record_def(type_parameter.id, PathResolution::new(def));
}
item_id: NodeId,
impl_items: &[ImplItem]) {
// If applicable, create a rib for the type parameters.
- self.with_type_parameter_rib(HasTypeParameters(generics,
- TypeSpace,
- ItemRibKind),
- |this| {
+ self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
// Resolve the type parameters.
this.visit_generics(generics);
// specific type parameters.
let type_parameters =
HasTypeParameters(&sig.generics,
- FnSpace,
MethodRibKind(!sig.decl.has_self()));
this.with_type_parameter_rib(type_parameters, |this| {
visit::walk_impl_item(this, impl_item);
let mut result = String::from("<");
result.push_str(&rustc::hir::print::ty_to_string(&ty));
- if let Some(def_id) = self.tcx
- .trait_of_item(self.tcx.map.local_def_id(id)) {
+ if let Some(def_id) = self.tcx.trait_id_of_impl(impl_id) {
result.push_str(" as ");
result.push_str(&self.tcx.item_path_str(def_id));
}
Def::Enum(def_id) |
Def::TyAlias(def_id) |
Def::Trait(def_id) |
- Def::TyParam(_, _, def_id, _) => {
+ Def::TyParam(def_id) => {
Some(Data::TypeRefData(TypeRefData {
span: sub_span.unwrap(),
ref_id: Some(def_id),
&format!("comparison of `{}`", rhs_t),
StrEqFnLangItem);
let args = [lhs_data, lhs_len, rhs_data, rhs_len];
- Callee::def(bcx.ccx(), did, bcx.tcx().mk_substs(Substs::empty()))
+ Callee::def(bcx.ccx(), did, Substs::empty(bcx.tcx()))
.call(bcx, debug_loc, ArgVals(&args), None)
}
use std::rc::Rc;
use llvm::{ValueRef, True, IntEQ, IntNE};
-use rustc::ty::subst;
+use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use syntax::ast;
use syntax::attr;
fn get_cases<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
adt: ty::AdtDef<'tcx>,
- substs: &subst::Substs<'tcx>)
+ substs: &Substs<'tcx>)
-> Vec<Case<'tcx>> {
adt.variants.iter().map(|vi| {
let field_tys = vi.fields.iter().map(|field| {
// and should not matter anyhow.
let instance_ty = scx.tcx().erase_regions(&instance_ty.ty);
- let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice());
+ let hash = get_symbol_hash(scx, &def_path, instance_ty, &substs.types);
let mut buffer = SymbolPathBuffer {
names: Vec::with_capacity(def_path.data.len())
use rustc::hir::def_id::DefId;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use rustc::hir::pat_util::simple_name;
-use rustc::ty::subst::{self, Substs};
+use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::adjustment::CustomCoerceUnsized;
// Allocate space:
let def_id = require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem);
- let r = Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty()))
+ let r = Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx()))
.call(bcx, debug_loc, ArgVals(&[size, align]), None);
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
// change to the vtable.
old_info.expect("unsized_info: missing old info for trait upcast")
}
- (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => {
- // Note that we preserve binding levels here:
- let substs = principal.0.substs.with_self_ty(source).erase_regions();
- let substs = ccx.tcx().mk_substs(substs);
- let trait_ref = ty::Binder(ty::TraitRef {
- def_id: principal.def_id(),
- substs: substs,
- });
+ (_, &ty::TyTrait(ref data)) => {
+ let trait_ref = data.principal.with_self_ty(ccx.tcx(), source);
+ let trait_ref = ccx.tcx().erase_regions(&trait_ref);
consts::ptrcast(meth::get_vtable(ccx, trait_ref),
Type::vtable_ptr(ccx))
}
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>)
-> CustomCoerceUnsized {
- let trait_substs = Substs::new(subst::VecPerParamSpace::new(vec![target_ty],
- vec![source_ty],
- Vec::new()),
- subst::VecPerParamSpace::empty());
-
let trait_ref = ty::Binder(ty::TraitRef {
def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(),
- substs: scx.tcx().mk_substs(trait_substs)
+ substs: Substs::new_trait(scx.tcx(), vec![target_ty], vec![], source_ty)
});
match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
common::validate_substs(instance.substs);
(instance.substs, Some(instance.def), Some(inlined_id))
}
- None => (ccx.tcx().mk_substs(Substs::empty()), None, None)
+ None => (Substs::empty(ccx.tcx()), None, None)
};
let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id));
Ok(id) => id,
Err(s) => ccx.sess().fatal(&s)
};
- let empty_substs = ccx.tcx().mk_substs(Substs::empty());
+ let empty_substs = Substs::empty(ccx.tcx());
let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx).val;
let args = {
let opaque_rust_main =
hir_map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), .. }) => {
let def_id = tcx.map.local_def_id(id);
- let scheme = tcx.lookup_item_type(def_id);
- scheme.generics.types.is_empty()
+ let generics = tcx.lookup_generics(def_id);
+ generics.parent_types == 0 && generics.types.is_empty()
}
_ => false
use llvm::{self, ValueRef, get_params};
use middle::cstore::LOCAL_CRATE;
use rustc::hir::def_id::DefId;
-use rustc::ty::subst;
+use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::hir::map as hir_map;
use abi::{Abi, FnType};
/// Function or method definition.
pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>,
def_id: DefId,
- substs: &'tcx subst::Substs<'tcx>)
+ substs: &'tcx Substs<'tcx>)
-> Callee<'tcx> {
let tcx = ccx.tcx();
- if substs.self_ty().is_some() {
- // Only trait methods can have a Self parameter.
- return Callee::trait_method(ccx, def_id, substs);
+ if let Some(trait_id) = tcx.trait_of_item(def_id) {
+ return Callee::trait_method(ccx, trait_id, def_id, substs);
}
let maybe_node_id = inline::get_local_instance(ccx, def_id)
/// Trait method, which has to be resolved to an impl method.
pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
+ trait_id: DefId,
def_id: DefId,
- substs: &'tcx subst::Substs<'tcx>)
+ substs: &'tcx Substs<'tcx>)
-> Callee<'tcx> {
let tcx = ccx.tcx();
- let method_item = tcx.impl_or_trait_item(def_id);
- let trait_id = method_item.container().id();
- let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id));
- let trait_ref = tcx.normalize_associated_type(&trait_ref);
+ let trait_ref = ty::TraitRef::from_method(tcx, trait_id, substs);
+ let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref));
match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
traits::VtableImpl(vtable_impl) => {
let impl_did = vtable_impl.impl_def_id;
let mname = tcx.item_name(def_id);
// create a concatenated set of substitutions which includes
// those from the impl and those from the method:
- let impl_substs = vtable_impl.substs.with_method_from(&substs);
- let substs = tcx.mk_substs(impl_substs);
- let mth = meth::get_impl_method(tcx, impl_did, substs, mname);
+ let mth = meth::get_impl_method(tcx, substs, impl_did, vtable_impl.substs, mname);
// Translate the function, bypassing Callee::def.
// That is because default methods have the same ID as the
/// Given a DefId and some Substs, produces the monomorphic item type.
fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- substs: &'tcx subst::Substs<'tcx>)
+ substs: &'tcx Substs<'tcx>)
-> Ty<'tcx> {
let ty = tcx.lookup_item_type(def_id).ty;
monomorphize::apply_param_substs(tcx, substs, &ty)
/// - `substs`: values for each of the fn/method's parameters
fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
def_id: DefId,
- substs: &'tcx subst::Substs<'tcx>)
+ substs: &'tcx Substs<'tcx>)
-> Datum<'tcx, Rvalue> {
let tcx = ccx.tcx();
use rustc::hir::def_id::DefId;
use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem};
use rustc::traits;
-use rustc::ty::subst::{self, Substs, Subst};
+use rustc::ty::subst::{Substs, Subst};
use rustc::ty::{self, TypeFoldable, TyCtxt};
use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::mir::repr as mir;
create_fn_trans_item(scx.tcx(),
exchange_free_fn_def_id,
fn_substs,
- scx.tcx().mk_substs(Substs::empty()));
+ Substs::empty(scx.tcx()));
output.push(exchange_free_fn_trans_item);
}
.drop_trait()
.unwrap();
- let self_type_substs = scx.tcx().mk_substs(
- Substs::empty().with_self_ty(ty));
+ let self_type_substs = Substs::new_trait(scx.tcx(), vec![], vec![], ty);
let trait_ref = ty::TraitRef {
def_id: drop_trait_def_id,
let trans_item = create_fn_trans_item(scx.tcx(),
destructor_did,
substs,
- scx.tcx().mk_substs(Substs::empty()));
+ Substs::empty(scx.tcx()));
output.push(trans_item);
}
fn_substs,
param_substs);
- let is_trait_method = scx.tcx().trait_of_item(fn_def_id).is_some();
-
- if is_trait_method {
+ if let Some(trait_def_id) = scx.tcx().trait_of_item(fn_def_id) {
match scx.tcx().impl_or_trait_item(fn_def_id) {
ty::MethodTraitItem(ref method) => {
- match method.container {
- ty::TraitContainer(trait_def_id) => {
- debug!(" => trait method, attempting to find impl");
- do_static_trait_method_dispatch(scx,
- method,
- trait_def_id,
- fn_substs,
- param_substs)
- }
- ty::ImplContainer(_) => {
- // This is already a concrete implementation
- debug!(" => impl method");
- Some((fn_def_id, fn_substs))
- }
- }
+ debug!(" => trait method, attempting to find impl");
+ do_static_trait_method_dispatch(scx,
+ method,
+ trait_def_id,
+ fn_substs,
+ param_substs)
}
_ => bug!()
}
callee_substs,
param_substs);
+
let rcvr_substs = monomorphize::apply_param_substs(tcx,
param_substs,
&callee_substs);
-
- let trait_ref = ty::Binder(rcvr_substs.to_trait_ref(tcx, trait_id));
- let trait_ref = tcx.normalize_associated_type(&trait_ref);
- let vtbl = fulfill_obligation(scx, DUMMY_SP, trait_ref);
+ let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
+ let vtbl = fulfill_obligation(scx, DUMMY_SP, ty::Binder(trait_ref));
// Now that we know which impl is being used, we can dispatch to
// the actual function:
substs: impl_substs,
nested: _ }) =>
{
- let callee_substs = impl_substs.with_method_from(&rcvr_substs);
let impl_method = meth::get_impl_method(tcx,
+ rcvr_substs,
impl_did,
- tcx.mk_substs(callee_substs),
+ impl_substs,
trait_method.name);
Some((impl_method.method.def_id, &impl_method.substs))
}
assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst());
if let ty::TyTrait(ref trait_ty) = trait_ty.sty {
- let poly_trait_ref = trait_ty.principal_trait_ref_with_self_ty(scx.tcx(),
- impl_ty);
+ let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty);
// Walk all methods of the trait, including those of its supertraits
for trait_ref in traits::supertraits(scx.tcx(), poly_trait_ref) {
Some(create_fn_trans_item(scx.tcx(),
impl_method.method.def_id,
impl_method.substs,
- scx.tcx().mk_substs(Substs::empty())))
+ Substs::empty(scx.tcx())))
} else {
None
}
def_id_to_string(tcx, impl_def_id));
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
- let default_impls = tcx.provided_trait_methods(trait_ref.def_id);
let callee_substs = tcx.erase_regions(&trait_ref.substs);
let overridden_methods: FnvHashSet<_> = items.iter()
.map(|item| item.name)
.collect();
- for default_impl in default_impls {
- if overridden_methods.contains(&default_impl.name) {
+ for method in tcx.provided_trait_methods(trait_ref.def_id) {
+ if overridden_methods.contains(&method.name) {
continue;
}
- if default_impl.generics.has_type_params(subst::FnSpace) {
+ if !method.generics.types.is_empty() {
continue;
}
// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
+ let impl_substs = Substs::for_item(tcx, impl_def_id,
+ |_, _| ty::ReErased,
+ |_, _| tcx.types.err);
let mth = meth::get_impl_method(tcx,
- impl_def_id,
callee_substs,
- default_impl.name);
+ impl_def_id,
+ impl_substs,
+ method.name);
assert!(mth.is_provided);
let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs);
- if !normalize_and_test_predicates(tcx, predicates.into_vec()) {
+ if !normalize_and_test_predicates(tcx, predicates) {
continue;
}
- if can_have_local_instance(tcx, default_impl.def_id) {
+ if can_have_local_instance(tcx, method.def_id) {
let empty_substs = tcx.erase_regions(&mth.substs);
let item = create_fn_trans_item(tcx,
- default_impl.def_id,
+ method.def_id,
callee_substs,
empty_substs);
output.push(item);
let tcx = ccx.tcx();
match tcx.lang_items.eh_personality() {
Some(def_id) if !base::wants_msvc_seh(ccx.sess()) => {
- Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty())).reify(ccx).val
+ Callee::def(ccx, def_id, Substs::empty(tcx)).reify(ccx).val
}
_ => {
if let Some(llpersonality) = ccx.eh_personality().get() {
let tcx = ccx.tcx();
assert!(ccx.sess().target.target.options.custom_unwind_resume);
if let Some(def_id) = tcx.lang_items.eh_unwind_resume() {
- return Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty()));
+ return Callee::def(ccx, def_id, Substs::empty(tcx));
}
let ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
let arg_ids = args.iter().map(|arg| arg.pat.id);
let fn_args = arg_ids.zip(arg_vals.iter().cloned()).collect();
- let substs = ccx.tcx().mk_substs(substs.clone().erase_regions());
+ let substs = ccx.tcx().erase_regions(&substs);
let substs = monomorphize::apply_param_substs(ccx.tcx(),
param_substs,
&substs);
param_substs: &'tcx Substs<'tcx>)
-> &'tcx hir::Expr {
let substs = ccx.tcx().node_id_item_substs(ref_expr.id).substs;
- let substs = ccx.tcx().mk_substs(substs.clone().erase_regions());
+ let substs = ccx.tcx().erase_regions(&substs);
let substs = monomorphize::apply_param_substs(ccx.tcx(),
param_substs,
&substs);
param_substs: &'tcx Substs<'tcx>)
-> Result<ValueRef, ConstEvalFailure> {
let expr = get_const_expr(ccx, def_id, ref_expr, param_substs);
- let empty_substs = ccx.tcx().mk_substs(Substs::empty());
+ let empty_substs = Substs::empty(ccx.tcx());
match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) {
Err(Runtime(err)) => {
report_const_eval_err(ccx.tcx(), &err, expr.span, "expression").emit();
let v = if use_mir {
::mir::trans_static_initializer(ccx, def_id)
} else {
- let empty_substs = ccx.tcx().mk_substs(Substs::empty());
+ let empty_substs = Substs::empty(ccx.tcx());
const_expr(ccx, expr, empty_substs, None, TrueConst::Yes)
.map(|(v, _)| v)
}.map_err(|e| e.into_inner())?;
use partitioning::CodegenUnit;
use trans_item::TransItem;
use type_::{Type, TypeNames};
-use rustc::ty::subst::{Substs, VecPerParamSpace};
+use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use session::config::NoDebugInfo;
use session::Session;
/// Given the def-id of some item that has no type parameters, make
/// a suitable "empty substs" for it.
pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
- let scheme = self.tcx().lookup_item_type(item_def_id);
- self.empty_substs_for_scheme(&scheme)
- }
-
- pub fn empty_substs_for_scheme(&self, scheme: &ty::TypeScheme<'tcx>)
- -> &'tcx Substs<'tcx> {
- assert!(scheme.generics.types.is_empty());
- self.tcx().mk_substs(
- Substs::new(VecPerParamSpace::empty(),
- scheme.generics.regions.map(|_| ty::ReErased)))
+ Substs::for_item(self.tcx(), item_def_id, |_, _| ty::ReErased, |_, _| {
+ bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
+ })
}
pub fn symbol_hasher(&self) -> &RefCell<Sha256> {
pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
self.shared().empty_substs_for_def_id(item_def_id)
}
-
- pub fn empty_substs_for_scheme(&self, scheme: &ty::TypeScheme<'tcx>)
- -> &'tcx Substs<'tcx> {
- self.shared().empty_substs_for_scheme(scheme)
- }
}
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
let expr_file_line = consts::addr_of(ccx, expr_file_line_const, align, "panic_loc");
let args = vec!(expr_file_line);
let did = langcall(bcx.tcx(), Some(call_info.span), "", PanicFnLangItem);
- Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty()))
+ Callee::def(ccx, did, Substs::empty(ccx.tcx()))
.call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx
}
let file_line = consts::addr_of(ccx, file_line_const, align, "panic_bounds_check_loc");
let args = vec!(file_line, index, len);
let did = langcall(bcx.tcx(), Some(call_info.span), "", PanicBoundsCheckFnLangItem);
- Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty()))
+ Callee::def(ccx, did, Substs::empty(ccx.tcx()))
.call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx
}
use rustc::hir::def_id::DefId;
use rustc::hir::pat_util;
-use rustc::ty::subst;
+use rustc::ty::subst::Substs;
use rustc::hir::map as hir_map;
use rustc::hir::{self, PatKind};
use {type_of, adt, machine, monomorphize};
fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
cx: &CrateContext<'a, 'tcx>,
def_id: DefId,
- substs: &subst::Substs<'tcx>,
+ substs: &Substs<'tcx>,
output: &mut String) {
// First, find out the 'real' def_id of the type. Items inlined from
// other crates have to be mapped back to their source.
// Add the def-index as the second part
output.push_str(&format!("{:x}", def_id.index.as_usize()));
- let tps = substs.types.get_slice(subst::TypeSpace);
+ let tps = &substs.types;
if !tps.is_empty() {
output.push('<');
// But it does not describe the trait's methods.
let def_id = match trait_type.sty {
- ty::TyTrait(ref data) => data.principal_def_id(),
+ ty::TyTrait(ref data) => data.principal.def_id(),
_ => {
bug!("debuginfo: Unexpected trait-object type in \
trait_pointer_metadata(): {:?}",
// Creates MemberDescriptions for the fields of a struct
struct StructMemberDescriptionFactory<'tcx> {
variant: ty::VariantDef<'tcx>,
- substs: &'tcx subst::Substs<'tcx>,
+ substs: &'tcx Substs<'tcx>,
is_simd: bool,
span: Span,
}
// Get_template_parameters() will append a `<...>` clause to the function
// name if necessary.
- let generics = cx.tcx().lookup_item_type(fn_def_id).generics;
+ let generics = cx.tcx().lookup_generics(fn_def_id);
let template_parameters = get_template_parameters(cx,
&generics,
instance.substs,
name_to_append_suffix_to: &mut String)
-> DIArray
{
- let actual_types = param_substs.types.as_slice();
+ let actual_types = ¶m_substs.types;
if actual_types.is_empty() {
return create_DIArray(DIB(cx), &[]);
// Again, only create type information if full debuginfo is enabled
let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
- generics.types.as_slice().iter().enumerate().map(|(i, param)| {
- let actual_type = cx.tcx().normalize_associated_type(&actual_types[i]);
+ let names = get_type_parameter_names(cx, generics);
+ actual_types.iter().zip(names).map(|(ty, name)| {
+ let actual_type = cx.tcx().normalize_associated_type(ty);
let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
- let name = CString::new(param.name.as_str().as_bytes()).unwrap();
+ let name = CString::new(name.as_str().as_bytes()).unwrap();
unsafe {
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
return create_DIArray(DIB(cx), &template_params[..]);
}
+ fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+ generics: &ty::Generics<'tcx>)
+ -> Vec<ast::Name> {
+ let mut names = generics.parent.map_or(vec![], |def_id| {
+ get_type_parameter_names(cx, cx.tcx().lookup_generics(def_id))
+ });
+ names.extend(generics.types.iter().map(|param| param.name));
+ names
+ }
+
fn get_containing_scope_and_span<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
instance: Instance<'tcx>)
-> (DIScope, Span) {
use common::CrateContext;
use rustc::hir::def_id::DefId;
-use rustc::ty::subst;
+use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty};
use rustc::hir;
// would be possible but with inlining and LTO we have to use the least
// common denominator - otherwise we would run into conflicts.
fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
- substs: &subst::Substs<'tcx>,
+ substs: &Substs<'tcx>,
output: &mut String) {
if substs.types.is_empty() {
return;
hir::ExprPath(..) => {
match bcx.tcx().expect_def(expr.id) {
Def::Const(did) | Def::AssociatedConst(did) => {
- let empty_substs = bcx.tcx().mk_substs(Substs::empty());
+ let empty_substs = Substs::empty(bcx.tcx());
let const_expr = consts::get_const_expr(bcx.ccx(), did, expr,
empty_substs);
// Temporarily get cleanup scopes out of the way,
let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem);
let args = [PointerCast(bcx, v, Type::i8p(bcx.ccx())), size, align];
- Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty()))
+ Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx()))
.call(bcx, debug_loc, ArgVals(&args), None).bcx
}
let trait_ref = ty::Binder(ty::TraitRef {
def_id: tcx.lang_items.drop_trait().unwrap(),
- substs: tcx.mk_substs(Substs::empty().with_self_ty(t))
+ substs: Substs::new_trait(tcx, vec![], vec![], t)
});
let vtbl = match fulfill_obligation(bcx.ccx().shared(), DUMMY_SP, trait_ref) {
traits::VtableImpl(data) => data,
use libc;
use llvm;
use llvm::{ValueRef, TypeKind};
-use rustc::ty::subst;
-use rustc::ty::subst::FnSpace;
+use rustc::ty::subst::Substs;
use abi::{Abi, FnType};
use adt;
use base::*;
callee::ArgExprs(arg_exprs) => {
assert_eq!(arg_exprs.len(), 1);
- let (in_type, out_type) = (*substs.types.get(FnSpace, 0),
- *substs.types.get(FnSpace, 1));
+ let (in_type, out_type) = (substs.types[0],
+ substs.types[1]);
let llintype = type_of::type_of(ccx, in_type);
let llouttype = type_of::type_of(ccx, out_type);
Call(bcx, llfn, &[], call_debug_location)
}
(_, "size_of") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
let lltp_ty = type_of::type_of(ccx, tp_ty);
C_uint(ccx, machine::llsize_of_alloc(ccx, lltp_ty))
}
(_, "size_of_val") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
if !type_is_sized(tcx, tp_ty) {
let (llsize, _) =
glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]);
}
}
(_, "min_align_of") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
C_uint(ccx, type_of::align_of(ccx, tp_ty))
}
(_, "min_align_of_val") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
if !type_is_sized(tcx, tp_ty) {
let (_, llalign) =
glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]);
}
}
(_, "pref_align_of") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
let lltp_ty = type_of::type_of(ccx, tp_ty);
C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty))
}
(_, "drop_in_place") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
let ptr = if type_is_sized(tcx, tp_ty) {
llargs[0]
} else {
C_nil(ccx)
}
(_, "type_name") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
let ty_name = token::intern_and_get_ident(&tp_ty.to_string());
C_str_slice(ccx, ty_name)
}
(_, "type_id") => {
- C_u64(ccx, ccx.tcx().type_id_hash(*substs.types.get(FnSpace, 0)))
+ C_u64(ccx, ccx.tcx().type_id_hash(substs.types[0]))
}
(_, "init_dropped") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
if !type_is_zero_size(ccx, tp_ty) {
drop_done_fill_mem(bcx, llresult, tp_ty);
}
C_nil(ccx)
}
(_, "init") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
if !type_is_zero_size(ccx, tp_ty) {
// Just zero out the stack slot. (See comment on base::memzero for explanation)
init_zero_mem(bcx, llresult, tp_ty);
C_nil(ccx)
}
(_, "needs_drop") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
C_bool(ccx, bcx.fcx.type_needs_drop(tp_ty))
}
copy_intrinsic(bcx,
false,
false,
- *substs.types.get(FnSpace, 0),
+ substs.types[0],
llargs[1],
llargs[0],
llargs[2],
copy_intrinsic(bcx,
true,
false,
- *substs.types.get(FnSpace, 0),
+ substs.types[0],
llargs[1],
llargs[0],
llargs[2],
(_, "write_bytes") => {
memset_intrinsic(bcx,
false,
- *substs.types.get(FnSpace, 0),
+ substs.types[0],
llargs[0],
llargs[1],
llargs[2],
copy_intrinsic(bcx,
false,
true,
- *substs.types.get(FnSpace, 0),
+ substs.types[0],
llargs[0],
llargs[1],
llargs[2],
copy_intrinsic(bcx,
true,
true,
- *substs.types.get(FnSpace, 0),
+ substs.types[0],
llargs[0],
llargs[1],
llargs[2],
(_, "volatile_set_memory") => {
memset_intrinsic(bcx,
true,
- *substs.types.get(FnSpace, 0),
+ substs.types[0],
llargs[0],
llargs[1],
llargs[2],
call_debug_location)
}
(_, "volatile_load") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
let mut ptr = llargs[0];
if let Some(ty) = fn_ty.ret.cast {
ptr = PointerCast(bcx, ptr, ty.ptr_to());
to_immediate(bcx, load, tp_ty)
},
(_, "volatile_store") => {
- let tp_ty = *substs.types.get(FnSpace, 0);
+ let tp_ty = substs.types[0];
if type_is_fat_ptr(bcx.tcx(), tp_ty) {
VolatileStore(bcx, llargs[1], expr::get_dataptr(bcx, llargs[0]));
VolatileStore(bcx, llargs[2], expr::get_meta(bcx, llargs[0]));
},
(_, "discriminant_value") => {
- let val_ty = substs.types.get(FnSpace, 0);
+ let val_ty = substs.types[0];
match val_ty.sty {
ty::TyEnum(..) => {
- let repr = adt::represent_type(ccx, *val_ty);
+ let repr = adt::represent_type(ccx, val_ty);
adt::trans_get_discr(bcx, &repr, llargs[0],
Some(llret_ty), true)
}
match split[1] {
"cxchg" | "cxchgweak" => {
- let sty = &substs.types.get(FnSpace, 0).sty;
+ let sty = &substs.types[0].sty;
if int_type_width_signed(sty, ccx).is_some() {
let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False };
let val = AtomicCmpXchg(bcx, llargs[0], llargs[1], llargs[2],
}
"load" => {
- let sty = &substs.types.get(FnSpace, 0).sty;
+ let sty = &substs.types[0].sty;
if int_type_width_signed(sty, ccx).is_some() {
AtomicLoad(bcx, llargs[0], order)
} else {
}
"store" => {
- let sty = &substs.types.get(FnSpace, 0).sty;
+ let sty = &substs.types[0].sty;
if int_type_width_signed(sty, ccx).is_some() {
AtomicStore(bcx, llargs[1], llargs[0], order);
} else {
_ => ccx.sess().fatal("unknown atomic operation")
};
- let sty = &substs.types.get(FnSpace, 0).sty;
+ let sty = &substs.types[0].sty;
if int_type_width_signed(sty, ccx).is_some() {
AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order)
} else {
fn generic_simd_intrinsic<'blk, 'tcx, 'a>
(bcx: Block<'blk, 'tcx>,
name: &str,
- substs: &'tcx subst::Substs<'tcx>,
+ substs: &'tcx Substs<'tcx>,
callee_ty: Ty<'tcx>,
args: Option<&[P<hir::Expr>]>,
llargs: &[ValueRef],
use back::symbol_names;
use llvm::{ValueRef, get_params};
use rustc::hir::def_id::DefId;
-use rustc::ty::subst::{FnSpace, Subst, Substs};
-use rustc::ty::subst;
+use rustc::ty::subst::{Subst, Substs};
use rustc::traits::{self, Reveal};
use abi::FnType;
use base::*;
pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_id: DefId,
- substs: &'tcx subst::Substs<'tcx>)
+ substs: &'tcx Substs<'tcx>)
-> Vec<Option<ImplMethod<'tcx>>>
{
debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs);
- let trt_id = match tcx.impl_trait_ref(impl_id) {
+ let trait_id = match tcx.impl_trait_ref(impl_id) {
Some(t_id) => t_id.def_id,
None => bug!("make_impl_vtable: don't know how to \
make a vtable for a type impl!")
};
- tcx.populate_implementations_for_trait_if_necessary(trt_id);
+ tcx.populate_implementations_for_trait_if_necessary(trait_id);
- let trait_item_def_ids = tcx.trait_item_def_ids(trt_id);
+ let trait_item_def_ids = tcx.trait_item_def_ids(trait_id);
trait_item_def_ids
.iter()
let name = trait_method_type.name;
// Some methods cannot be called on an object; skip those.
- if !tcx.is_vtable_safe_method(trt_id, &trait_method_type) {
+ if !tcx.is_vtable_safe_method(trait_id, &trait_method_type) {
debug!("get_vtable_methods: not vtable safe");
return None;
}
// the method may have some early-bound lifetimes, add
// regions for those
- let num_dummy_regions = trait_method_type.generics.regions.len(FnSpace);
- let dummy_regions = vec![ty::ReErased; num_dummy_regions];
- let method_substs = substs.clone()
- .with_method(vec![], dummy_regions);
- let method_substs = tcx.mk_substs(method_substs);
+ let method_substs = Substs::for_item(tcx, trait_method_def_id,
+ |_, _| ty::ReErased,
+ |_, _| tcx.types.err);
// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
- let mth = get_impl_method(tcx, impl_id, method_substs, name);
+ let mth = get_impl_method(tcx, method_substs, impl_id, substs, name);
debug!("get_vtable_methods: mth={:?}", mth);
// try and trans it, in that case. Issue #23435.
if mth.is_provided {
let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs);
- if !normalize_and_test_predicates(tcx, predicates.into_vec()) {
+ if !normalize_and_test_predicates(tcx, predicates) {
debug!("get_vtable_methods: predicates do not hold");
return None;
}
/// Locates the applicable definition of a method, given its name.
pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- impl_def_id: DefId,
substs: &'tcx Substs<'tcx>,
+ impl_def_id: DefId,
+ impl_substs: &'tcx Substs<'tcx>,
name: Name)
-> ImplMethod<'tcx>
{
match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() {
Some(node_item) => {
let substs = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
+ let substs = substs.rebase_onto(tcx, trait_def_id, impl_substs);
let substs = traits::translate_substs(&infcx, impl_def_id,
substs, node_item.node);
tcx.lift(&substs).unwrap_or_else(|| {
args: IndexVec<mir::Arg, Const<'tcx>>)
-> Result<Const<'tcx>, ConstEvalFailure> {
// Try to resolve associated constants.
- if instance.substs.self_ty().is_some() {
- // Only trait items can have a Self parameter.
- let trait_item = ccx.tcx().impl_or_trait_item(instance.def);
- let trait_id = trait_item.container().id();
- let substs = instance.substs;
- let trait_ref = ty::Binder(substs.to_trait_ref(ccx.tcx(), trait_id));
+ if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) {
+ let trait_ref = ty::TraitRef::new(trait_id, instance.substs);
+ let trait_ref = ty::Binder(trait_ref);
let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref);
if let traits::VtableImpl(vtable_impl) = vtable {
let name = ccx.tcx().item_name(instance.def);
use llvm;
use rustc::hir::def_id::DefId;
use rustc::infer::TransNormalize;
-use rustc::ty::subst;
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::{self, Ty, TypeFoldable, TyCtxt};
use attributes;
pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
fn_id: DefId,
- psubsts: &'tcx subst::Substs<'tcx>)
+ psubsts: &'tcx Substs<'tcx>)
-> (ValueRef, Ty<'tcx>) {
debug!("monomorphic_fn(fn_id={:?}, real_substs={:?})", fn_id, psubsts);
assert!(!psubsts.types.needs_infer() && !psubsts.types.has_param_types());
impl<'tcx> fmt::Display for Instance<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[], |_| None)
+ ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[])
}
}
// its self-type. If the self-type does not provide a characteristic
// DefId, we use the location of the impl after all.
- if let Some(self_ty) = instance.substs.self_ty() {
+ if tcx.trait_of_item(instance.def).is_some() {
+ let self_ty = instance.substs.types[0];
// This is an implementation of a trait method.
return characteristic_def_id_of_type(self_ty).or(Some(instance.def));
}
use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::subst;
+use rustc::ty::subst::Substs;
use rustc_const_eval::fatal_const_eval_err;
use std::hash::{Hash, Hasher};
use syntax::ast::{self, NodeId};
},
TransItem::Static(node_id) => {
let def_id = hir_map.local_def_id(node_id);
- let instance = Instance::new(def_id,
- tcx.mk_substs(subst::Substs::empty()));
+ let instance = Instance::new(def_id, Substs::empty(tcx));
to_string_internal(tcx, "static ", instance)
},
};
output.push(']');
},
ty::TyTrait(ref trait_data) => {
- push_item_name(tcx, trait_data.principal.skip_binder().def_id, output);
+ push_item_name(tcx, trait_data.principal.def_id(), output);
push_type_params(tcx,
&trait_data.principal.skip_binder().substs.types,
- &trait_data.bounds.projection_bounds,
+ &trait_data.projection_bounds,
output);
},
ty::TyFnDef(_, _, &ty::BareFnTy{ unsafety, abi, ref sig } ) |
}
fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- types: &'tcx subst::VecPerParamSpace<Ty<'tcx>>,
- projections: &[ty::PolyProjectionPredicate<'tcx>],
+ types: &[Ty<'tcx>],
+ projections: &[ty::PolyExistentialProjection<'tcx>],
output: &mut String) {
if types.is_empty() && projections.is_empty() {
return;
for projection in projections {
let projection = projection.skip_binder();
- let name = &projection.projection_ty.item_name.as_str();
+ let name = &projection.item_name.as_str();
output.push_str(name);
output.push_str("=");
push_unique_type_name(tcx, projection.ty, output);
#![allow(non_camel_case_types)]
use rustc::hir::def_id::DefId;
-use rustc::ty::subst;
use abi::FnType;
use adt;
use common::*;
// avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
- let tps = substs.types.get_slice(subst::TypeSpace);
- let name = llvm_type_name(cx, def.did, tps);
+ let name = llvm_type_name(cx, def.did, &substs.types);
adt::incomplete_type_of(cx, &repr, &name[..])
}
ty::TyClosure(..) => {
// Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache.
let repr = adt::represent_type(cx, t);
- // Unboxed closures can have substitutions in all spaces
- // inherited from their environment, so we use entire
- // contents of the VecPerParamSpace to construct the llvm
- // name
adt::incomplete_type_of(cx, &repr, "closure")
}
// in *after* placing it into the type cache. This prevents
// infinite recursion with recursive struct types.
let repr = adt::represent_type(cx, t);
- let tps = substs.types.get_slice(subst::TypeSpace);
- let name = llvm_type_name(cx, def.did, tps);
+ let name = llvm_type_name(cx, def.did, &substs.types);
adt::incomplete_type_of(cx, &repr, &name[..])
}
}
use hir::print as pprust;
use middle::resolve_lifetime as rl;
use rustc::lint;
-use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
-use rustc::ty::subst::VecPerParamSpace;
+use rustc::ty::subst::{Subst, Substs};
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::wf::object_region_bounds;
/// A cache used for the result of `ast_ty_to_ty_cache`
fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>>;
+ /// Returns the generic type and lifetime parameters for an item.
+ fn get_generics(&self, span: Span, id: DefId)
+ -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>;
+
/// Identify the type scheme for an item with a type, like a type
/// alias, fn, or struct. This allows you to figure out the set of
/// type parameters defined on the item.
fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
/// What type should we use when a type is omitted?
- fn ty_infer(&self,
- param_and_substs: Option<ty::TypeParameterDef<'tcx>>,
- substs: Option<&mut Substs<'tcx>>,
- space: Option<ParamSpace>,
- span: Span) -> Ty<'tcx>;
+ fn ty_infer(&self, span: Span) -> Ty<'tcx>;
+
+ /// Same as ty_infer, but with a known type parameter definition.
+ fn ty_infer_for_def(&self,
+ _def: &ty::TypeParameterDef<'tcx>,
+ _substs: &Substs<'tcx>,
+ span: Span) -> Ty<'tcx> {
+ self.ty_infer(span)
+ }
/// Projecting an associated type from a (potentially)
/// higher-ranked trait reference is more complicated, because of
type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
+/// Dummy type used for the `Self` of a `TraitRef` created for converting
+/// a trait object, and which gets removed in `ExistentialTraitRef`.
+/// This type must not appear anywhere in other converted types.
+const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0));
+
pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime)
-> ty::Region {
let r = match tcx.named_region_map.defs.get(&lifetime.id) {
issue_32330))
}
- Some(&rl::DefEarlyBoundRegion(space, index, _)) => {
+ Some(&rl::DefEarlyBoundRegion(index, _)) => {
ty::ReEarlyBound(ty::EarlyBoundRegion {
- space: space,
index: index,
name: lifetime.name
})
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
- decl_generics: &ty::Generics<'tcx>,
+ def_id: DefId,
item_segment: &hir::PathSegment)
- -> Substs<'tcx>
+ -> &'tcx Substs<'tcx>
{
let tcx = self.tcx();
- // ast_path_substs() is only called to convert paths that are
- // known to refer to traits, types, or structs. In these cases,
- // all type parameters defined for the item being referenced will
- // be in the TypeSpace or SelfSpace.
- //
- // Note: in the case of traits, the self parameter is also
- // defined, but we don't currently create a `type_param_def` for
- // `Self` because it is implicit.
- assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
- assert!(decl_generics.types.all(|d| d.space != FnSpace));
-
- let (regions, types, assoc_bindings) = match item_segment.parameters {
- hir::AngleBracketedParameters(ref data) => {
- self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data)
- }
+ match item_segment.parameters {
+ hir::AngleBracketedParameters(_) => {}
hir::ParenthesizedParameters(..) => {
struct_span_err!(tcx.sess, span, E0214,
"parenthesized parameters may only be used with a trait")
.span_label(span, &format!("only traits may use parentheses"))
.emit();
- let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
- (Substs::empty(),
- ty_param_defs.iter().map(|_| tcx.types.err).collect(),
- vec![])
+ return Substs::for_item(tcx, def_id, |_, _| {
+ ty::ReStatic
+ }, |_, _| {
+ tcx.types.err
+ });
}
- };
+ }
+
+ let (substs, assoc_bindings) =
+ self.create_substs_for_ast_path(rscope,
+ span,
+ param_mode,
+ def_id,
+ &item_segment.parameters,
+ None);
assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span));
- self.create_substs_for_ast_path(span,
- param_mode,
- decl_generics,
- None,
- types,
- regions)
+ substs
}
- fn create_region_substs(&self,
+ /// Given the type/region arguments provided to some path (along with
+ /// an implicit Self, if this is a trait reference) returns the complete
+ /// set of substitutions. This may involve applying defaulted type parameters.
+ ///
+ /// Note that the type listing given here is *exactly* what the user provided.
+ fn create_substs_for_ast_path(&self,
rscope: &RegionScope,
span: Span,
- decl_generics: &ty::Generics<'tcx>,
- regions_provided: Vec<ty::Region>)
- -> Substs<'tcx>
+ param_mode: PathParamMode,
+ def_id: DefId,
+ parameters: &hir::PathParameters,
+ self_ty: Option<Ty<'tcx>>)
+ -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
{
let tcx = self.tcx();
+ debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
+ parameters={:?})",
+ def_id, self_ty, parameters);
+
+ let (lifetimes, num_types_provided) = match *parameters {
+ hir::AngleBracketedParameters(ref data) => {
+ if param_mode == PathParamMode::Optional && data.types.is_empty() {
+ (&data.lifetimes[..], None)
+ } else {
+ (&data.lifetimes[..], Some(data.types.len()))
+ }
+ }
+ hir::ParenthesizedParameters(_) => (&[][..], Some(1))
+ };
+
// If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words,
// whatever & would get replaced with).
- let expected_num_region_params = decl_generics.regions.len(TypeSpace);
- let supplied_num_region_params = regions_provided.len();
+ let decl_generics = match self.get_generics(span, def_id) {
+ Ok(generics) => generics,
+ Err(ErrorReported) => {
+ // No convenient way to recover from a cycle here. Just bail. Sorry!
+ self.tcx().sess.abort_if_errors();
+ bug!("ErrorReported returned, but no errors reports?")
+ }
+ };
+ let expected_num_region_params = decl_generics.regions.len();
+ let supplied_num_region_params = lifetimes.len();
let regions = if expected_num_region_params == supplied_num_region_params {
- regions_provided
+ lifetimes.iter().map(|l| ast_region_to_region(tcx, l)).collect()
} else {
let anon_regions =
rscope.anon_regions(span, expected_num_region_params);
Err(_) => (0..expected_num_region_params).map(|_| ty::ReStatic).collect()
}
};
- Substs::new_type(vec![], regions)
- }
- /// Given the type/region arguments provided to some path (along with
- /// an implicit Self, if this is a trait reference) returns the complete
- /// set of substitutions. This may involve applying defaulted type parameters.
- ///
- /// Note that the type listing given here is *exactly* what the user provided.
- ///
- /// The `region_substs` should be the result of `create_region_substs`
- /// -- that is, a substitution with no types but the correct number of
- /// regions.
- fn create_substs_for_ast_path(&self,
- span: Span,
- param_mode: PathParamMode,
- decl_generics: &ty::Generics<'tcx>,
- self_ty: Option<Ty<'tcx>>,
- types_provided: Vec<Ty<'tcx>>,
- region_substs: Substs<'tcx>)
- -> Substs<'tcx>
- {
- let tcx = self.tcx();
+ // If a self-type was declared, one should be provided.
+ assert_eq!(decl_generics.has_self, self_ty.is_some());
- debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
- types_provided={:?}, region_substs={:?})",
- decl_generics, self_ty, types_provided,
- region_substs);
-
- assert_eq!(region_substs.regions.len(TypeSpace), decl_generics.regions.len(TypeSpace));
- assert!(region_substs.types.is_empty());
-
- // Convert the type parameters supplied by the user.
- let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
- let formal_ty_param_count = ty_param_defs.len();
- let required_ty_param_count = ty_param_defs.iter()
- .take_while(|x| x.default.is_none())
- .count();
-
- let mut type_substs = self.get_type_substs_for_defs(span,
- types_provided,
- param_mode,
- ty_param_defs,
- region_substs.clone(),
- self_ty);
-
- let supplied_ty_param_count = type_substs.len();
- check_type_argument_count(self.tcx(), span, supplied_ty_param_count,
- required_ty_param_count, formal_ty_param_count);
-
- if supplied_ty_param_count < required_ty_param_count {
- while type_substs.len() < required_ty_param_count {
- type_substs.push(tcx.types.err);
- }
- } else if supplied_ty_param_count > formal_ty_param_count {
- type_substs.truncate(formal_ty_param_count);
+ // Check the number of type parameters supplied by the user.
+ if let Some(num_provided) = num_types_provided {
+ let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
+ check_type_argument_count(tcx, span, num_provided, ty_param_defs);
}
- assert!(type_substs.len() >= required_ty_param_count &&
- type_substs.len() <= formal_ty_param_count);
-
- let mut substs = region_substs;
- substs.types.extend(TypeSpace, type_substs.into_iter());
- match self_ty {
- None => {
- // If no self-type is provided, it's still possible that
- // one was declared, because this could be an object type.
+ let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
+ let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| {
+ if let Some(ref default) = p.default {
+ if is_object && default.has_self_ty() {
+ // There is no suitable inference default for a type parameter
+ // that references self, in an object type.
+ return true;
+ }
}
- Some(ty) => {
- // If a self-type is provided, one should have been
- // "declared" (in other words, this should be a
- // trait-ref).
- assert!(decl_generics.types.get_self().is_some());
- substs.types.push(SelfSpace, ty);
+
+ false
+ };
+
+ let mut output_assoc_binding = None;
+ let substs = Substs::for_item(tcx, def_id, |def, _| {
+ regions[def.index as usize]
+ }, |def, substs| {
+ let i = def.index as usize;
+
+ // Handle Self first, so we can adjust the index to match the AST.
+ if let (0, Some(ty)) = (i, self_ty) {
+ return ty;
}
- }
- let actual_supplied_ty_param_count = substs.types.len(TypeSpace);
- for param in &ty_param_defs[actual_supplied_ty_param_count..] {
- if let Some(default) = param.default {
+ let i = i - self_ty.is_some() as usize;
+ if num_types_provided.map_or(false, |n| i < n) {
+ // A provided type parameter.
+ match *parameters {
+ hir::AngleBracketedParameters(ref data) => {
+ self.ast_ty_arg_to_ty(rscope, Some(def), substs, &data.types[i])
+ }
+ hir::ParenthesizedParameters(ref data) => {
+ assert_eq!(i, 0);
+ let (ty, assoc) =
+ self.convert_parenthesized_parameters(rscope, substs, data);
+ output_assoc_binding = Some(assoc);
+ ty
+ }
+ }
+ } else if num_types_provided.is_none() {
+ // No type parameters were provided, we can infer all.
+ let ty_var = if !default_needs_object_self(def) {
+ self.ty_infer_for_def(def, substs, span)
+ } else {
+ self.ty_infer(span)
+ };
+ ty_var
+ } else if let Some(default) = def.default {
+ // No type parameter provided, but a default exists.
+
// If we are converting an object type, then the
// `Self` parameter is unknown. However, some of the
// other type parameters may reference `Self` in their
// defaults. This will lead to an ICE if we are not
// careful!
- if self_ty.is_none() && default.has_self_ty() {
+ if default_needs_object_self(def) {
span_err!(tcx.sess, span, E0393,
"the type parameter `{}` must be explicitly specified \
in an object type because its default value `{}` references \
the type `Self`",
- param.name,
+ def.name,
default);
- substs.types.push(TypeSpace, tcx.types.err);
+ tcx.types.err
} else {
// This is a default type parameter.
- let default = default.subst_spanned(tcx,
- &substs,
- Some(span));
- substs.types.push(TypeSpace, default);
+ default.subst_spanned(tcx, substs, Some(span))
}
} else {
- span_bug!(span, "extra parameter without default");
+ // We've already errored above about the mismatch.
+ tcx.types.err
}
- }
-
- debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
- decl_generics, self_ty, substs);
+ });
- substs
- }
-
- /// Returns types_provided if it is not empty, otherwise populating the
- /// type parameters with inference variables as appropriate.
- fn get_type_substs_for_defs(&self,
- span: Span,
- types_provided: Vec<Ty<'tcx>>,
- param_mode: PathParamMode,
- ty_param_defs: &[ty::TypeParameterDef<'tcx>],
- mut substs: Substs<'tcx>,
- self_ty: Option<Ty<'tcx>>)
- -> Vec<Ty<'tcx>>
- {
- fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option<Ty<'tcx>>)
- -> Option<ty::TypeParameterDef<'tcx>>
- {
- if let Some(ref default) = p.default {
- if self_ty.is_none() && default.has_self_ty() {
- // There is no suitable inference default for a type parameter
- // that references self with no self-type provided.
- return None;
- }
+ let assoc_bindings = match *parameters {
+ hir::AngleBracketedParameters(ref data) => {
+ data.bindings.iter().map(|b| {
+ ConvertedBinding {
+ item_name: b.name,
+ ty: self.ast_ty_to_ty(rscope, &b.ty),
+ span: b.span
+ }
+ }).collect()
}
+ hir::ParenthesizedParameters(ref data) => {
+ vec![output_assoc_binding.unwrap_or_else(|| {
+ // This is an error condition, but we should
+ // get the associated type binding anyway.
+ self.convert_parenthesized_parameters(rscope, substs, data).1
+ })]
+ }
+ };
- Some(p.clone())
- }
-
- if param_mode == PathParamMode::Optional && types_provided.is_empty() {
- ty_param_defs
- .iter()
- .map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs),
- Some(TypeSpace), span))
- .collect()
- } else {
- types_provided
- }
- }
+ debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
+ decl_generics, self_ty, substs);
- fn convert_angle_bracketed_parameters(&self,
- rscope: &RegionScope,
- span: Span,
- decl_generics: &ty::Generics<'tcx>,
- data: &hir::AngleBracketedParameterData)
- -> (Substs<'tcx>,
- Vec<Ty<'tcx>>,
- Vec<ConvertedBinding<'tcx>>)
- {
- let regions: Vec<_> =
- data.lifetimes.iter()
- .map(|l| ast_region_to_region(self.tcx(), l))
- .collect();
-
- let region_substs =
- self.create_region_substs(rscope, span, decl_generics, regions);
-
- let types: Vec<_> =
- data.types.iter()
- .enumerate()
- .map(|(i,t)| self.ast_ty_arg_to_ty(rscope, decl_generics,
- i, ®ion_substs, t))
- .collect();
-
- let assoc_bindings: Vec<_> =
- data.bindings.iter()
- .map(|b| ConvertedBinding { item_name: b.name,
- ty: self.ast_ty_to_ty(rscope, &b.ty),
- span: b.span })
- .collect();
-
- (region_substs, types, assoc_bindings)
+ (substs, assoc_bindings)
}
/// Returns the appropriate lifetime to use for any output lifetimes
fn convert_parenthesized_parameters(&self,
rscope: &RegionScope,
- span: Span,
- decl_generics: &ty::Generics<'tcx>,
+ region_substs: &Substs<'tcx>,
data: &hir::ParenthesizedParameterData)
- -> (Substs<'tcx>,
- Vec<Ty<'tcx>>,
- Vec<ConvertedBinding<'tcx>>)
+ -> (Ty<'tcx>, ConvertedBinding<'tcx>)
{
- let region_substs =
- self.create_region_substs(rscope, span, decl_generics, Vec::new());
-
let anon_scope = rscope.anon_type_scope();
let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope);
- let inputs =
- data.inputs.iter()
- .map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
- 0, ®ion_substs, a_t))
- .collect::<Vec<Ty<'tcx>>>();
-
+ let inputs: Vec<_> = data.inputs.iter().map(|a_t| {
+ self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t)
+ }).collect();
let input_params = vec![String::new(); inputs.len()];
let implied_output_region = self.find_implied_output_region(&inputs, input_params);
- let input_ty = self.tcx().mk_tup(inputs);
-
let (output, output_span) = match data.output {
Some(ref output_ty) => {
(self.convert_ty_with_lifetime_elision(implied_output_region,
span: output_span
};
- (region_substs, vec![input_ty], vec![output_binding])
+ (self.tcx().mk_tup(inputs), output_binding)
}
pub fn instantiate_poly_trait_ref(&self,
rscope: &RegionScope,
ast_trait_ref: &hir::PolyTraitRef,
- self_ty: Option<Ty<'tcx>>,
+ self_ty: Ty<'tcx>,
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
pub fn instantiate_mono_trait_ref(&self,
rscope: &RegionScope,
trait_ref: &hir::TraitRef,
- self_ty: Option<Ty<'tcx>>)
+ self_ty: Ty<'tcx>)
-> ty::TraitRef<'tcx>
{
let trait_def_id = self.trait_def_id(trait_ref);
}
}
- fn object_path_to_poly_trait_ref(&self,
- rscope: &RegionScope,
- span: Span,
- param_mode: PathParamMode,
- trait_def_id: DefId,
- trait_path_ref_id: ast::NodeId,
- trait_segment: &hir::PathSegment,
- mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
- -> ty::PolyTraitRef<'tcx>
- {
- self.ast_path_to_poly_trait_ref(rscope,
- span,
- param_mode,
- trait_def_id,
- None,
- trait_path_ref_id,
- trait_segment,
- projections)
- }
-
fn ast_path_to_poly_trait_ref(&self,
rscope: &RegionScope,
span: Span,
param_mode: PathParamMode,
trait_def_id: DefId,
- self_ty: Option<Ty<'tcx>>,
+ self_ty: Ty<'tcx>,
path_id: ast::NodeId,
trait_segment: &hir::PathSegment,
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
trait_segment);
let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs));
- {
- let converted_bindings =
- assoc_bindings
- .iter()
- .filter_map(|binding| {
- // specify type to assert that error was already reported in Err case:
- let predicate: Result<_, ErrorReported> =
- self.ast_type_binding_to_poly_projection_predicate(path_id,
- poly_trait_ref.clone(),
- self_ty,
- binding);
- predicate.ok() // ok to ignore Err() because ErrorReported (see above)
- });
- poly_projections.extend(converted_bindings);
- }
+ poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
+ // specify type to assert that error was already reported in Err case:
+ let predicate: Result<_, ErrorReported> =
+ self.ast_type_binding_to_poly_projection_predicate(path_id,
+ poly_trait_ref,
+ binding);
+ predicate.ok() // ok to ignore Err() because ErrorReported (see above)
+ }));
debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
trait_segment, poly_projections, poly_trait_ref);
span: Span,
param_mode: PathParamMode,
trait_def_id: DefId,
- self_ty: Option<Ty<'tcx>>,
+ self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment)
-> ty::TraitRef<'tcx>
{
span: Span,
param_mode: PathParamMode,
trait_def_id: DefId,
- self_ty: Option<Ty<'tcx>>,
+ self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment)
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
{
}
};
- let (regions, types, assoc_bindings) = match trait_segment.parameters {
- hir::AngleBracketedParameters(ref data) => {
+ match trait_segment.parameters {
+ hir::AngleBracketedParameters(_) => {
// For now, require that parenthetical notation be used
// only with `Fn()` etc.
if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
type parameters is subject to change. \
Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
}
-
- self.convert_angle_bracketed_parameters(rscope, span, &trait_def.generics, data)
}
- hir::ParenthesizedParameters(ref data) => {
+ hir::ParenthesizedParameters(_) => {
// For now, require that parenthetical notation be used
// only with `Fn()` etc.
if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
"\
parenthetical notation is only stable when used with `Fn`-family traits");
}
-
- self.convert_parenthesized_parameters(rscope, span, &trait_def.generics, data)
}
- };
-
- let substs = self.create_substs_for_ast_path(span,
- param_mode,
- &trait_def.generics,
- self_ty,
- types,
- regions);
+ }
- (self.tcx().mk_substs(substs), assoc_bindings)
+ self.create_substs_for_ast_path(rscope,
+ span,
+ param_mode,
+ trait_def_id,
+ &trait_segment.parameters,
+ Some(self_ty))
}
fn ast_type_binding_to_poly_projection_predicate(
&self,
path_id: ast::NodeId,
- mut trait_ref: ty::PolyTraitRef<'tcx>,
- self_ty: Option<Ty<'tcx>>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
binding: &ConvertedBinding<'tcx>)
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
{
// Simple case: X is defined in the current trait.
if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
- return Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------+
- projection_ty: ty::ProjectionTy { // |
- trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+
- item_name: binding.item_name,
- },
- ty: binding.ty,
+ return Ok(trait_ref.map_bound(|trait_ref| {
+ ty::ProjectionPredicate {
+ projection_ty: ty::ProjectionTy {
+ trait_ref: trait_ref,
+ item_name: binding.item_name,
+ },
+ ty: binding.ty,
+ }
}));
}
// Otherwise, we have to walk through the supertraits to find
- // those that do. This is complicated by the fact that, for an
- // object type, the `Self` type is not present in the
- // substitutions (after all, it's being constructed right now),
- // but the `supertraits` iterator really wants one. To handle
- // this, we currently insert a dummy type and then remove it
- // later. Yuck.
-
- let dummy_self_ty = tcx.mk_infer(ty::FreshTy(0));
- if self_ty.is_none() { // if converting for an object type
- let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+
- assert!(dummy_substs.self_ty().is_none()); // |
- dummy_substs.types.push(SelfSpace, dummy_self_ty); // |
- trait_ref = ty::Binder(ty::TraitRef::new(trait_ref.def_id(), // <------------+
- tcx.mk_substs(dummy_substs)));
- }
-
+ // those that do.
self.ensure_super_predicates(binding.span, trait_ref.def_id())?;
- let mut candidates: Vec<ty::PolyTraitRef> =
+ let candidates: Vec<ty::PolyTraitRef> =
traits::supertraits(tcx, trait_ref.clone())
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name))
.collect();
- // If converting for an object type, then remove the dummy-ty from `Self` now.
- // Yuckety yuck.
- if self_ty.is_none() {
- for candidate in &mut candidates {
- let mut dummy_substs = candidate.0.substs.clone();
- assert!(dummy_substs.self_ty() == Some(dummy_self_ty));
- dummy_substs.types.pop(SelfSpace);
- *candidate = ty::Binder(ty::TraitRef::new(candidate.def_id(),
- tcx.mk_substs(dummy_substs)));
- }
- }
-
let candidate = self.one_bound_for_assoc_type(candidates,
&trait_ref.to_string(),
&binding.item_name.as_str(),
binding.span)?;
- Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+
- projection_ty: ty::ProjectionTy { // |
- trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+
- item_name: binding.item_name,
- },
- ty: binding.ty,
+ Ok(candidate.map_bound(|trait_ref| {
+ ty::ProjectionPredicate {
+ projection_ty: ty::ProjectionTy {
+ trait_ref: trait_ref,
+ item_name: binding.item_name,
+ },
+ ty: binding.ty,
+ }
}))
}
-> Ty<'tcx>
{
let tcx = self.tcx();
- let (generics, decl_ty) = match self.get_item_type_scheme(span, did) {
- Ok(ty::TypeScheme { generics, ty: decl_ty }) => {
- (generics, decl_ty)
- }
+ let decl_ty = match self.get_item_type_scheme(span, did) {
+ Ok(type_scheme) => type_scheme.ty,
Err(ErrorReported) => {
return tcx.types.err;
}
let substs = self.ast_path_substs_for_ty(rscope,
span,
param_mode,
- &generics,
+ did,
item_segment);
// FIXME(#12938): This is a hack until we have full support for DST.
if Some(did) == self.tcx().lang_items.owned_box() {
- assert_eq!(substs.types.len(TypeSpace), 1);
- return self.tcx().mk_box(*substs.types.get(TypeSpace, 0));
+ assert_eq!(substs.types.len(), 1);
+ return self.tcx().mk_box(substs.types[0]);
}
- decl_ty.subst(self.tcx(), &substs)
+ decl_ty.subst(self.tcx(), substs)
}
- fn ast_ty_to_trait_ref(&self,
- rscope: &RegionScope,
- ty: &hir::Ty,
- bounds: &[hir::TyParamBound])
- -> Result<TraitAndProjections<'tcx>, ErrorReported>
+ fn ast_ty_to_object_trait_ref(&self,
+ rscope: &RegionScope,
+ span: Span,
+ ty: &hir::Ty,
+ bounds: &[hir::TyParamBound])
+ -> Ty<'tcx>
{
/*!
* In a type like `Foo + Send`, we want to wait to collect the
* name, and reports an error otherwise.
*/
+ let tcx = self.tcx();
match ty.node {
hir::TyPath(None, ref path) => {
- let resolution = self.tcx().expect_resolution(ty.id);
+ let resolution = tcx.expect_resolution(ty.id);
match resolution.base_def {
Def::Trait(trait_def_id) if resolution.depth == 0 => {
- let mut projection_bounds = Vec::new();
- let trait_ref =
- self.object_path_to_poly_trait_ref(rscope,
- path.span,
- PathParamMode::Explicit,
- trait_def_id,
- ty.id,
- path.segments.last().unwrap(),
- &mut projection_bounds);
- Ok((trait_ref, projection_bounds))
+ self.trait_path_to_object_type(rscope,
+ path.span,
+ PathParamMode::Explicit,
+ trait_def_id,
+ ty.id,
+ path.segments.last().unwrap(),
+ span,
+ partition_bounds(tcx, span, bounds))
}
_ => {
- struct_span_err!(self.tcx().sess, ty.span, E0172,
+ struct_span_err!(tcx.sess, ty.span, E0172,
"expected a reference to a trait")
.span_label(ty.span, &format!("expected a trait"))
.emit();
- Err(ErrorReported)
+ tcx.types.err
}
}
}
_ => {
- let mut err = struct_span_err!(self.tcx().sess, ty.span, E0178,
+ let mut err = struct_span_err!(tcx.sess, ty.span, E0178,
"expected a path on the left-hand side \
of `+`, not `{}`",
pprust::ty_to_string(ty));
}
}
err.emit();
- Err(ErrorReported)
+ tcx.types.err
}
}
}
- fn trait_ref_to_object_type(&self,
- rscope: &RegionScope,
- span: Span,
- trait_ref: ty::PolyTraitRef<'tcx>,
- projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
- bounds: &[hir::TyParamBound])
- -> Ty<'tcx>
- {
- let existential_bounds = self.conv_existential_bounds(rscope,
- span,
- trait_ref.clone(),
- projection_bounds,
- bounds);
-
- let result = self.make_object_type(span, trait_ref, existential_bounds);
- debug!("trait_ref_to_object_type: result={:?}",
- result);
-
- result
+ /// Transform a PolyTraitRef into a PolyExistentialTraitRef by
+ /// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF).
+ fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
+ -> ty::ExistentialTraitRef<'tcx> {
+ assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
+ ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
}
- fn make_object_type(&self,
- span: Span,
- principal: ty::PolyTraitRef<'tcx>,
- bounds: ty::ExistentialBounds<'tcx>)
- -> Ty<'tcx> {
+ fn trait_path_to_object_type(&self,
+ rscope: &RegionScope,
+ path_span: Span,
+ param_mode: PathParamMode,
+ trait_def_id: DefId,
+ trait_path_ref_id: ast::NodeId,
+ trait_segment: &hir::PathSegment,
+ span: Span,
+ partitioned_bounds: PartitionedBounds)
+ -> Ty<'tcx> {
let tcx = self.tcx();
- let object = ty::TraitTy {
- principal: principal,
- bounds: bounds
+
+ let mut projection_bounds = vec![];
+ let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
+ let principal = self.ast_path_to_poly_trait_ref(rscope,
+ path_span,
+ param_mode,
+ trait_def_id,
+ dummy_self,
+ trait_path_ref_id,
+ trait_segment,
+ &mut projection_bounds);
+
+ let PartitionedBounds { builtin_bounds,
+ trait_bounds,
+ region_bounds } =
+ partitioned_bounds;
+
+ if !trait_bounds.is_empty() {
+ let b = &trait_bounds[0];
+ let span = b.trait_ref.path.span;
+ struct_span_err!(self.tcx().sess, span, E0225,
+ "only the builtin traits can be used as closure or object bounds")
+ .span_label(span, &format!("non-builtin trait used as bounds"))
+ .emit();
+ }
+
+ // Erase the dummy_self (TRAIT_OBJECT_DUMMY_SELF) used above.
+ let existential_principal = principal.map_bound(|trait_ref| {
+ self.trait_ref_to_existential(trait_ref)
+ });
+ let existential_projections = projection_bounds.iter().map(|bound| {
+ bound.map_bound(|b| {
+ let p = b.projection_ty;
+ ty::ExistentialProjection {
+ trait_ref: self.trait_ref_to_existential(p.trait_ref),
+ item_name: p.item_name,
+ ty: b.ty
+ }
+ })
+ }).collect();
+
+ let region_bound =
+ self.compute_object_lifetime_bound(span,
+ ®ion_bounds,
+ existential_principal,
+ builtin_bounds);
+
+ let region_bound = match region_bound {
+ Some(r) => r,
+ None => {
+ match rscope.object_lifetime_default(span) {
+ Some(r) => r,
+ None => {
+ span_err!(self.tcx().sess, span, E0228,
+ "the lifetime bound for this object type cannot be deduced \
+ from context; please supply an explicit bound");
+ ty::ReStatic
+ }
+ }
+ }
};
- let object_trait_ref =
- object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
+
+ debug!("region_bound: {:?}", region_bound);
// ensure the super predicates and stop if we encountered an error
if self.ensure_super_predicates(span, principal.def_id()).is_err() {
}
let mut associated_types: FnvHashSet<(DefId, ast::Name)> =
- traits::supertraits(tcx, object_trait_ref)
+ traits::supertraits(tcx, principal)
.flat_map(|tr| {
let trait_def = tcx.lookup_trait_def(tr.def_id());
trait_def.associated_type_names
})
.collect();
- for projection_bound in &object.bounds.projection_bounds {
+ for projection_bound in &projection_bounds {
let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
projection_bound.0.projection_ty.item_name);
associated_types.remove(&pair);
.emit();
}
- tcx.mk_trait(object.principal, object.bounds)
+ let ty = tcx.mk_trait(ty::TraitObject {
+ principal: existential_principal,
+ region_bound: region_bound,
+ builtin_bounds: builtin_bounds,
+ projection_bounds: existential_projections
+ });
+ debug!("trait_object_type: {:?}", ty);
+ ty
}
fn report_ambiguous_associated_type(&self,
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
- (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
+ (&ty::TyParam(_), Def::TyParam(param_did)) => {
let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
+ let param_name = tcx.type_parameter_def(param_node_id).name;
match self.find_bound_for_assoc_item(param_node_id,
param_name,
assoc_name,
}
}
_ => {
- self.report_ambiguous_associated_type(span,
- &ty.to_string(),
- "Trait",
- &assoc_name.as_str());
+ // Don't print TyErr to the user.
+ if !ty.references_error() {
+ self.report_ambiguous_associated_type(span,
+ &ty.to_string(),
+ "Trait",
+ &assoc_name.as_str());
+ }
return (tcx.types.err, Def::Err);
}
};
span,
param_mode,
trait_def_id,
- Some(self_ty),
+ self_ty,
trait_segment);
debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
/// # Parameters
///
/// * `this`, `rscope`: the surrounding context
- /// * `decl_generics`: the generics of the struct/enum/trait declaration being
- /// referenced
- /// * `index`: the index of the type parameter being instantiated from the list
- /// (we assume it is in the `TypeSpace`)
+ /// * `def`: the type parameter being instantiated (if available)
/// * `region_substs`: a partial substitution consisting of
/// only the region type parameters being supplied to this type.
/// * `ast_ty`: the ast representation of the type being supplied
- pub fn ast_ty_arg_to_ty(&self,
- rscope: &RegionScope,
- decl_generics: &ty::Generics<'tcx>,
- index: usize,
- region_substs: &Substs<'tcx>,
- ast_ty: &hir::Ty)
- -> Ty<'tcx>
+ fn ast_ty_arg_to_ty(&self,
+ rscope: &RegionScope,
+ def: Option<&ty::TypeParameterDef<'tcx>>,
+ region_substs: &Substs<'tcx>,
+ ast_ty: &hir::Ty)
+ -> Ty<'tcx>
{
let tcx = self.tcx();
- if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) {
+ if let Some(def) = def {
let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs);
let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default);
self.ast_ty_to_ty(rscope1, ast_ty)
Def::Trait(trait_def_id) => {
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
- let mut projection_bounds = Vec::new();
-
- let trait_ref =
- self.object_path_to_poly_trait_ref(rscope,
- span,
- param_mode,
- trait_def_id,
- base_path_ref_id,
- base_segments.last().unwrap(),
- &mut projection_bounds);
tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
- self.trait_ref_to_object_type(rscope,
- span,
- trait_ref,
- projection_bounds,
- &[])
+
+ self.trait_path_to_object_type(rscope,
+ span,
+ param_mode,
+ trait_def_id,
+ base_path_ref_id,
+ base_segments.last().unwrap(),
+ span,
+ partition_bounds(tcx, span, &[]))
}
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
did,
base_segments.last().unwrap())
}
- Def::TyParam(space, index, _, name) => {
+ Def::TyParam(did) => {
tcx.prohibit_type_params(base_segments);
- tcx.mk_param(space, index, name)
+
+ let node_id = tcx.map.as_local_node_id(did).unwrap();
+ let param = tcx.ty_param_defs.borrow().get(&node_id)
+ .map(ty::ParamTy::for_def);
+ if let Some(p) = param {
+ p.to_ty(tcx)
+ } else {
+ // Only while computing defaults of earlier type
+ // parameters can a type parameter be missing its def.
+ struct_span_err!(tcx.sess, span, E0128,
+ "type parameters with a default cannot use \
+ forward declared identifiers")
+ .span_label(span, &format!("defaulted type parameters \
+ cannot be forward declared"))
+ .emit();
+ tcx.types.err
+ }
}
Def::SelfTy(_, Some(impl_id)) => {
// Self in impl (we know the concrete type).
tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty))
}
hir::TyObjectSum(ref ty, ref bounds) => {
- match self.ast_ty_to_trait_ref(rscope, &ty, bounds) {
- Ok((trait_ref, projection_bounds)) => {
- self.trait_ref_to_object_type(rscope,
- ast_ty.span,
- trait_ref,
- projection_bounds,
- bounds)
- }
- Err(ErrorReported) => {
- self.tcx().types.err
- }
- }
+ self.ast_ty_to_object_trait_ref(rscope, ast_ty.span, ty, bounds)
}
hir::TyPtr(ref mt) => {
tcx.mk_ptr(ty::TypeAndMut {
tcx.mk_fn_ptr(bare_fn_ty)
}
hir::TyPolyTraitRef(ref bounds) => {
- self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
+ self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
}
hir::TyImplTrait(ref bounds) => {
use collect::{compute_bounds, SizedByDefault};
// Create the anonymized type.
let def_id = tcx.map.local_def_id(ast_ty.id);
if let Some(anon_scope) = rscope.anon_type_scope() {
- let substs = anon_scope.fresh_substs(tcx);
+ let substs = anon_scope.fresh_substs(self, ast_ty.span);
let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
// Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
let predicates = bounds.predicates(tcx, ty);
let predicates = tcx.lift_to_global(&predicates).unwrap();
tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates {
- predicates: VecPerParamSpace::new(vec![], vec![], predicates)
+ parent: None,
+ predicates: predicates
});
ty
// values in a ExprClosure, or as
// the type of local variables. Both of these cases are
// handled specially and will not descend into this routine.
- self.ty_infer(None, None, None, ast_ty.span)
+ self.ty_infer(ast_ty.span)
}
};
{
match a.ty.node {
hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
- hir::TyInfer => self.ty_infer(None, None, None, a.ty.span),
+ hir::TyInfer => self.ty_infer(a.ty.span),
_ => self.ast_ty_to_ty(rscope, &a.ty),
}
}
let output_ty = match decl.output {
_ if is_infer && expected_ret_ty.is_some() =>
expected_ret_ty.unwrap(),
- _ if is_infer =>
- self.ty_infer(None, None, None, decl.output.span()),
+ _ if is_infer => self.ty_infer(decl.output.span()),
hir::Return(ref output) =>
self.ast_ty_to_ty(&rb, &output),
hir::DefaultReturn(..) => bug!(),
}
}
- /// Given an existential type like `Foo+'a+Bar`, this routine converts
- /// the `'a` and `Bar` intos an `ExistentialBounds` struct.
- /// The `main_trait_refs` argument specifies the `Foo` -- it is absent
- /// for closures. Eventually this should all be normalized, I think,
- /// so that there is no "main trait ref" and instead we just have a flat
- /// list of bounds as the existential type.
- fn conv_existential_bounds(&self,
- rscope: &RegionScope,
- span: Span,
- principal_trait_ref: ty::PolyTraitRef<'tcx>,
- projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
- ast_bounds: &[hir::TyParamBound])
- -> ty::ExistentialBounds<'tcx>
- {
- let partitioned_bounds =
- partition_bounds(self.tcx(), span, ast_bounds);
-
- self.conv_existential_bounds_from_partitioned_bounds(
- rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
- }
-
- fn conv_ty_poly_trait_ref(&self,
+ fn conv_object_ty_poly_trait_ref(&self,
rscope: &RegionScope,
span: Span,
ast_bounds: &[hir::TyParamBound])
{
let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]);
- let mut projection_bounds = Vec::new();
- let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
- let trait_bound = partitioned_bounds.trait_bounds.remove(0);
- self.instantiate_poly_trait_ref(rscope,
- trait_bound,
- None,
- &mut projection_bounds)
+ let trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
+ partitioned_bounds.trait_bounds.remove(0)
} else {
span_err!(self.tcx().sess, span, E0224,
"at least one non-builtin trait is required for an object type");
return self.tcx().types.err;
};
- let bounds =
- self.conv_existential_bounds_from_partitioned_bounds(rscope,
- span,
- main_trait_bound.clone(),
- projection_bounds,
- partitioned_bounds);
-
- self.make_object_type(span, main_trait_bound, bounds)
- }
-
- pub fn conv_existential_bounds_from_partitioned_bounds(&self,
- rscope: &RegionScope,
- span: Span,
- principal_trait_ref: ty::PolyTraitRef<'tcx>,
- projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, // Empty for boxed closures
- partitioned_bounds: PartitionedBounds)
- -> ty::ExistentialBounds<'tcx>
- {
- let PartitionedBounds { builtin_bounds,
- trait_bounds,
- region_bounds } =
- partitioned_bounds;
-
- if !trait_bounds.is_empty() {
- let b = &trait_bounds[0];
- let span = b.trait_ref.path.span;
- struct_span_err!(self.tcx().sess, span, E0225,
- "only the builtin traits can be used as closure or object bounds")
- .span_label(span, &format!("non-builtin trait used as bounds"))
- .emit();
- }
-
- let region_bound =
- self.compute_object_lifetime_bound(span,
- ®ion_bounds,
- principal_trait_ref,
- builtin_bounds);
-
- let region_bound = match region_bound {
- Some(r) => r,
- None => {
- match rscope.object_lifetime_default(span) {
- Some(r) => r,
- None => {
- span_err!(self.tcx().sess, span, E0228,
- "the lifetime bound for this object type cannot be deduced \
- from context; please supply an explicit bound");
- ty::ReStatic
- }
- }
- }
- };
-
- debug!("region_bound: {:?}", region_bound);
-
- ty::ExistentialBounds::new(region_bound, builtin_bounds, projection_bounds)
+ let trait_ref = &trait_bound.trait_ref;
+ let trait_def_id = self.trait_def_id(trait_ref);
+ self.trait_path_to_object_type(rscope,
+ trait_ref.path.span,
+ PathParamMode::Explicit,
+ trait_def_id,
+ trait_ref.ref_id,
+ trait_ref.path.segments.last().unwrap(),
+ span,
+ partitioned_bounds)
}
/// Given the bounds on an object, determines what single region bound (if any) we can
fn compute_object_lifetime_bound(&self,
span: Span,
explicit_region_bounds: &[&hir::Lifetime],
- principal_trait_ref: ty::PolyTraitRef<'tcx>,
+ principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>,
builtin_bounds: ty::BuiltinBounds)
-> Option<ty::Region> // if None, use the default
{
// No explicit region bound specified. Therefore, examine trait
// bounds and see if we can derive region bounds from those.
let derived_region_bounds =
- object_region_bounds(tcx, &principal_trait_ref, builtin_bounds);
+ object_region_bounds(tcx, principal_trait_ref, builtin_bounds);
// If there are no derived region bounds, then report back that we
// can find no region bound. The caller will use the default.
let parameters = &segments[segments.len() - 1].parameters;
if !parameters.types().is_empty() {
check_type_argument_count(tcx, b.trait_ref.path.span,
- parameters.types().len(), 0, 0);
+ parameters.types().len(), &[]);
}
if !parameters.lifetimes().is_empty() {
report_lifetime_number_error(tcx, b.trait_ref.path.span,
}
fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
- required: usize, accepted: usize) {
+ ty_param_defs: &[ty::TypeParameterDef]) {
+ let accepted = ty_param_defs.len();
+ let required = ty_param_defs.iter().take_while(|x| x.default.is_none()) .count();
if supplied < required {
let expected = if required < accepted {
"expected at least"
}
// Type check the path.
- let scheme = tcx.lookup_item_type(def.def_id());
- let predicates = tcx.lookup_predicates(def.def_id());
- let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
- opt_ty, def, pat.span, pat.id);
+ let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
self.demand_suptype(pat.span, expected, pat_ty);
}
}
// Type check the path.
- let scheme = tcx.lookup_item_type(def.def_id());
- let scheme = if scheme.ty.is_fn() {
+ let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
+
+ let pat_ty = if pat_ty.is_fn() {
// Replace constructor type with constructed type for tuple struct patterns.
- let fn_ret = tcx.no_late_bound_regions(&scheme.ty.fn_ret()).unwrap();
- ty::TypeScheme { ty: fn_ret, generics: scheme.generics }
+ tcx.no_late_bound_regions(&pat_ty.fn_ret()).unwrap()
} else {
// Leave the type as is for unit structs (backward compatibility).
- scheme
+ pat_ty
};
- let predicates = tcx.lookup_predicates(def.def_id());
- let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
- opt_ty, def, pat.span, pat.id);
+ self.write_ty(pat.id, pat_ty);
self.demand_eqtype(pat.span, expected, pat_ty);
// Type check subpatterns.
Some(f) => f,
None => return None
},
- substs: tcx.mk_substs(Substs::new_trait(vec![], vec![], self.cur_ty))
+ substs: Substs::new_trait(tcx, vec![], vec![], self.cur_ty)
};
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
match t.sty {
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
- ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())),
+ ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.def_id())),
ty::TyStruct(def, substs) => {
// FIXME(arielb1): do some kind of normalization
match def.struct_variant().fields.last() {
use super::{check_fn, Expectation, FnCtxt};
use astconv::AstConv;
-use rustc::ty::subst;
use rustc::ty::{self, ToPolyTraitRef, Ty};
use std::cmp;
use syntax::abi::Abi;
match expected_ty.sty {
ty::TyTrait(ref object_type) => {
- let proj_bounds = object_type.projection_bounds_with_self_ty(self.tcx,
- self.tcx.types.err);
- let sig = proj_bounds.iter()
- .filter_map(|pb| self.deduce_sig_from_projection(pb))
- .next();
- let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal_def_id());
+ let sig = object_type.projection_bounds.iter().filter_map(|pb| {
+ let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
+ self.deduce_sig_from_projection(&pb)
+ }).next();
+ let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal.def_id());
(sig, kind)
}
ty::TyInfer(ty::TyVar(vid)) => {
return None;
}
- let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0);
+ let arg_param_ty = trait_ref.substs().types[1];
let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty);
use rustc::ty;
use rustc::traits::{self, Reveal};
use rustc::ty::error::ExpectedFound;
-use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
+use rustc::ty::subst::{Subst, Substs};
use rustc::hir::map::Node;
use rustc::hir::{ImplItemKind, TraitItem_};
}
}
- let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
- let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
+ let num_impl_m_type_params = impl_m.generics.types.len();
+ let num_trait_m_type_params = trait_m.generics.types.len();
if num_impl_m_type_params != num_trait_m_type_params {
span_err!(tcx.sess, impl_m_span, E0049,
"method `{}` has {} type parameter{} \
// Create mapping from trait to skolemized.
let trait_to_skol_substs =
- trait_to_impl_substs
- .subst(tcx, impl_to_skol_substs).clone()
- .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
- impl_to_skol_substs.regions.get_slice(subst::FnSpace).to_vec());
+ impl_to_skol_substs.rebase_onto(tcx, impl_m.container_id(),
+ trait_to_impl_substs.subst(tcx, impl_to_skol_substs));
debug!("compare_impl_method: trait_to_skol_substs={:?}",
trait_to_skol_substs);
impl_m,
&trait_m.generics,
&impl_m.generics,
- &trait_to_skol_substs,
+ trait_to_skol_substs,
impl_to_skol_substs) {
return;
}
tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| {
let mut fulfillment_cx = traits::FulfillmentContext::new();
- // Normalize the associated types in the trait_bounds.
- let trait_bounds = trait_m.predicates.instantiate(tcx, &trait_to_skol_substs);
-
// Create obligations for each predicate declared by the impl
// definition in the context of the trait's parameter
// environment. We can't just use `impl_env.caller_bounds`,
// however, because we want to replace all late-bound regions with
// region variables.
- let impl_bounds =
- impl_m.predicates.instantiate(tcx, impl_to_skol_substs);
-
- debug!("compare_impl_method: impl_bounds={:?}", impl_bounds);
+ let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap());
+ let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
- // Obtain the predicate split predicate sets for each.
- let trait_pred = trait_bounds.predicates.split();
- let impl_pred = impl_bounds.predicates.split();
+ debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
// This is the only tricky bit of the new way we check implementation methods
- // We need to build a set of predicates where only the FnSpace bounds
+ // We need to build a set of predicates where only the method-level bounds
// are from the trait and we assume all other bounds from the implementation
// to be previously satisfied.
//
// We then register the obligations from the impl_m and check to see
// if all constraints hold.
- let hybrid_preds = VecPerParamSpace::new(
- impl_pred.types,
- impl_pred.selfs,
- trait_pred.fns
- );
+ hybrid_preds.predicates.extend(
+ trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
// Construct trait parameter environment and then shift it into the skolemized viewpoint.
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
- let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.into_vec());
+ let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
let trait_param_env = traits::normalize_param_env_or_error(tcx,
trait_param_env,
normalize_cause.clone());
// FIXME(@jroesch) this seems ugly, but is a temporary change
infcx.parameter_environment = trait_param_env;
- debug!("compare_impl_method: trait_bounds={:?}",
+ debug!("compare_impl_method: caller_bounds={:?}",
infcx.parameter_environment.caller_bounds);
let mut selcx = traits::SelectionContext::new(&infcx);
- let (impl_pred_fns, _) =
+ let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs);
+ let (impl_m_own_bounds, _) =
infcx.replace_late_bound_regions_with_fresh_var(
impl_m_span,
infer::HigherRankedType,
- &ty::Binder(impl_pred.fns));
- for predicate in impl_pred_fns {
+ &ty::Binder(impl_m_own_bounds.predicates));
+ for predicate in impl_m_own_bounds {
let traits::Normalized { value: predicate, .. } =
traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
infcx.parameter_environment.free_id_outlive,
&trait_m.fty.sig);
let trait_sig =
- trait_sig.subst(tcx, &trait_to_skol_substs);
+ trait_sig.subst(tcx, trait_to_skol_substs);
let trait_sig =
assoc::normalize_associated_types_in(&infcx,
&mut fulfillment_cx,
-> bool
{
- let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
- let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
+ let trait_params = &trait_generics.regions[..];
+ let impl_params = &impl_generics.regions[..];
debug!("check_region_bounds_on_impl_method: \
trait_generics={:?} \
// Create mapping from trait to skolemized.
let trait_to_skol_substs =
- trait_to_impl_substs
- .subst(tcx, impl_to_skol_substs).clone()
- .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
- impl_to_skol_substs.regions.get_slice(subst::FnSpace).to_vec());
+ impl_to_skol_substs.rebase_onto(tcx, impl_c.container.id(),
+ trait_to_impl_substs.subst(tcx, impl_to_skol_substs));
debug!("compare_const_impl: trait_to_skol_substs={:?}",
trait_to_skol_substs);
// Compute skolemized form of impl and trait const tys.
let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
- let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs);
+ let trait_ty = trait_c.ty.subst(tcx, trait_to_skol_substs);
let mut origin = TypeOrigin::Misc(impl_c_span);
let err = infcx.commit_if_ok(|_| {
use middle::free_region::FreeRegionMap;
use rustc::infer;
use middle::region;
-use rustc::ty::subst::{self, Subst};
+use rustc::ty::subst::{Subst, Substs};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::traits::{self, Reveal};
use util::nodemap::FnvHashSet;
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> {
- let ty::TypeScheme { generics: ref dtor_generics,
- ty: dtor_self_type } = ccx.tcx.lookup_item_type(drop_impl_did);
+ let dtor_self_type = ccx.tcx.lookup_item_type(drop_impl_did).ty;
let dtor_predicates = ccx.tcx.lookup_predicates(drop_impl_did);
match dtor_self_type.sty {
ty::TyEnum(adt_def, self_to_impl_substs) |
ty::TyStruct(adt_def, self_to_impl_substs) => {
ensure_drop_params_and_item_params_correspond(ccx,
drop_impl_did,
- dtor_generics,
- &dtor_self_type,
+ dtor_self_type,
adt_def.did)?;
ensure_drop_predicates_are_implied_by_item_defn(ccx,
fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
ccx: &CrateCtxt<'a, 'tcx>,
drop_impl_did: DefId,
- drop_impl_generics: &ty::Generics<'tcx>,
- drop_impl_ty: &ty::Ty<'tcx>,
+ drop_impl_ty: Ty<'tcx>,
self_type_did: DefId) -> Result<(), ()>
{
let tcx = ccx.tcx;
let drop_impl_span = tcx.map.def_id_span(drop_impl_did, syntax_pos::DUMMY_SP);
let fresh_impl_substs =
- infcx.fresh_substs_for_generics(drop_impl_span, drop_impl_generics);
- let fresh_impl_self_ty = drop_impl_ty.subst(tcx, &fresh_impl_substs);
+ infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
+ let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
if let Err(_) = infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span),
named_type, fresh_impl_self_ty) {
drop_impl_did: DefId,
dtor_predicates: &ty::GenericPredicates<'tcx>,
self_type_did: DefId,
- self_to_impl_substs: &subst::Substs<'tcx>) -> Result<(), ()> {
+ self_to_impl_substs: &Substs<'tcx>) -> Result<(), ()> {
// Here is an example, analogous to that from
// `compare_impl_method`.
let generic_assumptions = tcx.lookup_predicates(self_type_did);
let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
- assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::SelfSpace));
- assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::FnSpace));
- let assumptions_in_impl_context =
- assumptions_in_impl_context.predicates.get_slice(subst::TypeSpace);
+ let assumptions_in_impl_context = assumptions_in_impl_context.predicates;
// An earlier version of this code attempted to do this checking
// via the traits::fulfill machinery. However, it ran into trouble
// 'a:'b and T:'b into region inference constraints. It is simpler
// just to look for all the predicates directly.
- assert!(dtor_predicates.predicates.is_empty_in(subst::SelfSpace));
- assert!(dtor_predicates.predicates.is_empty_in(subst::FnSpace));
- let predicates = dtor_predicates.predicates.get_slice(subst::TypeSpace);
- for predicate in predicates {
+ assert_eq!(dtor_predicates.parent, None);
+ for predicate in &dtor_predicates.predicates {
// (We do not need to worry about deep analysis of type
// expressions etc because the Drop impls are already forced
// to take on a structure that is roughly an alpha-renaming of
ty::TyStruct(def, substs) if def.is_phantom_data() => {
// PhantomData<T> - behaves identically to T
- let ity = *substs.types.get(subst::TypeSpace, 0);
+ let ity = substs.types[0];
iterate_over_potentially_unsafe_regions_in_type(
cx, context, ity, depth+1)
}
use intrinsics;
use rustc::infer::TypeOrigin;
-use rustc::ty::subst::{self, Substs};
+use rustc::ty::subst::Substs;
use rustc::ty::FnSig;
use rustc::ty::{self, Ty};
use {CrateCtxt, require_same_types};
let def_id = tcx.map.local_def_id(it.id);
let i_ty = tcx.lookup_item_type(def_id);
- let mut substs = Substs::empty();
- substs.types = i_ty.generics.types.map(|def| tcx.mk_param_from_def(def));
+ let substs = Substs::for_item(tcx, def_id,
+ |_, _| ty::ReErased,
+ |def, _| tcx.mk_param_from_def(def));
- let fty = tcx.mk_fn_def(def_id, tcx.mk_substs(substs),
- tcx.mk_bare_fn(ty::BareFnTy {
+ let fty = tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy {
unsafety: hir::Unsafety::Unsafe,
abi: abi,
sig: ty::Binder(FnSig {
variadic: false,
}),
}));
- let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
+ let i_n_tps = i_ty.generics.types.len();
if i_n_tps != n_tps {
struct_span_err!(tcx.sess, it.span, E0094,
"intrinsic has wrong number of type \
pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
let name = token::intern(&format!("P{}", n));
- ccx.tcx.mk_param(subst::FnSpace, n, name)
+ ccx.tcx.mk_param(n, name)
}
let tcx = ccx.tcx;
it: &hir::ForeignItem) {
let param = |n| {
let name = token::intern(&format!("P{}", n));
- ccx.tcx.mk_param(subst::FnSpace, n, name)
+ ccx.tcx.mk_param(n, name)
};
let tcx = ccx.tcx;
let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id));
- let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
+ let i_n_tps = i_ty.generics.types.len();
let name = it.name.as_str();
let (n_tps, inputs, output) = match &*name {
use check::{FnCtxt, callee};
use hir::def_id::DefId;
-use rustc::ty::subst::{self};
+use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty};
use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
/// argument is the receiver.
method_sig: ty::FnSig<'tcx>,
- /// Substitutions for all types/early-bound-regions declared on
- /// the method.
- all_substs: subst::Substs<'tcx>,
-
/// Generic bounds on the method's parameters which must be added
/// as pending obligations.
method_predicates: ty::InstantiatedPredicates<'tcx>,
// Create the final signature for the method, replacing late-bound regions.
let InstantiatedMethodSig {
- method_sig, all_substs, method_predicates
+ method_sig, method_predicates
} = self.instantiate_method_sig(&pick, all_substs);
- let all_substs = self.tcx.mk_substs(all_substs);
let method_self_ty = method_sig.inputs[0];
// Unify the (adjusted) self type with what the method expects.
fn fresh_receiver_substs(&mut self,
self_ty: Ty<'tcx>,
pick: &probe::Pick<'tcx>)
- -> subst::Substs<'tcx>
+ -> &'tcx Substs<'tcx>
{
match pick.kind {
probe::InherentImplPick => {
probe::ObjectPick => {
let trait_def_id = pick.item.container().id();
- self.extract_trait_ref(self_ty, |this, object_ty, data| {
+ self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
// The object data has no entry for the Self
// Type. For the purposes of this method call, we
// substitute the object type itself. This
// been ruled out when we deemed the trait to be
// "object safe".
let original_poly_trait_ref =
- data.principal_trait_ref_with_self_ty(this.tcx, object_ty);
+ principal.with_self_ty(this.tcx, object_ty);
let upcast_poly_trait_ref =
- this.upcast(original_poly_trait_ref.clone(), trait_def_id);
+ this.upcast(original_poly_trait_ref, trait_def_id);
let upcast_trait_ref =
this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
original_poly_trait_ref,
upcast_trait_ref,
trait_def_id);
- upcast_trait_ref.substs.clone()
+ upcast_trait_ref.substs
})
}
let impl_trait_ref =
self.instantiate_type_scheme(
self.span,
- &impl_polytype.substs,
+ impl_polytype.substs,
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
- impl_trait_ref.substs.clone()
+ impl_trait_ref.substs
}
probe::TraitPick => {
let trait_def_id = pick.item.container().id();
- let trait_def = self.tcx.lookup_trait_def(trait_def_id);
// Make a trait reference `$0 : Trait<$1...$n>`
// consisting entirely of type variables. Later on in
// the process we will unify the transformed-self-type
// of the method with the actual type in order to
// unify some of these variables.
- self.fresh_substs_for_trait(self.span,
- &trait_def.generics,
- self.next_ty_var())
+ self.fresh_substs_for_item(self.span, trait_def_id)
}
probe::WhereClausePick(ref poly_trait_ref) => {
// Where clauses can have bound regions in them. We need to instantiate
// those to convert from a poly-trait-ref to a trait-ref.
- self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs.clone()
+ self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs
}
}
}
- fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
- F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R,
+ fn extract_existential_trait_ref<R, F>(&mut self,
+ self_ty: Ty<'tcx>,
+ mut closure: F) -> R
+ where F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>,
+ Ty<'tcx>,
+ ty::PolyExistentialTraitRef<'tcx>) -> R,
{
// If we specified that this is an object method, then the
// self-type ought to be something that can be dereferenced to
self.fcx.autoderef(self.span, self_ty)
.filter_map(|(ty, _)| {
match ty.sty {
- ty::TyTrait(ref data) => Some(closure(self, ty, &data)),
+ ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)),
_ => None,
}
})
fn instantiate_method_substs(&mut self,
pick: &probe::Pick<'tcx>,
- supplied_method_types: Vec<Ty<'tcx>>,
- substs: subst::Substs<'tcx>)
- -> subst::Substs<'tcx>
+ mut supplied_method_types: Vec<Ty<'tcx>>,
+ substs: &Substs<'tcx>)
+ -> &'tcx Substs<'tcx>
{
// Determine the values for the generic parameters of the method.
// If they were not explicitly supplied, just construct fresh
// variables.
let num_supplied_types = supplied_method_types.len();
let method = pick.item.as_opt_method().unwrap();
- let method_types = method.generics.types.get_slice(subst::FnSpace);
- let num_method_types = method_types.len();
-
+ let num_method_types = method.generics.types.len();
+
+ if num_supplied_types > 0 && num_supplied_types != num_method_types {
+ if num_method_types == 0 {
+ span_err!(self.tcx.sess, self.span, E0035,
+ "does not take type parameters");
+ } else {
+ span_err!(self.tcx.sess, self.span, E0036,
+ "incorrect number of type parameters given for this method: \
+ expected {}, found {}",
+ num_method_types, num_supplied_types);
+ }
+ supplied_method_types = vec![self.tcx.types.err; num_method_types];
+ }
// Create subst for early-bound lifetime parameters, combining
// parameters from the type and those from the method.
//
// FIXME -- permit users to manually specify lifetimes
- let method_regions =
- self.region_vars_for_defs(
- self.span,
- pick.item.as_opt_method().unwrap()
- .generics.regions.get_slice(subst::FnSpace));
-
- let subst::Substs { types, regions } = substs;
- let regions = regions.with_slice(subst::FnSpace, &method_regions);
- let mut final_substs = subst::Substs { types: types, regions: regions };
-
- if num_supplied_types == 0 {
- self.type_vars_for_defs(
- self.span,
- subst::FnSpace,
- &mut final_substs,
- method_types);
- } else if num_method_types == 0 {
- span_err!(self.tcx.sess, self.span, E0035,
- "does not take type parameters");
- self.type_vars_for_defs(
- self.span,
- subst::FnSpace,
- &mut final_substs,
- method_types);
- } else if num_supplied_types != num_method_types {
- span_err!(self.tcx.sess, self.span, E0036,
- "incorrect number of type parameters given for this method: expected {}, found {}",
- num_method_types, num_supplied_types);
- final_substs.types.replace(
- subst::FnSpace,
- vec![self.tcx.types.err; num_method_types]);
- } else {
- final_substs.types.replace(subst::FnSpace, supplied_method_types);
- }
-
- return final_substs;
+ Substs::for_item(self.tcx, method.def_id, |def, _| {
+ if let Some(&r) = substs.regions.get(def.index as usize) {
+ r
+ } else {
+ self.region_var_for_def(self.span, def)
+ }
+ }, |def, cur_substs| {
+ if let Some(&ty) = substs.types.get(def.index as usize) {
+ ty
+ } else if supplied_method_types.is_empty() {
+ self.type_var_for_def(self.span, def, cur_substs)
+ } else {
+ supplied_method_types[def.index as usize - substs.types.len()]
+ }
+ })
}
fn unify_receivers(&mut self,
fn instantiate_method_sig(&mut self,
pick: &probe::Pick<'tcx>,
- all_substs: subst::Substs<'tcx>)
+ all_substs: &'tcx Substs<'tcx>)
-> InstantiatedMethodSig<'tcx>
{
debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
// type/early-bound-regions substitutions performed. There can
// be no late-bound regions appearing here.
let method_predicates = pick.item.as_opt_method().unwrap()
- .predicates.instantiate(self.tcx, &all_substs);
+ .predicates.instantiate(self.tcx, all_substs);
let method_predicates = self.normalize_associated_types_in(self.span,
&method_predicates);
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
method_sig);
- let method_sig = self.instantiate_type_scheme(self.span, &all_substs, &method_sig);
+ let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
debug!("type scheme substituted, method_sig={:?}",
method_sig);
InstantiatedMethodSig {
method_sig: method_sig,
- all_substs: all_substs,
method_predicates: method_predicates,
}
}
fn add_obligations(&mut self,
fty: Ty<'tcx>,
- all_substs: &subst::Substs<'tcx>,
+ all_substs: &Substs<'tcx>,
method_predicates: &ty::InstantiatedPredicates<'tcx>) {
debug!("add_obligations: fty={:?} all_substs={:?} method_predicates={:?}",
fty,
use check::FnCtxt;
use hir::def::Def;
use hir::def_id::DefId;
-use rustc::ty::subst;
+use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
- let type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace);
- let expected_number_of_input_types = type_parameter_defs.len();
-
- assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
+ if let Some(ref input_types) = opt_input_types {
+ assert_eq!(trait_def.generics.types.len() - 1, input_types.len());
+ }
assert!(trait_def.generics.regions.is_empty());
// Construct a trait-reference `self_ty : Trait<input_tys>`
- let mut substs = subst::Substs::new_trait(Vec::new(), Vec::new(), self_ty);
-
- match opt_input_types {
- Some(input_types) => {
- assert_eq!(expected_number_of_input_types, input_types.len());
- substs.types.replace(subst::ParamSpace::TypeSpace, input_types);
+ let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
+ self.region_var_for_def(span, def)
+ }, |def, substs| {
+ if def.index == 0 {
+ self_ty
+ } else if let Some(ref input_types) = opt_input_types {
+ input_types[def.index as usize - 1]
+ } else {
+ self.type_var_for_def(span, def, substs)
}
+ });
- None => {
- self.type_vars_for_defs(
- span,
- subst::ParamSpace::TypeSpace,
- &mut substs,
- type_parameter_defs);
- }
- }
-
- let trait_ref = ty::TraitRef::new(trait_def_id, self.tcx.mk_substs(substs));
+ let trait_ref = ty::TraitRef::new(trait_def_id, substs);
// Construct an obligation
let poly_trait_ref = trait_ref.to_poly_trait_ref();
let tcx = self.tcx;
let method_item = self.trait_item(trait_def_id, m_name).unwrap();
let method_ty = method_item.as_opt_method().unwrap();
- assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
- assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);
+ assert_eq!(method_ty.generics.types.len(), 0);
+ assert_eq!(method_ty.generics.regions.len(), 0);
debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
method_item, method_ty);
use check::{FnCtxt};
use hir::def_id::DefId;
use hir::def::Def;
-use rustc::ty::subst;
-use rustc::ty::subst::Subst;
+use rustc::ty::subst::{Subst, Substs};
use rustc::traits;
use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable};
use rustc::infer::{InferOk, TypeOrigin};
#[derive(Debug)]
enum CandidateKind<'tcx> {
- InherentImplCandidate(subst::Substs<'tcx>,
+ InherentImplCandidate(&'tcx Substs<'tcx>,
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
- ExtensionImplCandidate(/* Impl */ DefId, subst::Substs<'tcx>,
+ ExtensionImplCandidate(/* Impl */ DefId, &'tcx Substs<'tcx>,
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
ObjectCandidate,
TraitCandidate,
match self_ty.sty {
ty::TyTrait(box ref data) => {
- self.assemble_inherent_candidates_from_object(self_ty, data);
- self.assemble_inherent_impl_candidates_for_type(data.principal_def_id());
+ self.assemble_inherent_candidates_from_object(self_ty, data.principal);
+ self.assemble_inherent_impl_candidates_for_type(data.principal.def_id());
}
ty::TyEnum(def, _) |
ty::TyStruct(def, _) => {
}
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
- let impl_ty = impl_ty.subst(self.tcx, &impl_substs);
+ let impl_ty = impl_ty.subst(self.tcx, impl_substs);
// Determine the receiver type that the method itself expects.
- let xform_self_ty = self.xform_self_ty(&item, impl_ty, &impl_substs);
+ let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs);
// We can't use normalize_associated_types_in as it will pollute the
// fcx's fulfillment context after this probe is over.
fn assemble_inherent_candidates_from_object(&mut self,
self_ty: Ty<'tcx>,
- data: &ty::TraitTy<'tcx>) {
+ principal: ty::PolyExistentialTraitRef<'tcx>) {
debug!("assemble_inherent_candidates_from_object(self_ty={:?})",
self_ty);
// a substitution that replaces `Self` with the object type
// itself. Hence, a `&self` method will wind up with an
// argument type like `&Trait`.
- let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx, self_ty);
+ let trait_ref = principal.with_self_ty(self.tcx, self_ty);
self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| {
let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
trait_ref,
trait_ref.substs,
m);
- assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
- trait_ref.substs.types.get_slice(subst::TypeSpace).len());
- assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
- trait_ref.substs.regions.get_slice(subst::TypeSpace).len());
- assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(),
- trait_ref.substs.types.get_slice(subst::SelfSpace).len());
- assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
- trait_ref.substs.regions.get_slice(subst::SelfSpace).len());
+ assert_eq!(m.generics.parent_types as usize,
+ trait_ref.substs.types.len());
+ assert_eq!(m.generics.parent_regions as usize,
+ trait_ref.substs.regions.len());
}
// Because this trait derives from a where-clause, it
let impl_trait_ref =
self.tcx.impl_trait_ref(impl_def_id)
.unwrap() // we know this is a trait impl
- .subst(self.tcx, &impl_substs);
+ .subst(self.tcx, impl_substs);
debug!("impl_trait_ref={:?}", impl_trait_ref);
// for the purposes of our method lookup, we only take
// receiver type into account, so we can just substitute
// fresh types here to use during substitution and subtyping.
- let trait_def = self.tcx.lookup_trait_def(trait_def_id);
- let substs = self.fresh_substs_for_trait(self.span,
- &trait_def.generics,
- step.self_ty);
+ let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
+ self.region_var_for_def(self.span, def)
+ }, |def, substs| {
+ if def.index == 0 {
+ step.self_ty
+ } else {
+ self.type_var_for_def(self.span, def, substs)
+ }
+ });
let xform_self_ty = self.xform_self_ty(&item,
step.self_ty,
- &substs);
+ substs);
self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
let trait_predicates = self.tcx.lookup_predicates(def_id);
let bounds = trait_predicates.instantiate(self.tcx, substs);
- let predicates = bounds.predicates.into_vec();
+ let predicates = bounds.predicates;
debug!("assemble_projection_candidates: predicates={:?}",
predicates);
for poly_bound in
fn xform_self_ty(&self,
item: &ty::ImplOrTraitItem<'tcx>,
impl_ty: Ty<'tcx>,
- substs: &subst::Substs<'tcx>)
+ substs: &Substs<'tcx>)
-> Ty<'tcx>
{
match item.as_opt_method() {
fn xform_method_self_ty(&self,
method: &Rc<ty::Method<'tcx>>,
impl_ty: Ty<'tcx>,
- substs: &subst::Substs<'tcx>)
+ substs: &Substs<'tcx>)
-> Ty<'tcx>
{
debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
// are given do not include type/lifetime parameters for the
// method yet. So create fresh variables here for those too,
// if there are any.
- assert_eq!(substs.types.len(subst::FnSpace), 0);
- assert_eq!(substs.regions.len(subst::FnSpace), 0);
+ assert_eq!(substs.types.len(), method.generics.parent_types as usize);
+ assert_eq!(substs.regions.len(), method.generics.parent_regions as usize);
if self.mode == Mode::Path {
return impl_ty;
}
- let mut placeholder;
- let mut substs = substs;
- if
- !method.generics.types.is_empty_in(subst::FnSpace) ||
- !method.generics.regions.is_empty_in(subst::FnSpace)
- {
- // In general, during probe we erase regions. See
- // `impl_self_ty()` for an explanation.
- let method_regions =
- method.generics.regions.get_slice(subst::FnSpace)
- .iter()
- .map(|_| ty::ReErased)
- .collect();
-
- placeholder = (*substs).clone().with_method(Vec::new(), method_regions);
-
- self.type_vars_for_defs(
- self.span,
- subst::FnSpace,
- &mut placeholder,
- method.generics.types.get_slice(subst::FnSpace));
-
- substs = &placeholder;
- }
-
// Erase any late-bound regions from the method and substitute
// in the values from the substitution.
let xform_self_ty = method.fty.sig.input(0);
let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty);
- let xform_self_ty = xform_self_ty.subst(self.tcx, substs);
- xform_self_ty
+ if method.generics.types.is_empty() && method.generics.regions.is_empty() {
+ xform_self_ty.subst(self.tcx, substs)
+ } else {
+ let substs = Substs::for_item(self.tcx, method.def_id, |def, _| {
+ if let Some(&r) = substs.regions.get(def.index as usize) {
+ r
+ } else {
+ // In general, during probe we erase regions. See
+ // `impl_self_ty()` for an explanation.
+ ty::ReErased
+ }
+ }, |def, cur_substs| {
+ if let Some(&ty) = substs.types.get(def.index as usize) {
+ ty
+ } else {
+ self.type_var_for_def(self.span, def, cur_substs)
+ }
+ });
+ xform_self_ty.subst(self.tcx, substs)
+ }
}
/// Get the type of an impl and generate substitutions with placeholders.
fn impl_ty_and_substs(&self,
impl_def_id: DefId)
- -> (Ty<'tcx>, subst::Substs<'tcx>)
+ -> (Ty<'tcx>, &'tcx Substs<'tcx>)
{
- let impl_pty = self.tcx.lookup_item_type(impl_def_id);
-
- let type_vars =
- impl_pty.generics.types.map(
- |_| self.next_ty_var());
+ let impl_ty = self.tcx.lookup_item_type(impl_def_id).ty;
- let region_placeholders =
- impl_pty.generics.regions.map(
- |_| ty::ReErased); // see erase_late_bound_regions() for an expl of why 'erased
+ let substs = Substs::for_item(self.tcx, impl_def_id,
+ |_, _| ty::ReErased,
+ |_, _| self.next_ty_var());
- let substs = subst::Substs::new(type_vars, region_placeholders);
- (impl_pty.ty, substs)
+ (impl_ty, substs)
}
/// Replace late-bound-regions bound by `value` with `'static` using
self.autoderef(span, ty).any(|(ty, _)| self.probe(|_| {
let fn_once_substs =
- Substs::new_trait(vec![self.next_ty_var()], vec![], ty);
- let trait_ref =
- ty::TraitRef::new(fn_once,
- tcx.mk_substs(fn_once_substs));
+ Substs::new_trait(tcx, vec![self.next_ty_var()], vec![], ty);
+ let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
let poly_trait_ref = trait_ref.to_poly_trait_ref();
let obligation = Obligation::misc(span,
self.body_id,
match ty.sty {
ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.did.is_local(),
- ty::TyTrait(ref tr) => tr.principal_def_id().is_local(),
+ ty::TyTrait(ref tr) => tr.principal.def_id().is_local(),
ty::TyParam(_) => true,
use hir::def_id::DefId;
use hir::pat_util;
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
-use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
+use rustc::ty::subst::{Subst, Substs};
use rustc::traits::{self, Reveal};
-use rustc::ty::{GenericPredicates, TypeScheme};
use rustc::ty::{ParamTy, ParameterEnvironment};
use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility};
let impl_def_id = ccx.tcx.map.local_def_id(it.id);
match ccx.tcx.impl_trait_ref(impl_def_id) {
Some(impl_trait_ref) => {
- let trait_def_id = impl_trait_ref.def_id;
-
check_impl_items_against_trait(ccx,
it.span,
impl_def_id,
&impl_trait_ref,
impl_items);
- check_on_unimplemented(
- ccx,
- &ccx.tcx.lookup_trait_def(trait_def_id).generics,
- it,
- ccx.tcx.item_name(trait_def_id));
+ let trait_def_id = impl_trait_ref.def_id;
+ check_on_unimplemented(ccx, trait_def_id, it);
}
None => { }
}
}
hir::ItemTrait(..) => {
let def_id = ccx.tcx.map.local_def_id(it.id);
- let generics = &ccx.tcx.lookup_trait_def(def_id).generics;
- check_on_unimplemented(ccx, generics, it, it.name);
+ check_on_unimplemented(ccx, def_id, it);
}
hir::ItemStruct(..) => {
check_struct(ccx, it.id, it.span);
}
fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- generics: &ty::Generics,
- item: &hir::Item,
- name: ast::Name) {
+ def_id: DefId,
+ item: &hir::Item) {
+ let generics = ccx.tcx.lookup_generics(def_id);
if let Some(ref attr) = item.attrs.iter().find(|a| {
a.check_name("rustc_on_unimplemented")
}) {
}) {
Some(_) => (),
None => {
+ let name = ccx.tcx.item_name(def_id);
span_err!(ccx.tcx.sess, attr.span, E0230,
"there is no type parameter \
{} on trait {}",
&self.ast_ty_to_ty_cache
}
+ fn get_generics(&self, _: Span, id: DefId)
+ -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
+ {
+ Ok(self.tcx().lookup_generics(id))
+ }
+
fn get_item_type_scheme(&self, _: Span, id: DefId)
-> Result<ty::TypeScheme<'tcx>, ErrorReported>
{
.filter_map(|predicate| {
match *predicate {
ty::Predicate::Trait(ref data) => {
- if data.0.self_ty().is_param(def.space, def.index) {
+ if data.0.self_ty().is_param(def.index) {
Some(data.to_poly_trait_ref())
} else {
None
trait_def.associated_type_names.contains(&assoc_name)
}
- fn ty_infer(&self,
- ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
- substs: Option<&mut subst::Substs<'tcx>>,
- space: Option<subst::ParamSpace>,
- span: Span) -> Ty<'tcx> {
- // Grab the default doing subsitution
- let default = ty_param_def.and_then(|def| {
- def.default.map(|ty| type_variable::Default {
- ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)),
- origin_span: span,
- def_id: def.default_def_id
- })
- });
-
- let ty_var = self.next_ty_var_with_default(default);
+ fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
+ self.next_ty_var()
+ }
- // Finally we add the type variable to the substs
- match substs {
- None => ty_var,
- Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var }
- }
+ fn ty_infer_for_def(&self,
+ ty_param_def: &ty::TypeParameterDef<'tcx>,
+ substs: &Substs<'tcx>,
+ span: Span) -> Ty<'tcx> {
+ self.type_var_for_def(span, ty_param_def, substs)
}
fn projected_ty_from_poly_trait_ref(&self,
bounds: &ty::GenericPredicates<'tcx>)
-> ty::InstantiatedPredicates<'tcx>
{
+ let result = bounds.instantiate(self.tcx, substs);
+ let result = self.normalize_associated_types_in(span, &result.predicates);
+ debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
+ bounds,
+ substs,
+ result);
ty::InstantiatedPredicates {
- predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
+ predicates: result
}
}
node_id: ast::NodeId)
-> Ty<'tcx> {
debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
- let mut type_scheme = self.tcx.lookup_item_type(did);
- if type_scheme.ty.is_fn() {
+ let mut ty = self.tcx.lookup_item_type(did).ty;
+ if ty.is_fn() {
// Tuple variants have fn type even in type namespace, extract true variant type from it
- let fn_ret = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap();
- type_scheme = ty::TypeScheme { ty: fn_ret, generics: type_scheme.generics }
+ ty = self.tcx.no_late_bound_regions(&ty.fn_ret()).unwrap();
}
let type_predicates = self.tcx.lookup_predicates(did);
let substs = AstConv::ast_path_substs_for_ty(self, self,
path.span,
PathParamMode::Optional,
- &type_scheme.generics,
+ did,
path.segments.last().unwrap());
- let substs = self.tcx.mk_substs(substs);
- debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs);
+ debug!("instantiate_type_path: ty={:?} substs={:?}", ty, substs);
let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
let cause = traits::ObligationCause::new(path.span, self.body_id,
traits::ItemObligation(did));
self.add_obligations_for_parameters(cause, &bounds);
- let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty);
+ let ty_substituted = self.instantiate_type_scheme(path.span, substs, &ty);
self.write_ty(node_id, ty_substituted);
self.write_substs(node_id, ty::ItemSubsts {
substs: substs
span: Span, // (potential) receiver for this impl
did: DefId)
-> TypeAndSubsts<'tcx> {
- let tcx = self.tcx;
+ let ity = self.tcx.lookup_item_type(did);
+ debug!("impl_self_ty: ity={:?}", ity);
- let ity = tcx.lookup_item_type(did);
- let (tps, rps, raw_ty) =
- (ity.generics.types.get_slice(subst::TypeSpace),
- ity.generics.regions.get_slice(subst::TypeSpace),
- ity.ty);
-
- debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty);
-
- let rps = self.region_vars_for_defs(span, rps);
- let mut substs = subst::Substs::new(
- VecPerParamSpace::empty(),
- VecPerParamSpace::new(rps, Vec::new(), Vec::new()));
- self.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps);
- let substd_ty = self.instantiate_type_scheme(span, &substs, &raw_ty);
+ let substs = self.fresh_substs_for_item(span, did);
+ let substd_ty = self.instantiate_type_scheme(span, &substs, &ity.ty);
TypeAndSubsts { substs: substs, ty: substd_ty }
}
self.set_tainted_by_errors();
return None;
}
- Def::Variant(..) | Def::Struct(..) => {
- Some(self.tcx.expect_variant_def(def))
+ Def::Variant(type_did, _) | Def::Struct(type_did) => {
+ Some((type_did, self.tcx.expect_variant_def(def)))
}
- Def::TyAlias(did) | Def::AssociatedTy(_, did) => {
+ Def::TyAlias(did) => {
if let Some(&ty::TyStruct(adt, _)) = self.tcx.opt_lookup_item_type(did)
.map(|scheme| &scheme.ty.sty) {
- Some(adt.struct_variant())
+ Some((did, adt.struct_variant()))
} else {
None
}
_ => None
};
- if let Some(variant) = variant {
+ if let Some((def_id, variant)) = variant {
if variant.kind == ty::VariantKind::Tuple &&
!self.tcx.sess.features.borrow().relaxed_adts {
emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
"relaxed_adts", span, GateIssue::Language,
"tuple structs and variants in struct patterns are unstable");
}
- let ty = self.instantiate_type_path(def.def_id(), path, node_id);
+ let ty = self.instantiate_type_path(def_id, path, node_id);
Some((variant, ty))
} else {
struct_span_err!(self.tcx.sess, path.span, E0071,
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
expr.id, expr.span);
if def != Def::Err {
- let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
- def);
- self.instantiate_value_path(segments, scheme, &predicates,
- opt_ty, def, expr.span, id);
+ self.instantiate_value_path(segments, opt_ty, def, expr.span, id);
} else {
self.set_tainted_by_errors();
self.write_error(id);
*self.ps.borrow_mut() = prev;
}
- // Returns the type parameter count and the type for the given definition.
- fn type_scheme_and_predicates_for_def(&self,
- sp: Span,
- defn: Def)
- -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
- match defn {
- Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => {
- let typ = self.local_ty(sp, nid);
- (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
- ty::GenericPredicates::empty())
- }
- Def::Fn(id) | Def::Method(id) |
- Def::Static(id, _) | Def::Variant(_, id) |
- Def::Struct(id) | Def::Const(id) | Def::AssociatedConst(id) => {
- (self.tcx.lookup_item_type(id), self.tcx.lookup_predicates(id))
- }
- Def::Trait(_) |
- Def::Enum(..) |
- Def::TyAlias(..) |
- Def::AssociatedTy(..) |
- Def::PrimTy(_) |
- Def::TyParam(..) |
- Def::Mod(..) |
- Def::ForeignMod(..) |
- Def::Label(..) |
- Def::SelfTy(..) |
- Def::Err => {
- span_bug!(sp, "expected value, found {:?}", defn);
- }
- }
- }
-
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
pub fn instantiate_value_path(&self,
segments: &[hir::PathSegment],
- type_scheme: TypeScheme<'tcx>,
- type_predicates: &ty::GenericPredicates<'tcx>,
opt_self_ty: Option<Ty<'tcx>>,
def: Def,
span: Span,
node_id: ast::NodeId)
-> Ty<'tcx> {
- debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
+ debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
segments,
def,
- node_id,
- type_scheme);
+ node_id);
// We need to extract the type parameters supplied by the user in
// the path `path`. Due to the current setup, this is a bit of a
assert!(!segments.is_empty());
let mut ufcs_associated = None;
- let mut segment_spaces: Vec<_>;
+ let mut type_segment = None;
+ let mut fn_segment = None;
match def {
// Case 1 and 1b. Reference to a *type* or *enum variant*.
- Def::SelfTy(..) |
- Def::Struct(..) |
- Def::Variant(..) |
- Def::Enum(..) |
- Def::TyAlias(..) |
- Def::AssociatedTy(..) |
- Def::Trait(..) |
- Def::PrimTy(..) |
- Def::TyParam(..) => {
+ Def::Struct(def_id) |
+ Def::Variant(_, def_id) |
+ Def::Enum(def_id) |
+ Def::TyAlias(def_id) |
+ Def::AssociatedTy(_, def_id) |
+ Def::Trait(def_id) => {
// Everything but the final segment should have no
// parameters at all.
- segment_spaces = vec![None; segments.len() - 1];
- segment_spaces.push(Some(subst::TypeSpace));
+ let mut generics = self.tcx.lookup_generics(def_id);
+ if let Some(def_id) = generics.parent {
+ // Variant and struct constructors use the
+ // generics of their parent type definition.
+ generics = self.tcx.lookup_generics(def_id);
+ }
+ type_segment = Some((segments.last().unwrap(), generics));
}
// Case 2. Reference to a top-level value.
- Def::Fn(..) |
- Def::Const(..) |
- Def::Static(..) => {
- segment_spaces = vec![None; segments.len() - 1];
- segment_spaces.push(Some(subst::FnSpace));
- }
-
- // Case 3. Reference to a method.
- Def::Method(def_id) => {
- let container = self.tcx.impl_or_trait_item(def_id).container();
- match container {
- ty::TraitContainer(trait_did) => {
- callee::check_legal_trait_for_method_call(self.ccx, span, trait_did)
- }
- ty::ImplContainer(_) => {}
- }
-
- if segments.len() >= 2 {
- segment_spaces = vec![None; segments.len() - 2];
- segment_spaces.push(Some(subst::TypeSpace));
- segment_spaces.push(Some(subst::FnSpace));
- } else {
- // `<T>::method` will end up here, and so can `T::method`.
- let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
- segment_spaces = vec![Some(subst::FnSpace)];
- ufcs_associated = Some((container, self_ty));
- }
+ Def::Fn(def_id) |
+ Def::Const(def_id) |
+ Def::Static(def_id, _) => {
+ fn_segment = Some((segments.last().unwrap(),
+ self.tcx.lookup_generics(def_id)));
}
+ // Case 3. Reference to a method or associated const.
+ Def::Method(def_id) |
Def::AssociatedConst(def_id) => {
let container = self.tcx.impl_or_trait_item(def_id).container();
match container {
ty::ImplContainer(_) => {}
}
+ let generics = self.tcx.lookup_generics(def_id);
if segments.len() >= 2 {
- segment_spaces = vec![None; segments.len() - 2];
- segment_spaces.push(Some(subst::TypeSpace));
- segment_spaces.push(None);
+ let parent_generics = self.tcx.lookup_generics(generics.parent.unwrap());
+ type_segment = Some((&segments[segments.len() - 2], parent_generics));
} else {
- // `<T>::CONST` will end up here, and so can `T::CONST`.
- let self_ty = opt_self_ty.expect("UFCS sugared const missing Self");
- segment_spaces = vec![None];
+ // `<T>::assoc` will end up here, and so can `T::assoc`.
+ let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self");
ufcs_associated = Some((container, self_ty));
}
+ fn_segment = Some((segments.last().unwrap(), generics));
}
// Other cases. Various nonsense that really shouldn't show up
// elsewhere. (I hope)
Def::Mod(..) |
Def::ForeignMod(..) |
+ Def::PrimTy(..) |
+ Def::SelfTy(..) |
+ Def::TyParam(..) |
Def::Local(..) |
Def::Label(..) |
- Def::Upvar(..) => {
- segment_spaces = vec![None; segments.len()];
- }
-
- Def::Err => {
- self.set_tainted_by_errors();
- segment_spaces = vec![None; segments.len()];
- }
+ Def::Upvar(..) |
+ Def::Err => {}
}
- assert_eq!(segment_spaces.len(), segments.len());
// In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
// `opt_self_ty` can also be Some for `Foo::method`, where Foo's
// type parameters are not mandatory.
let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none();
- debug!("segment_spaces={:?}", segment_spaces);
-
- // Next, examine the definition, and determine how many type
- // parameters we expect from each space.
- let type_defs = &type_scheme.generics.types;
- let region_defs = &type_scheme.generics.regions;
+ debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment);
// Now that we have categorized what space the parameters for each
// segment belong to, let's sort out the parameters that the user
// provided (if any) into their appropriate spaces. We'll also report
// errors if type parameters are provided in an inappropriate place.
- let mut substs = Substs::empty();
- for (&opt_space, segment) in segment_spaces.iter().zip(segments) {
- if let Some(space) = opt_space {
- self.push_explicit_parameters_from_segment_to_substs(space,
- span,
- type_defs,
- region_defs,
- segment,
- &mut substs);
- } else {
- self.tcx.prohibit_type_params(slice::ref_slice(segment));
- }
- }
- if let Some(self_ty) = opt_self_ty {
- if type_defs.len(subst::SelfSpace) == 1 {
- substs.types.push(subst::SelfSpace, self_ty);
+ let poly_segments = type_segment.is_some() as usize +
+ fn_segment.is_some() as usize;
+ self.tcx.prohibit_type_params(&segments[..segments.len() - poly_segments]);
+
+ match def {
+ Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => {
+ let ty = self.local_ty(span, nid);
+ let ty = self.normalize_associated_types_in(span, &ty);
+ self.write_ty(node_id, ty);
+ self.write_substs(node_id, ty::ItemSubsts {
+ substs: Substs::empty(self.tcx)
+ });
+ return ty;
}
+ _ => {}
}
// Now we have to compare the types that the user *actually*
// variables. If the user provided some types, we may still need
// to add defaults. If the user provided *too many* types, that's
// a problem.
- for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] {
- self.adjust_type_parameters(span, space, type_defs,
- require_type_space, &mut substs);
- assert_eq!(substs.types.len(space), type_defs.len(space));
+ self.check_path_parameter_count(span, !require_type_space, &mut type_segment);
+ self.check_path_parameter_count(span, true, &mut fn_segment);
+
+ let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| {
+ let mut i = def.index as usize;
+ let type_regions = match (type_segment, fn_segment) {
+ (_, Some((_, generics))) => generics.parent_regions as usize,
+ (Some((_, generics)), None) => generics.regions.len(),
+ (None, None) => 0
+ };
- self.adjust_region_parameters(span, space, region_defs, &mut substs);
- assert_eq!(substs.regions.len(space), region_defs.len(space));
- }
+ let segment = if i < type_regions {
+ type_segment
+ } else {
+ i -= type_regions;
+ fn_segment
+ };
+ let lifetimes = match segment.map(|(s, _)| &s.parameters) {
+ Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..],
+ Some(&hir::ParenthesizedParameters(_)) => bug!(),
+ None => &[]
+ };
+
+ if let Some(ast_lifetime) = lifetimes.get(i) {
+ ast_region_to_region(self.tcx, ast_lifetime)
+ } else {
+ self.region_var_for_def(span, def)
+ }
+ }, |def, substs| {
+ let mut i = def.index as usize;
+ let (type_types, has_self) = match (type_segment, fn_segment) {
+ (_, Some((_, generics))) => {
+ (generics.parent_types as usize, generics.has_self)
+ }
+ (Some((_, generics)), None) => {
+ (generics.types.len(), generics.has_self)
+ }
+ (None, None) => (0, false)
+ };
+
+ let can_omit = i >= type_types || !require_type_space;
+ let segment = if i < type_types {
+ // Handle Self first, so we can adjust the index to match the AST.
+ if has_self && i == 0 {
+ return opt_self_ty.unwrap_or_else(|| {
+ self.type_var_for_def(span, def, substs)
+ });
+ }
+ i -= has_self as usize;
+ type_segment
+ } else {
+ i -= type_types;
+ fn_segment
+ };
+ let types = match segment.map(|(s, _)| &s.parameters) {
+ Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..],
+ Some(&hir::ParenthesizedParameters(_)) => bug!(),
+ None => &[]
+ };
+
+ let omitted = can_omit && types.is_empty();
+ if let Some(ast_ty) = types.get(i) {
+ // A provided type parameter.
+ self.to_ty(ast_ty)
+ } else if let (false, Some(default)) = (omitted, def.default) {
+ // No type parameter provided, but a default exists.
+ default.subst_spanned(self.tcx, substs, Some(span))
+ } else {
+ // No type parameters were provided, we can infer all.
+ // This can also be reached in some error cases:
+ // We prefer to use inference variables instead of
+ // TyError to let type inference recover somewhat.
+ self.type_var_for_def(span, def, substs)
+ }
+ });
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
- let substs = self.tcx.mk_substs(substs);
- assert!(!substs.has_regions_escaping_depth(0));
- assert!(!type_scheme.has_escaping_regions());
+ let scheme = self.tcx.lookup_item_type(def.def_id());
+ let type_predicates = self.tcx.lookup_predicates(def.def_id());
+ assert!(!substs.has_escaping_regions());
+ assert!(!scheme.ty.has_escaping_regions());
// Add all the obligations that are required, substituting and
// normalized appropriately.
// Substitute the values for the type parameters into the type of
// the referenced item.
- let ty_substituted = self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
+ let ty_substituted = self.instantiate_type_scheme(span, &substs, &scheme.ty);
if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated {
// type parameters, which we can infer by unifying the provided `Self`
// with the substituted impl type.
let impl_scheme = self.tcx.lookup_item_type(impl_def_id);
- assert_eq!(substs.types.len(subst::TypeSpace),
- impl_scheme.generics.types.len(subst::TypeSpace));
- assert_eq!(substs.regions.len(subst::TypeSpace),
- impl_scheme.generics.regions.len(subst::TypeSpace));
let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) {
ty_substituted
}
- /// Finds the parameters that the user provided and adds them to `substs`. If too many
- /// parameters are provided, then reports an error and clears the output vector.
- ///
- /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to
- /// use inference variables. This seems less likely to lead to derived errors.
- ///
- /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults
- /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters
- /// here because we can easily use the precise span of the N+1'th parameter.
- fn push_explicit_parameters_from_segment_to_substs(&self,
- space: subst::ParamSpace,
- span: Span,
- type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
- region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
- segment: &hir::PathSegment,
- substs: &mut Substs<'tcx>)
- {
- match segment.parameters {
- hir::AngleBracketedParameters(ref data) => {
- self.push_explicit_angle_bracketed_parameters_from_segment_to_substs(
- space, type_defs, region_defs, data, substs);
+ /// Report errors if the provided parameters are too few or too many.
+ fn check_path_parameter_count(&self,
+ span: Span,
+ can_omit: bool,
+ segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
+ let (lifetimes, types, bindings) = match segment.map(|(s, _)| &s.parameters) {
+ Some(&hir::AngleBracketedParameters(ref data)) => {
+ (&data.lifetimes[..], &data.types[..], &data.bindings[..])
}
-
- hir::ParenthesizedParameters(ref data) => {
- span_err!(self.tcx.sess, span, E0238,
- "parenthesized parameters may only be used with a trait");
- self.push_explicit_parenthesized_parameters_from_segment_to_substs(
- space, span, type_defs, data, substs);
+ Some(&hir::ParenthesizedParameters(_)) => {
+ span_bug!(span, "parenthesized parameters cannot appear in ExprPath");
}
- }
- }
+ None => (&[][..], &[][..], &[][..])
+ };
- fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(&self,
- space: subst::ParamSpace,
- type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
- region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
- data: &hir::AngleBracketedParameterData,
- substs: &mut Substs<'tcx>)
- {
- {
- let type_count = type_defs.len(space);
- assert_eq!(substs.types.len(space), 0);
- for (i, typ) in data.types.iter().enumerate() {
- let t = self.to_ty(&typ);
- if i < type_count {
- substs.types.push(space, t);
- } else if i == type_count {
- struct_span_err!(self.tcx.sess, typ.span, E0087,
- "too many type parameters provided: \
- expected at most {} parameter{}, \
- found {} parameter{}",
- type_count,
- if type_count == 1 {""} else {"s"},
- data.types.len(),
- if data.types.len() == 1 {""} else {"s"})
- .span_label(typ.span , &format!("expected {} parameter{}",
- type_count,
- if type_count == 1 {""} else {"s"})).emit();
- substs.types.truncate(space, 0);
- break;
- }
- }
- }
+ let count = |n| {
+ format!("{} parameter{}", n, if n == 1 { "" } else { "s" })
+ };
- if !data.bindings.is_empty() {
- span_err!(self.tcx.sess, data.bindings[0].span, E0182,
- "unexpected binding of associated item in expression path \
- (only allowed in type paths)");
+ // Check provided lifetime parameters.
+ let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
+ if lifetimes.len() > lifetime_defs.len() {
+ let span = lifetimes[lifetime_defs.len()].span;
+ span_err!(self.tcx.sess, span, E0088,
+ "too many lifetime parameters provided: \
+ expected {}, found {}",
+ count(lifetime_defs.len()),
+ count(lifetimes.len()));
+ } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() {
+ span_err!(self.tcx.sess, span, E0090,
+ "too few lifetime parameters provided: \
+ expected {}, found {}",
+ count(lifetime_defs.len()),
+ count(lifetimes.len()));
}
- {
- let region_count = region_defs.len(space);
- assert_eq!(substs.regions.len(space), 0);
- for (i, lifetime) in data.lifetimes.iter().enumerate() {
- let r = ast_region_to_region(self.tcx, lifetime);
- if i < region_count {
- substs.regions.push(space, r);
- } else if i == region_count {
- span_err!(self.tcx.sess, lifetime.span, E0088,
- "too many lifetime parameters provided: \
- expected {} parameter{}, found {} parameter{}",
- region_count,
- if region_count == 1 {""} else {"s"},
- data.lifetimes.len(),
- if data.lifetimes.len() == 1 {""} else {"s"});
- substs.regions.truncate(space, 0);
- break;
- }
+ // Check provided type parameters.
+ let type_defs = segment.map_or(&[][..], |(_, generics)| {
+ if generics.parent.is_none() {
+ &generics.types[generics.has_self as usize..]
+ } else {
+ &generics.types
}
- }
- }
-
- /// As with
- /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`,
- /// but intended for `Foo(A,B) -> C` form. This expands to
- /// roughly the same thing as `Foo<(A,B),C>`. One important
- /// difference has to do with the treatment of anonymous
- /// regions, which are translated into bound regions (NYI).
- fn push_explicit_parenthesized_parameters_from_segment_to_substs(&self,
- space: subst::ParamSpace,
- span: Span,
- type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
- data: &hir::ParenthesizedParameterData,
- substs: &mut Substs<'tcx>)
- {
- let type_count = type_defs.len(space);
- if type_count < 2 {
- span_err!(self.tcx.sess, span, E0167,
- "parenthesized form always supplies 2 type parameters, \
- but only {} parameter(s) were expected",
- type_count);
- }
-
- let input_tys: Vec<Ty> =
- data.inputs.iter().map(|ty| self.to_ty(&ty)).collect();
-
- let tuple_ty = self.tcx.mk_tup(input_tys);
-
- if type_count >= 1 {
- substs.types.push(space, tuple_ty);
- }
-
- let output_ty: Option<Ty> =
- data.output.as_ref().map(|ty| self.to_ty(&ty));
-
- let output_ty =
- output_ty.unwrap_or(self.tcx.mk_nil());
-
- if type_count >= 2 {
- substs.types.push(space, output_ty);
- }
- }
-
- fn adjust_type_parameters(&self,
- span: Span,
- space: ParamSpace,
- defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
- require_type_space: bool,
- substs: &mut Substs<'tcx>)
- {
- let provided_len = substs.types.len(space);
- let desired = defs.get_slice(space);
- let required_len = desired.iter()
- .take_while(|d| d.default.is_none())
- .count();
-
- debug!("adjust_type_parameters(space={:?}, \
- provided_len={}, \
- desired_len={}, \
- required_len={})",
- space,
- provided_len,
- desired.len(),
- required_len);
-
- // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
- assert!(provided_len <= desired.len());
-
- // Nothing specified at all: supply inference variables for
- // everything.
- if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
- substs.types.replace(space, Vec::new());
- self.type_vars_for_defs(span, space, substs, &desired[..]);
- return;
- }
-
- // Too few parameters specified: report an error and use Err
- // for everything.
- if provided_len < required_len {
+ });
+ let required_len = type_defs.iter()
+ .take_while(|d| d.default.is_none())
+ .count();
+ if types.len() > type_defs.len() {
+ let span = types[type_defs.len()].span;
+ struct_span_err!(self.tcx.sess, span, E0087,
+ "too many type parameters provided: \
+ expected at most {}, found {}",
+ count(type_defs.len()),
+ count(types.len()))
+ .span_label(span, &format!("expected {}",
+ count(type_defs.len()))).emit();
+
+ // To prevent derived errors to accumulate due to extra
+ // type parameters, we force instantiate_value_path to
+ // use inference variables instead of the provided types.
+ *segment = None;
+ } else if !(can_omit && types.len() == 0) && types.len() < required_len {
let qualifier =
- if desired.len() != required_len { "at least " } else { "" };
+ if type_defs.len() != required_len { "at least " } else { "" };
span_err!(self.tcx.sess, span, E0089,
- "too few type parameters provided: expected {}{} parameter{}, \
- found {} parameter{}",
- qualifier, required_len,
- if required_len == 1 {""} else {"s"},
- provided_len,
- if provided_len == 1 {""} else {"s"});
- substs.types.replace(space, vec![self.tcx.types.err; desired.len()]);
- return;
- }
-
- // Otherwise, add in any optional parameters that the user
- // omitted. The case of *too many* parameters is handled
- // already by
- // push_explicit_parameters_from_segment_to_substs(). Note
- // that the *default* type are expressed in terms of all prior
- // parameters, so we have to substitute as we go with the
- // partial substitution that we have built up.
- for i in provided_len..desired.len() {
- let default = desired[i].default.unwrap();
- let default = default.subst_spanned(self.tcx, substs, Some(span));
- substs.types.push(space, default);
+ "too few type parameters provided: \
+ expected {}{}, found {}",
+ qualifier,
+ count(required_len),
+ count(types.len()));
}
- assert_eq!(substs.types.len(space), desired.len());
-
- debug!("Final substs: {:?}", substs);
- }
-
- fn adjust_region_parameters(&self,
- span: Span,
- space: ParamSpace,
- defs: &VecPerParamSpace<ty::RegionParameterDef>,
- substs: &mut Substs)
- {
- let provided_len = substs.regions.len(space);
- let desired = defs.get_slice(space);
- // Enforced by `push_explicit_parameters_from_segment_to_substs()`.
- assert!(provided_len <= desired.len());
-
- // If nothing was provided, just use inference variables.
- if provided_len == 0 {
- substs.regions.replace(
- space,
- self.region_vars_for_defs(span, desired));
- return;
- }
-
- // If just the right number were provided, everybody is happy.
- if provided_len == desired.len() {
- return;
+ if !bindings.is_empty() {
+ span_err!(self.tcx.sess, bindings[0].span, E0182,
+ "unexpected binding of associated item in expression path \
+ (only allowed in type paths)");
}
-
- // Otherwise, too few were provided. Report an error and then
- // use inference variables.
- span_err!(self.tcx.sess, span, E0090,
- "too few lifetime parameters provided: expected {} parameter{}, \
- found {} parameter{}",
- desired.len(),
- if desired.len() == 1 {""} else {"s"},
- provided_len,
- if provided_len == 1 {""} else {"s"});
-
- substs.regions.replace(
- space,
- self.region_vars_for_defs(span, desired));
}
fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
}
/*From:*/ (_,
- /*To: */ &ty::TyTrait(box ty::TraitTy { ref bounds, .. })) => {
+ /*To: */ &ty::TyTrait(ref obj)) => {
// When T is existentially quantified as a trait
// `Foo+'to`, it must outlive the region bound `'to`.
self.type_must_outlive(infer::RelateObjectBound(cast_expr.span),
- from_ty, bounds.region_bound);
+ from_ty, obj.region_bound);
}
/*From:*/ (&ty::TyBox(from_referent_ty),
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
- let needs_infer = {
- projection_ty.trait_ref.substs.types.iter().any(|t| t.needs_infer()) ||
- projection_ty.trait_ref.substs.regions.iter().any(|r| r.needs_infer())
- };
+ let needs_infer = projection_ty.trait_ref.needs_infer();
if env_bounds.is_empty() && needs_infer {
debug!("projection_must_outlive: no declared bounds");
//
// we can thus deduce that `<T as SomeTrait<'a>>::SomeType : 'a`.
let trait_predicates = self.tcx.lookup_predicates(projection_ty.trait_ref.def_id);
+ assert_eq!(trait_predicates.parent, None);
let predicates = trait_predicates.predicates.as_slice().to_vec();
traits::elaborate_predicates(self.tcx, predicates)
.filter_map(|predicate| {
use hir::def_id::DefId;
use middle::region::{CodeExtent};
use rustc::infer::TypeOrigin;
-use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt};
use std::collections::HashSet;
use syntax::ast;
-use syntax::parse::token::keywords;
use syntax_pos::Span;
use errors::DiagnosticBuilder;
let item_def_id = self.tcx().map.local_def_id(item.id);
let ty_predicates = self.tcx().lookup_predicates(item_def_id);
+ assert_eq!(ty_predicates.parent, None);
let variances = self.tcx().item_variances(item_def_id);
let mut constrained_parameters: HashSet<_> =
variances.types
- .iter_enumerated()
- .filter(|&(_, _, &variance)| variance != ty::Bivariant)
- .map(|(space, index, _)| self.param_ty(ast_generics, space, index))
+ .iter().enumerate()
+ .filter(|&(_, &variance)| variance != ty::Bivariant)
+ .map(|(index, _)| self.param_ty(ast_generics, index))
.map(|p| Parameter::Type(p))
.collect();
None,
&mut constrained_parameters);
- for (space, index, _) in variances.types.iter_enumerated() {
- let param_ty = self.param_ty(ast_generics, space, index);
+ for (index, _) in variances.types.iter().enumerate() {
+ let param_ty = self.param_ty(ast_generics, index);
if constrained_parameters.contains(&Parameter::Type(param_ty)) {
continue;
}
- let span = self.ty_param_span(ast_generics, item, space, index);
+ let span = ast_generics.ty_params[index].span;
self.report_bivariance(span, param_ty.name);
}
- for (space, index, &variance) in variances.regions.iter_enumerated() {
+ for (index, &variance) in variances.regions.iter().enumerate() {
if variance != ty::Bivariant {
continue;
}
- assert_eq!(space, TypeSpace);
let span = ast_generics.lifetimes[index].lifetime.span;
let name = ast_generics.lifetimes[index].lifetime.name;
self.report_bivariance(span, name);
}
}
- fn param_ty(&self,
- ast_generics: &hir::Generics,
- space: ParamSpace,
- index: usize)
- -> ty::ParamTy
- {
- let name = match space {
- TypeSpace => ast_generics.ty_params[index].name,
- SelfSpace => keywords::SelfType.name(),
- FnSpace => bug!("Fn space occupied?"),
- };
-
- ty::ParamTy { space: space, idx: index as u32, name: name }
- }
-
- fn ty_param_span(&self,
- ast_generics: &hir::Generics,
- item: &hir::Item,
- space: ParamSpace,
- index: usize)
- -> Span
- {
- match space {
- TypeSpace => ast_generics.ty_params[index].span,
- SelfSpace => item.span,
- FnSpace => span_bug!(item.span, "Fn space occupied?"),
+ fn param_ty(&self, ast_generics: &hir::Generics, index: usize) -> ty::ParamTy {
+ ty::ParamTy {
+ idx: index as u32,
+ name: ast_generics.ty_params[index].name
}
}
}
fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) {
- let impl_params = generics.types.get_slice(subst::TypeSpace).iter()
- .map(|tp| tp.name).collect::<HashSet<_>>();
+ let parent = tcx.lookup_generics(generics.parent.unwrap());
+ let impl_params: HashSet<_> = parent.types.iter().map(|tp| tp.name).collect();
- for method_param in generics.types.get_slice(subst::FnSpace) {
+ for method_param in &generics.types {
if impl_params.contains(&method_param.name) {
error_194(tcx, span, method_param.name);
}
// Trait impl: take implied bounds from all types that
// appear in the trait reference.
let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref);
- trait_ref.substs.types.as_slice().to_vec()
+ trait_ref.substs.types.to_vec()
}
None => {
use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
use rustc::ty::adjustment;
use rustc::ty::fold::{TypeFolder,TypeFoldable};
-use rustc::ty::subst::ParamSpace;
use rustc::infer::{InferCtxt, FixupError};
use rustc::util::nodemap::DefIdMap;
use write_substs_to_tcx;
wbcx.visit_closures();
wbcx.visit_liberated_fn_sigs();
wbcx.visit_fru_field_types();
- wbcx.visit_anon_types();
+ wbcx.visit_anon_types(item_id);
wbcx.visit_deferred_obligations(item_id);
}
}
}
let free_substs = fcx.parameter_environment.free_substs;
- for &space in &ParamSpace::all() {
- for (i, r) in free_substs.regions.get_slice(space).iter().enumerate() {
- match *r {
- ty::ReFree(ty::FreeRegion {
- bound_region: ty::BoundRegion::BrNamed(def_id, name, _), ..
- }) => {
- let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion {
- space: space,
- index: i as u32,
- name: name,
- });
- wbcx.free_to_bound_regions.insert(def_id, bound_region);
- }
- _ => {
- bug!("{:?} is not a free region for an early-bound lifetime", r);
- }
+ for (i, r) in free_substs.regions.iter().enumerate() {
+ match *r {
+ ty::ReFree(ty::FreeRegion {
+ bound_region: ty::BoundRegion::BrNamed(def_id, name, _), ..
+ }) => {
+ let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion {
+ index: i as u32,
+ name: name,
+ });
+ wbcx.free_to_bound_regions.insert(def_id, bound_region);
+ }
+ _ => {
+ bug!("{:?} is not a free region for an early-bound lifetime", r);
}
}
}
}
}
- fn visit_anon_types(&self) {
+ fn visit_anon_types(&self, item_id: ast::NodeId) {
if self.fcx.writeback_errors.get() {
return
}
+ let item_def_id = self.fcx.tcx.map.local_def_id(item_id);
+
let gcx = self.tcx().global_tcx();
for (&def_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() {
let reason = ResolvingAnonTy(def_id);
}
});
- gcx.tcache.borrow_mut().insert(def_id, ty::TypeScheme {
+ gcx.register_item_type(def_id, ty::TypeScheme {
ty: outside_ty,
- generics: ty::Generics::empty()
+ generics: gcx.lookup_generics(item_def_id)
});
}
}
use hir::def_id::DefId;
use middle::lang_items::UnsizeTraitLangItem;
-use rustc::ty::subst::{self, Subst};
+use rustc::ty::subst::Subst;
use rustc::ty::{self, TyCtxt, TypeFoldable};
use rustc::traits::{self, Reveal};
use rustc::ty::{ImplOrTraitItemId, ConstTraitItemId};
}
TyTrait(ref t) => {
- Some(t.principal_def_id())
+ Some(t.principal.def_id())
}
TyBox(_) => {
let source = tcx.lookup_item_type(impl_did).ty;
let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap();
- let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
+ let target = trait_ref.substs.types[1];
debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)",
source, target);
self.check_def_id(item, def.did);
}
ty::TyTrait(ref data) => {
- self.check_def_id(item, data.principal_def_id());
+ self.check_def_id(item, data.principal.def_id());
}
ty::TyBox(..) => {
match self.tcx.lang_items.require_owned_box() {
// This is something like impl Trait1 for Trait2. Illegal
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
- if !self.tcx.is_object_safe(data.principal_def_id()) {
+ if !self.tcx.is_object_safe(data.principal.def_id()) {
// This is an error, but it will be
// reported by wfcheck. Ignore it
// here. This is tested by
// `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
- traits::supertrait_def_ids(self.tcx, data.principal_def_id());
+ traits::supertrait_def_ids(self.tcx, data.principal.def_id());
if supertrait_def_ids.any(|d| d == trait_def_id) {
span_err!(self.tcx.sess, item.span, E0371,
"the object type `{}` automatically \
use middle::const_val::ConstVal;
use rustc_const_eval::EvalHint::UncheckedExprHint;
use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
-use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
+use rustc::ty::subst::Substs;
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
use rustc::ty::{VariantKind};
use syntax::{abi, ast, attr};
use syntax::parse::token::keywords;
-use syntax::ptr::P;
use syntax_pos::Span;
use rustc::hir::{self, intravisit, map as hir_map, print as pprust};
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum AstConvRequest {
+ GetGenerics(DefId),
GetItemTypeScheme(DefId),
GetTraitDef(DefId),
EnsureSuperPredicates(DefId),
err.span_label(span, &format!("cyclic reference"));
match cycle[0] {
+ AstConvRequest::GetGenerics(def_id) |
AstConvRequest::GetItemTypeScheme(def_id) |
AstConvRequest::GetTraitDef(def_id) => {
err.note(
for request in &cycle[1..] {
match *request {
+ AstConvRequest::GetGenerics(def_id) |
AstConvRequest::GetItemTypeScheme(def_id) |
AstConvRequest::GetTraitDef(def_id) => {
err.note(
}
match cycle[0] {
+ AstConvRequest::GetGenerics(def_id) |
AstConvRequest::GetItemTypeScheme(def_id) |
AstConvRequest::GetTraitDef(def_id) => {
err.note(
&self.ccx.ast_ty_to_ty_cache
}
+ fn get_generics(&self, span: Span, id: DefId)
+ -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
+ {
+ self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || {
+ Ok(generics_of_def_id(self.ccx, id))
+ })
+ }
+
fn get_item_type_scheme(&self, span: Span, id: DefId)
-> Result<ty::TypeScheme<'tcx>, ErrorReported>
{
None
}
- fn ty_infer(&self,
- _ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
- _substs: Option<&mut Substs<'tcx>>,
- _space: Option<ParamSpace>,
- span: Span) -> Ty<'tcx> {
+ fn ty_infer(&self, span: Span) -> Ty<'tcx> {
struct_span_err!(
self.tcx().sess,
span,
impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
fn get_type_parameter_bounds(&self,
astconv: &AstConv<'tcx, 'tcx>,
- _span: Span,
+ span: Span,
node_id: ast::NodeId)
-> Vec<ty::Predicate<'tcx>>
{
let def = astconv.tcx().type_parameter_def(node_id);
- self.predicates
- .iter()
- .filter(|predicate| {
- match **predicate {
- ty::Predicate::Trait(ref data) => {
- data.skip_binder().self_ty().is_param(def.space, def.index)
- }
- ty::Predicate::TypeOutlives(ref data) => {
- data.skip_binder().0.is_param(def.space, def.index)
- }
- ty::Predicate::Rfc1592(..) |
- ty::Predicate::Equate(..) |
- ty::Predicate::RegionOutlives(..) |
- ty::Predicate::WellFormed(..) |
- ty::Predicate::ObjectSafe(..) |
- ty::Predicate::ClosureKind(..) |
- ty::Predicate::Projection(..) => {
- false
- }
+ let mut results = self.parent.map_or(vec![], |def_id| {
+ let parent = astconv.tcx().lookup_predicates(def_id);
+ parent.get_type_parameter_bounds(astconv, span, node_id)
+ });
+
+ results.extend(self.predicates.iter().filter(|predicate| {
+ match **predicate {
+ ty::Predicate::Trait(ref data) => {
+ data.skip_binder().self_ty().is_param(def.index)
}
- })
- .cloned()
- .collect()
+ ty::Predicate::TypeOutlives(ref data) => {
+ data.skip_binder().0.is_param(def.index)
+ }
+ ty::Predicate::Rfc1592(..) |
+ ty::Predicate::Equate(..) |
+ ty::Predicate::RegionOutlives(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
+ ty::Predicate::ClosureKind(..) |
+ ty::Predicate::Projection(..) => {
+ false
+ }
+ }
+ }).cloned());
+
+ results
}
}
let path_res = tcx.expect_resolution(ast_ty.id);
match path_res.base_def {
Def::SelfTy(Some(def_id), None) |
- Def::TyParam(_, _, def_id, _) if path_res.depth == 0 => {
+ Def::TyParam(def_id) if path_res.depth == 0 => {
def_id == tcx.map.local_def_id(param_id)
}
_ => false
}
}
-
fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
container: ImplOrTraitItemContainer,
name: ast::Name,
sig: &hir::MethodSig,
defaultness: hir::Defaultness,
untransformed_rcvr_ty: Ty<'tcx>,
- rcvr_ty_generics: &ty::Generics<'tcx>,
rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
- let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics);
+ let def_id = ccx.tcx.map.local_def_id(id);
+ let ty_generics = generics_of_def_id(ccx, def_id);
let ty_generic_predicates =
- ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
+ ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false);
let (fty, explicit_self_category) = {
let anon_scope = match container {
- ImplContainer(_) => Some(AnonTypeScope::new(&ty_generics)),
+ ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
TraitContainer(_) => None
};
AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
sig, untransformed_rcvr_ty, anon_scope)
};
- let def_id = ccx.tcx.map.local_def_id(id);
- let substs = mk_item_substs(ccx.tcx, &ty_generics);
-
let ty_method = ty::Method::new(name,
ty_generics,
ty_generic_predicates,
def_id,
container);
+ let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
+ ccx.tcx.map.span(id), def_id);
let fty = ccx.tcx.mk_fn_def(def_id, substs, ty_method.fty);
debug!("method {} (id {}) has type {:?}",
name, id, fty);
- ccx.tcx.register_item_type(def_id, TypeScheme {
- generics: ty_method.generics.clone(),
- ty: fty
- });
- ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
-
+ ccx.tcx.tcache.borrow_mut().insert(def_id, fty);
write_ty_to_tcx(ccx, id, fty);
+ ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
debug!("writing method type: def_id={:?} mty={:?}",
def_id, ty_method);
}
fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- struct_generics: &ty::Generics<'tcx>,
+ struct_generics: &'tcx ty::Generics<'tcx>,
struct_predicates: &ty::GenericPredicates<'tcx>,
field: &hir::StructField,
ty_f: ty::FieldDefMaster<'tcx>)
/* add the field to the tcache */
ccx.tcx.register_item_type(ccx.tcx.map.local_def_id(field.id),
ty::TypeScheme {
- generics: struct_generics.clone(),
+ generics: struct_generics,
ty: tt
});
ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(field.id),
ty: ty::Ty<'tcx>,
has_value: bool)
{
+ let predicates = ty::GenericPredicates {
+ parent: Some(container.id()),
+ predicates: vec![]
+ };
ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
- ty::GenericPredicates::empty());
+ predicates);
write_ty_to_tcx(ccx, id, ty);
}
}
hir::ItemEnum(ref enum_definition, _) => {
- let (scheme, predicates) = convert_typed_item(ccx, it);
- write_ty_to_tcx(ccx, it.id, scheme.ty);
+ let def_id = ccx.tcx.map.local_def_id(it.id);
+ let scheme = type_scheme_of_def_id(ccx, def_id);
+ let predicates = predicates_of_item(ccx, it);
convert_enum_variant_types(ccx,
tcx.lookup_adt_def_master(ccx.tcx.map.local_def_id(it.id)),
scheme,
AstConv::instantiate_mono_trait_ref(&ccx.icx(&()),
&ExplicitRscope,
ast_trait_ref,
- None);
+ tcx.mk_self_type());
tcx.record_trait_has_default_impl(trait_ref.def_id);
// Create generics from the generics specified in the impl head.
debug!("convert: ast_generics={:?}", generics);
let def_id = ccx.tcx.map.local_def_id(it.id);
- let ty_generics = ty_generics_for_impl(ccx, generics);
- let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
+ let ty_generics = generics_of_def_id(ccx, def_id);
+ let mut ty_predicates =
+ ty_generic_predicates(ccx, generics, None, vec![], false);
debug!("convert: impl_bounds={:?}", ty_predicates);
write_ty_to_tcx(ccx, it.id, selfty);
tcx.register_item_type(def_id,
- TypeScheme { generics: ty_generics.clone(),
+ TypeScheme { generics: ty_generics,
ty: selfty });
let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| {
AstConv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
&ExplicitRscope,
ast_trait_ref,
- Some(selfty))
+ selfty)
});
tcx.impl_trait_refs.borrow_mut().insert(def_id, trait_ref);
}
if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node {
+ let const_def_id = ccx.tcx.map.local_def_id(impl_item.id);
+ let ty_generics = generics_of_def_id(ccx, const_def_id);
let ty = ccx.icx(&ty_predicates)
.to_ty(&ExplicitRscope, &ty);
- tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id),
+ tcx.register_item_type(const_def_id,
TypeScheme {
- generics: ty_generics.clone(),
+ generics: ty_generics,
ty: ty,
});
// Trait-associated constants are always public.
convert_method(ccx, ImplContainer(def_id),
impl_item.name, impl_item.id, method_vis,
- sig, impl_item.defaultness, selfty, &ty_generics,
+ sig, impl_item.defaultness, selfty,
&ty_predicates);
}
}
// Convert all the associated constants.
for trait_item in trait_items {
if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node {
+ let const_def_id = ccx.tcx.map.local_def_id(trait_item.id);
+ let ty_generics = generics_of_def_id(ccx, const_def_id);
let ty = ccx.icx(&trait_predicates)
.to_ty(&ExplicitRscope, ty);
- tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id),
+ tcx.register_item_type(const_def_id,
TypeScheme {
- generics: trait_def.generics.clone(),
+ generics: ty_generics,
ty: ty,
});
convert_associated_const(ccx,
sig,
hir::Defaultness::Default,
tcx.mk_self_type(),
- &trait_def.generics,
&trait_predicates);
}
trait_item_def_ids);
},
hir::ItemStruct(ref struct_def, _) => {
- let (scheme, predicates) = convert_typed_item(ccx, it);
- write_ty_to_tcx(ccx, it.id, scheme.ty);
+ let def_id = ccx.tcx.map.local_def_id(it.id);
+ let scheme = type_scheme_of_def_id(ccx, def_id);
+ let predicates = predicates_of_item(ccx, it);
- let it_def_id = ccx.tcx.map.local_def_id(it.id);
- let variant = tcx.lookup_adt_def_master(it_def_id).struct_variant();
+ let variant = tcx.lookup_adt_def_master(def_id).struct_variant();
for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) {
convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
},
hir::ItemTy(_, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
- let (scheme, _) = convert_typed_item(ccx, it);
- write_ty_to_tcx(ccx, it.id, scheme.ty);
+ let def_id = ccx.tcx.map.local_def_id(it.id);
+ type_scheme_of_def_id(ccx, def_id);
+ predicates_of_item(ccx, it);
},
_ => {
- // This call populates the type cache with the converted type
- // of the item in passing. All we have to do here is to write
- // it into the node type table.
- let (scheme, _) = convert_typed_item(ccx, it);
- write_ty_to_tcx(ccx, it.id, scheme.ty);
+ let def_id = ccx.tcx.map.local_def_id(it.id);
+ type_scheme_of_def_id(ccx, def_id);
+ predicates_of_item(ccx, it);
},
}
}
scheme: ty::TypeScheme<'tcx>,
predicates: ty::GenericPredicates<'tcx>) {
let tcx = ccx.tcx;
+ let def_id = tcx.map.local_def_id(ctor_id);
+ generics_of_def_id(ccx, def_id);
let ctor_ty = match variant.kind {
VariantKind::Unit | VariantKind::Struct => scheme.ty,
VariantKind::Tuple => {
.iter()
.map(|field| field.unsubst_ty())
.collect();
- let def_id = tcx.map.local_def_id(ctor_id);
- let substs = mk_item_substs(tcx, &scheme.generics);
+ let substs = mk_item_substs(&ccx.icx(&predicates),
+ ccx.tcx.map.span(ctor_id), def_id);
tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy {
unsafety: hir::Unsafety::Normal,
abi: abi::Abi::Rust,
}
};
write_ty_to_tcx(ccx, ctor_id, ctor_ty);
+ tcx.tcache.borrow_mut().insert(def_id, ctor_ty);
tcx.predicates.borrow_mut().insert(tcx.map.local_def_id(ctor_id), predicates);
- tcx.register_item_type(tcx.map.local_def_id(ctor_id),
- TypeScheme {
- generics: scheme.generics,
- ty: ctor_ty
- });
}
fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// generic types:
let trait_def = trait_def_of_item(ccx, item);
let self_predicate = ty::GenericPredicates {
- predicates: VecPerParamSpace::new(vec![],
- vec![trait_def.trait_ref.to_predicate()],
- vec![])
+ parent: None,
+ predicates: vec![trait_def.trait_ref.to_predicate()]
};
let scope = &(generics, &self_predicate);
// Combine the two lists to form the complete set of superbounds:
let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
let superpredicates = ty::GenericPredicates {
- predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
+ parent: None,
+ predicates: superbounds
};
debug!("superpredicates for trait {:?} = {:?}",
tcx.map.local_def_id(item.id),
}
let (unsafety, generics, items) = match it.node {
- hir::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
+ hir::ItemTrait(unsafety, ref generics, _, ref items) => {
+ (unsafety, generics, items)
+ }
_ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"),
};
err.emit();
}
- let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
-
- let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics);
+ let ty_generics = generics_of_def_id(ccx, def_id);
+ let substs = mk_item_substs(&ccx.icx(generics), it.span, def_id);
let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
match trait_item.node {
}
}).collect();
- let trait_ref = ty::TraitRef {
- def_id: def_id,
- substs: substs,
- };
-
+ let trait_ref = ty::TraitRef::new(def_id, substs);
let trait_def = ty::TraitDef::new(unsafety,
paren_sugar,
ty_generics,
trait_ref,
associated_type_names);
- return tcx.intern_trait_def(trait_def);
-
- fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- generics: &hir::Generics)
- -> Substs<'tcx>
- {
- let tcx = ccx.tcx;
-
- // Creates a no-op substitution for the trait's type parameters.
- let regions =
- generics.lifetimes
- .iter()
- .enumerate()
- .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
- space: TypeSpace,
- index: i as u32,
- name: def.lifetime.name
- }))
- .collect();
-
- // Start with the generics in the type parameters...
- let types: Vec<_> =
- generics.ty_params
- .iter()
- .enumerate()
- .map(|(i, def)| tcx.mk_param(TypeSpace,
- i as u32, def.name))
- .collect();
-
- // ...and also create the `Self` parameter.
- let self_ty = tcx.mk_self_type();
-
- Substs::new_trait(types, regions, self_ty)
- }
+ tcx.intern_trait_def(trait_def)
}
fn trait_defines_associated_type_named(ccx: &CrateCtxt,
// but to get the full set of predicates on a trait we need to add
// in the supertrait bounds and anything declared on the
// associated types.
- let mut base_predicates = super_predicates;
+ let mut base_predicates = super_predicates.predicates;
// Add in a predicate that `Self:Trait` (where `Trait` is the
// current trait). This is needed for builtin bounds.
let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate();
- base_predicates.predicates.push(SelfSpace, self_predicate);
+ base_predicates.push(self_predicate);
// add in the explicit where-clauses
let mut trait_predicates =
- ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
+ ty_generic_predicates(ccx, generics, None, base_predicates, true);
let assoc_predicates = predicates_for_associated_types(ccx,
generics,
&trait_predicates,
trait_def.trait_ref,
items);
- trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
+ trait_predicates.predicates.extend(assoc_predicates);
let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
assert!(prev_predicates.is_none());
}
}
-fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- def_id: DefId)
- -> ty::TypeScheme<'tcx>
-{
- if let Some(node_id) = ccx.tcx.map.as_local_node_id(def_id) {
- match ccx.tcx.map.find(node_id) {
- Some(hir_map::NodeItem(item)) => {
- type_scheme_of_item(ccx, &item)
+fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ def_id: DefId)
+ -> &'tcx ty::Generics<'tcx> {
+ let tcx = ccx.tcx;
+ let node_id = if let Some(id) = tcx.map.as_local_node_id(def_id) {
+ id
+ } else {
+ return tcx.lookup_generics(def_id);
+ };
+ tcx.generics.memoize(def_id, || {
+ use rustc::hir::map::*;
+ use rustc::hir::*;
+
+ let node = tcx.map.get(node_id);
+ let parent_def_id = match node {
+ NodeImplItem(_) |
+ NodeTraitItem(_) |
+ NodeVariant(_) |
+ NodeStructCtor(_) => {
+ let parent_id = tcx.map.get_parent(node_id);
+ Some(tcx.map.local_def_id(parent_id))
}
- Some(hir_map::NodeForeignItem(foreign_item)) => {
- let abi = ccx.tcx.map.get_foreign_abi(node_id);
- type_scheme_of_foreign_item(ccx, &foreign_item, abi)
+ _ => None
+ };
+
+ let mut opt_self = None;
+ let mut allow_defaults = false;
+
+ let no_generics = hir::Generics::empty();
+ let ast_generics = match node {
+ NodeTraitItem(item) => {
+ match item.node {
+ MethodTraitItem(ref sig, _) => &sig.generics,
+ _ => &no_generics
+ }
}
- x => {
- bug!("unexpected sort of node in get_item_type_scheme(): {:?}",
- x);
+
+ NodeImplItem(item) => {
+ match item.node {
+ ImplItemKind::Method(ref sig, _) => &sig.generics,
+ _ => &no_generics
+ }
}
+
+ NodeItem(item) => {
+ match item.node {
+ ItemFn(_, _, _, _, ref generics, _) |
+ ItemImpl(_, _, ref generics, _, _, _) => generics,
+
+ ItemTy(_, ref generics) |
+ ItemEnum(_, ref generics) |
+ ItemStruct(_, ref generics) => {
+ allow_defaults = true;
+ generics
+ }
+
+ ItemTrait(_, ref generics, _, _) => {
+ // Add in the self type parameter.
+ //
+ // Something of a hack: use the node id for the trait, also as
+ // the node id for the Self type parameter.
+ let param_id = item.id;
+
+ let parent = ccx.tcx.map.get_parent(param_id);
+
+ let def = ty::TypeParameterDef {
+ index: 0,
+ name: keywords::SelfType.name(),
+ def_id: tcx.map.local_def_id(param_id),
+ default_def_id: tcx.map.local_def_id(parent),
+ default: None,
+ object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
+ };
+ tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
+ opt_self = Some(def);
+
+ allow_defaults = true;
+ generics
+ }
+
+ _ => &no_generics
+ }
+ }
+
+ NodeForeignItem(item) => {
+ match item.node {
+ ForeignItemStatic(..) => &no_generics,
+ ForeignItemFn(_, ref generics) => generics
+ }
+ }
+
+ _ => &no_generics
+ };
+
+ let has_self = opt_self.is_some();
+ let mut parent_has_self = false;
+ let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| {
+ let generics = generics_of_def_id(ccx, def_id);
+ assert_eq!(generics.parent, None);
+ assert_eq!(generics.parent_regions, 0);
+ assert_eq!(generics.parent_types, 0);
+ assert_eq!(has_self, false);
+ parent_has_self = generics.has_self;
+ (generics.regions.len() as u32, generics.types.len() as u32)
+ });
+
+ let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics);
+ let regions = early_lifetimes.iter().enumerate().map(|(i, l)| {
+ ty::RegionParameterDef {
+ name: l.lifetime.name,
+ index: parent_regions + i as u32,
+ def_id: tcx.map.local_def_id(l.lifetime.id),
+ bounds: l.bounds.iter().map(|l| {
+ ast_region_to_region(tcx, l)
+ }).collect()
+ }
+ }).collect();
+
+ // Now create the real type parameters.
+ let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
+ let i = parent_types + has_self as u32 + i as u32;
+ get_or_create_type_parameter_def(ccx, ast_generics, i, p, allow_defaults)
+ });
+ let types: Vec<_> = opt_self.into_iter().chain(types).collect();
+
+ // Debugging aid.
+ if tcx.has_attr(def_id, "rustc_object_lifetime_default") {
+ let object_lifetime_default_reprs: String =
+ types.iter().map(|t| {
+ match t.object_lifetime_default {
+ ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
+ d => format!("{:?}", d),
+ }
+ }).collect::<Vec<String>>().join(",");
+ tcx.sess.span_err(tcx.map.span(node_id), &object_lifetime_default_reprs);
}
- } else {
- ccx.tcx.lookup_item_type(def_id)
- }
+
+ tcx.alloc_generics(ty::Generics {
+ parent: parent_def_id,
+ parent_regions: parent_regions as u32,
+ parent_types: parent_types as u32,
+ regions: regions,
+ types: types,
+ has_self: has_self || parent_has_self
+ })
+ })
}
-fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- item: &hir::Item)
- -> ty::TypeScheme<'tcx>
-{
- let item_def_id = ccx.tcx.map.local_def_id(item.id);
- ccx.tcx.tcache.memoize(item_def_id, || {
- // NB. Since the `memoized` function enters a new task, and we
- // are giving this task access to the item `item`, we must
- // register a read.
- assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id));
- ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id));
- compute_type_scheme_of_item(ccx, item)
+fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+ def_id: DefId)
+ -> Ty<'tcx> {
+ let node_id = if let Some(id) = ccx.tcx.map.as_local_node_id(def_id) {
+ id
+ } else {
+ return ccx.tcx.lookup_item_type(def_id).ty;
+ };
+ ccx.tcx.tcache.memoize(def_id, || {
+ use rustc::hir::map::*;
+ use rustc::hir::*;
+
+ let ty = match ccx.tcx.map.get(node_id) {
+ NodeItem(item) => {
+ match item.node {
+ ItemStatic(ref t, _, _) | ItemConst(ref t, _) => {
+ ccx.icx(&()).to_ty(&ExplicitRscope, &t)
+ }
+ ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
+ let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
+ Some(AnonTypeScope::new(def_id)));
+ let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
+ ccx.tcx.mk_fn_def(def_id, substs, tofd)
+ }
+ ItemTy(ref t, ref generics) => {
+ ccx.icx(generics).to_ty(&ExplicitRscope, &t)
+ }
+ ItemEnum(ref ei, ref generics) => {
+ let def = convert_enum_def(ccx, item, ei);
+ let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
+ ccx.tcx.mk_enum(def, substs)
+ }
+ ItemStruct(ref si, ref generics) => {
+ let def = convert_struct_def(ccx, item, si);
+ let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
+ ccx.tcx.mk_struct(def, substs)
+ }
+ ItemDefaultImpl(..) |
+ ItemTrait(..) |
+ ItemImpl(..) |
+ ItemMod(..) |
+ ItemForeignMod(..) |
+ ItemExternCrate(..) |
+ ItemUse(..) => {
+ span_bug!(
+ item.span,
+ "compute_type_of_item: unexpected item type: {:?}",
+ item.node);
+ }
+ }
+ }
+ NodeForeignItem(foreign_item) => {
+ let abi = ccx.tcx.map.get_foreign_abi(node_id);
+
+ match foreign_item.node {
+ ForeignItemFn(ref fn_decl, ref generics) => {
+ compute_type_of_foreign_fn_decl(
+ ccx, ccx.tcx.map.local_def_id(foreign_item.id),
+ fn_decl, generics, abi)
+ }
+ ForeignItemStatic(ref t, _) => {
+ ccx.icx(&()).to_ty(&ExplicitRscope, t)
+ }
+ }
+ }
+ x => {
+ bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
+ }
+ };
+
+ write_ty_to_tcx(ccx, node_id, ty);
+ ty
})
}
-fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- it: &hir::Item)
- -> ty::TypeScheme<'tcx>
-{
- let tcx = ccx.tcx;
- match it.node {
- hir::ItemStatic(ref t, _, _) | hir::ItemConst(ref t, _) => {
- let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &t);
- ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
- }
- hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
- let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
- let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
- Some(AnonTypeScope::new(&ty_generics)));
- let def_id = ccx.tcx.map.local_def_id(it.id);
- let substs = mk_item_substs(tcx, &ty_generics);
- let ty = tcx.mk_fn_def(def_id, substs, tofd);
- ty::TypeScheme { ty: ty, generics: ty_generics }
- }
- hir::ItemTy(ref t, ref generics) => {
- let ty_generics = ty_generics_for_type(ccx, generics);
- let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &t);
- ty::TypeScheme { ty: ty, generics: ty_generics }
- }
- hir::ItemEnum(ref ei, ref generics) => {
- let def = convert_enum_def(ccx, it, ei);
- let ty_generics = ty_generics_for_type(ccx, generics);
- let substs = mk_item_substs(tcx, &ty_generics);
- let t = tcx.mk_enum(def, substs);
- ty::TypeScheme { ty: t, generics: ty_generics }
- }
- hir::ItemStruct(ref si, ref generics) => {
- let def = convert_struct_def(ccx, it, si);
- let ty_generics = ty_generics_for_type(ccx, generics);
- let substs = mk_item_substs(tcx, &ty_generics);
- let t = tcx.mk_struct(def, substs);
- ty::TypeScheme { ty: t, generics: ty_generics }
- }
- hir::ItemDefaultImpl(..) |
- hir::ItemTrait(..) |
- hir::ItemImpl(..) |
- hir::ItemMod(..) |
- hir::ItemForeignMod(..) |
- hir::ItemExternCrate(..) |
- hir::ItemUse(..) => {
- span_bug!(
- it.span,
- "compute_type_scheme_of_item: unexpected item type: {:?}",
- it.node);
+fn type_scheme_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+ def_id: DefId)
+ -> ty::TypeScheme<'tcx> {
+ if def_id.is_local() {
+ ty::TypeScheme {
+ generics: generics_of_def_id(ccx, def_id),
+ ty: type_of_def_id(ccx, def_id)
}
+ } else {
+ ccx.tcx.lookup_item_type(def_id)
}
}
-fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
it: &hir::Item)
- -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
-{
- let tcx = ccx.tcx;
+ -> ty::GenericPredicates<'tcx> {
+ let def_id = ccx.tcx.map.local_def_id(it.id);
- let tag = type_scheme_of_item(ccx, it);
- let scheme = TypeScheme { generics: tag.generics, ty: tag.ty };
- let predicates = match it.node {
- hir::ItemStatic(..) | hir::ItemConst(..) => {
- ty::GenericPredicates::empty()
- }
- hir::ItemFn(_, _, _, _, ref ast_generics, _) => {
- ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
- }
- hir::ItemTy(_, ref generics) => {
- ty_generic_predicates_for_type_or_impl(ccx, generics)
- }
- hir::ItemEnum(_, ref generics) => {
- ty_generic_predicates_for_type_or_impl(ccx, generics)
- }
- hir::ItemStruct(_, ref generics) => {
- ty_generic_predicates_for_type_or_impl(ccx, generics)
- }
- hir::ItemDefaultImpl(..) |
- hir::ItemTrait(..) |
- hir::ItemExternCrate(..) |
- hir::ItemUse(..) |
- hir::ItemImpl(..) |
- hir::ItemMod(..) |
- hir::ItemForeignMod(..) => {
- span_bug!(
- it.span,
- "compute_type_scheme_of_item: unexpected item type: {:?}",
- it.node);
- }
+ let no_generics = hir::Generics::empty();
+ let generics = match it.node {
+ hir::ItemFn(_, _, _, _, ref generics, _) |
+ hir::ItemTy(_, ref generics) |
+ hir::ItemEnum(_, ref generics) |
+ hir::ItemStruct(_, ref generics) => generics,
+ _ => &no_generics
};
- let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
- predicates.clone());
+ let predicates = ty_generic_predicates(ccx, generics, None, vec![], false);
+ let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id,
+ predicates.clone());
assert!(prev_predicates.is_none());
- // Debugging aid.
- if tcx.has_attr(ccx.tcx.map.local_def_id(it.id), "rustc_object_lifetime_default") {
- let object_lifetime_default_reprs: String =
- scheme.generics.types.iter()
- .map(|t| match t.object_lifetime_default {
- ty::ObjectLifetimeDefault::Specific(r) => r.to_string(),
- d => format!("{:?}", d),
- })
- .collect::<Vec<String>>()
- .join(",");
-
- tcx.sess.span_err(it.span, &object_lifetime_default_reprs);
- }
-
- return (scheme, predicates);
-}
-
-fn type_scheme_of_foreign_item<'a, 'tcx>(
- ccx: &CrateCtxt<'a, 'tcx>,
- item: &hir::ForeignItem,
- abi: abi::Abi)
- -> ty::TypeScheme<'tcx>
-{
- let item_def_id = ccx.tcx.map.local_def_id(item.id);
- ccx.tcx.tcache.memoize(item_def_id, || {
- // NB. Since the `memoized` function enters a new task, and we
- // are giving this task access to the item `item`, we must
- // register a read.
- assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id));
- ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id));
- compute_type_scheme_of_foreign_item(ccx, item, abi)
- })
-}
-
-fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
- ccx: &CrateCtxt<'a, 'tcx>,
- it: &hir::ForeignItem,
- abi: abi::Abi)
- -> ty::TypeScheme<'tcx>
-{
- match it.node {
- hir::ForeignItemFn(ref fn_decl, ref generics) => {
- compute_type_scheme_of_foreign_fn_decl(
- ccx, ccx.tcx.map.local_def_id(it.id),
- fn_decl, generics, abi)
- }
- hir::ForeignItemStatic(ref t, _) => {
- ty::TypeScheme {
- generics: ty::Generics::empty(),
- ty: AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
- }
- }
- }
+ predicates
}
fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// map, and I regard each time that I use it as a personal and
// moral failing, but at the moment it seems like the only
// convenient way to extract the ABI. - ndm
- let tcx = ccx.tcx;
- let abi = tcx.map.get_foreign_abi(it.id);
-
- let scheme = type_scheme_of_foreign_item(ccx, it, abi);
- write_ty_to_tcx(ccx, it.id, scheme.ty);
+ let def_id = ccx.tcx.map.local_def_id(it.id);
+ type_scheme_of_def_id(ccx, def_id);
- let predicates = match it.node {
- hir::ForeignItemFn(_, ref generics) => {
- ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
- }
- hir::ForeignItemStatic(..) => {
- ty::GenericPredicates::empty()
- }
+ let no_generics = hir::Generics::empty();
+ let generics = match it.node {
+ hir::ForeignItemFn(_, ref generics) => generics,
+ hir::ForeignItemStatic(..) => &no_generics
};
- let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
- predicates);
+ let predicates = ty_generic_predicates(ccx, generics, None, vec![], false);
+ let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
assert!(prev_predicates.is_none());
}
-fn ty_generics_for_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &hir::Generics)
- -> ty::Generics<'tcx> {
- ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty(), true)
-}
-
-fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &hir::Generics)
- -> ty::Generics<'tcx> {
- ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty(), false)
-}
-
-fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- generics: &hir::Generics)
- -> ty::GenericPredicates<'tcx>
-{
- ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
-}
-
-fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- trait_id: ast::NodeId,
- substs: &'tcx Substs<'tcx>,
- ast_generics: &hir::Generics)
- -> ty::Generics<'tcx>
-{
- debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
- ccx.tcx.map.local_def_id(trait_id), substs);
-
- let mut generics = ty_generics_for_type(ccx, ast_generics);
-
- // Add in the self type parameter.
- //
- // Something of a hack: use the node id for the trait, also as
- // the node id for the Self type parameter.
- let param_id = trait_id;
-
- let parent = ccx.tcx.map.get_parent(param_id);
-
- let def = ty::TypeParameterDef {
- space: SelfSpace,
- index: 0,
- name: keywords::SelfType.name(),
- def_id: ccx.tcx.map.local_def_id(param_id),
- default_def_id: ccx.tcx.map.local_def_id(parent),
- default: None,
- object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
- };
-
- ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
-
- generics.types.push(SelfSpace, def);
-
- return generics;
-}
-
-fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- generics: &hir::Generics,
- base_generics: &ty::Generics<'tcx>)
- -> ty::Generics<'tcx>
-{
- ty_generics(ccx, FnSpace, generics, base_generics, false)
-}
-
-fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- generics: &hir::Generics,
- base_predicates: &ty::GenericPredicates<'tcx>)
- -> ty::GenericPredicates<'tcx>
-{
- ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
-}
-
// Add the Sized bound, unless the type parameter is marked as `?Sized`.
fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
bounds: &mut ty::BuiltinBounds,
}
fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- space: ParamSpace,
ast_generics: &hir::Generics,
- base_predicates: &ty::GenericPredicates<'tcx>)
+ parent: Option<DefId>,
+ super_predicates: Vec<ty::Predicate<'tcx>>,
+ has_self: bool)
-> ty::GenericPredicates<'tcx>
{
let tcx = ccx.tcx;
- let mut result = base_predicates.clone();
+ let (parent_regions, parent_types) = parent.map_or((0, 0), |def_id| {
+ let generics = generics_of_def_id(ccx, def_id);
+ assert_eq!(generics.parent, None);
+ assert_eq!(generics.parent_regions, 0);
+ assert_eq!(generics.parent_types, 0);
+ (generics.regions.len() as u32, generics.types.len() as u32)
+ });
+ let ref base_predicates = match parent {
+ Some(def_id) => {
+ assert_eq!(super_predicates, vec![]);
+ tcx.lookup_predicates(def_id)
+ }
+ None => {
+ ty::GenericPredicates {
+ parent: None,
+ predicates: super_predicates.clone()
+ }
+ }
+ };
+ let mut predicates = super_predicates;
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`).
for (index, param) in ast_generics.ty_params.iter().enumerate() {
- let index = index as u32;
- let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx);
+ let index = parent_types + has_self as u32 + index as u32;
+ let param_ty = ty::ParamTy::new(index, param.name).to_ty(ccx.tcx);
let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
param_ty,
¶m.bounds,
SizedByDefault::Yes,
None,
param.span);
- let predicates = bounds.predicates(ccx.tcx, param_ty);
- result.predicates.extend(space, predicates.into_iter());
+ predicates.extend(bounds.predicates(ccx.tcx, param_ty));
}
// Collect the region predicates that were declared inline as
// have to be careful to only iterate over early-bound regions.
let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics);
for (index, param) in early_lifetimes.iter().enumerate() {
- let index = index as u32;
+ let index = parent_regions + index as u32;
let region =
ty::ReEarlyBound(ty::EarlyBoundRegion {
- space: space,
index: index,
name: param.lifetime.name
});
for bound in ¶m.bounds {
let bound_region = ast_region_to_region(ccx.tcx, bound);
let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
- result.predicates.push(space, outlives.to_predicate());
+ predicates.push(outlives.to_predicate());
}
}
let mut projections = Vec::new();
let trait_ref =
- conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
- ty,
- poly_trait_ref,
- &mut projections);
+ AstConv::instantiate_poly_trait_ref(&ccx.icx(&(base_predicates,
+ ast_generics)),
+ &ExplicitRscope,
+ poly_trait_ref,
+ ty,
+ &mut projections);
- result.predicates.push(space, trait_ref.to_predicate());
+ predicates.push(trait_ref.to_predicate());
for projection in &projections {
- result.predicates.push(space, projection.to_predicate());
+ predicates.push(projection.to_predicate());
}
}
&hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
let region = ast_region_to_region(tcx, lifetime);
let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
- result.predicates.push(space, ty::Predicate::TypeOutlives(pred))
+ predicates.push(ty::Predicate::TypeOutlives(pred))
}
}
}
for bound in ®ion_pred.bounds {
let r2 = ast_region_to_region(tcx, bound);
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
- result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
+ predicates.push(ty::Predicate::RegionOutlives(pred))
}
}
}
}
- return result;
-}
-
-fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
- space: ParamSpace,
- ast_generics: &hir::Generics,
- base_generics: &ty::Generics<'tcx>,
- allow_defaults: bool)
- -> ty::Generics<'tcx>
-{
- let tcx = ccx.tcx;
- let mut result = base_generics.clone();
-
- let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics);
- for (i, l) in early_lifetimes.iter().enumerate() {
- let bounds = l.bounds.iter()
- .map(|l| ast_region_to_region(tcx, l))
- .collect();
- let def = ty::RegionParameterDef { name: l.lifetime.name,
- space: space,
- index: i as u32,
- def_id: ccx.tcx.map.local_def_id(l.lifetime.id),
- bounds: bounds };
- result.regions.push(space, def);
+ ty::GenericPredicates {
+ parent: parent,
+ predicates: predicates
}
-
- assert!(result.types.is_empty_in(space));
-
- // Now create the real type parameters.
- for i in 0..ast_generics.ty_params.len() {
- let def =
- get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults);
- debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
- result.types.push(space, def);
- }
-
- result
-}
-
-fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- path: &P<hir::Ty>,
- space: ParamSpace,
- index: u32)
- -> Ty<'tcx>
-{
- let ty = AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path);
-
- for leaf_ty in ty.walk() {
- if let ty::TyParam(p) = leaf_ty.sty {
- if p.space == space && p.idx >= index {
- struct_span_err!(ccx.tcx.sess, path.span, E0128,
- "type parameters with a default cannot use \
- forward declared identifiers")
- .span_label(path.span, &format!("defaulted type parameters \
- cannot be forward declared"))
- .emit();
-
- return ccx.tcx.types.err
- }
- }
- }
-
- ty
}
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
ast_generics: &hir::Generics,
- space: ParamSpace,
index: u32,
+ param: &hir::TyParam,
allow_defaults: bool)
-> ty::TypeParameterDef<'tcx>
{
- let param = &ast_generics.ty_params[index as usize];
-
let tcx = ccx.tcx;
match tcx.ty_param_defs.borrow().get(¶m.id) {
Some(d) => { return d.clone(); }
None => { }
}
- let default = param.default.as_ref().map(
- |def| convert_default_type_parameter(ccx, def, space, index)
- );
+ let default =
+ param.default.as_ref().map(|def| ccx.icx(&()).to_ty(&ExplicitRscope, def));
let object_lifetime_default =
compute_object_lifetime_default(ccx, param.id,
}
let def = ty::TypeParameterDef {
- space: space,
index: index,
name: param.name,
def_id: ccx.tcx.map.local_def_id(param.id),
object_lifetime_default: object_lifetime_default,
};
+ if def.name == keywords::SelfType.name() {
+ span_bug!(param.span, "`Self` should not be the name of a regular parameter");
+ }
+
tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
+ debug!("get_or_create_type_parameter_def: def for type param: {:?}", def);
+
def
}
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
astconv.instantiate_poly_trait_ref(&rscope,
bound,
- Some(param_ty),
+ param_ty,
&mut projection_bounds)
}).collect();
match *bound {
hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => {
let mut projections = Vec::new();
- let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
+ let pred = astconv.instantiate_poly_trait_ref(&ExplicitRscope,
+ tr,
+ param_ty,
+ &mut projections);
projections.into_iter()
.map(|p| p.to_predicate())
.chain(Some(pred.to_predicate()))
}
}
-fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
- param_ty: Ty<'tcx>,
- trait_ref: &hir::PolyTraitRef,
- projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
- -> ty::PolyTraitRef<'tcx>
-{
- AstConv::instantiate_poly_trait_ref(astconv,
- &ExplicitRscope,
- trait_ref,
- Some(param_ty),
- projections)
-}
-
-fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
+fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
ccx: &CrateCtxt<'a, 'tcx>,
- id: DefId,
+ def_id: DefId,
decl: &hir::FnDecl,
ast_generics: &hir::Generics,
abi: abi::Abi)
- -> ty::TypeScheme<'tcx>
+ -> Ty<'tcx>
{
- let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
-
let rb = BindingRscope::new();
let input_tys = decl.inputs
.iter()
}
}
- let substs = mk_item_substs(ccx.tcx, &ty_generics);
- let t_fn = ccx.tcx.mk_fn_def(id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy {
+ let id = ccx.tcx.map.as_local_node_id(def_id).unwrap();
+ let substs = mk_item_substs(&ccx.icx(ast_generics), ccx.tcx.map.span(id), def_id);
+ ccx.tcx.mk_fn_def(def_id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy {
abi: abi,
unsafety: hir::Unsafety::Unsafe,
sig: ty::Binder(ty::FnSig {inputs: input_tys,
output: output,
variadic: decl.variadic}),
- }));
-
- ty::TypeScheme {
- generics: ty_generics,
- ty: t_fn
- }
+ }))
}
-pub fn mk_item_substs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- ty_generics: &ty::Generics)
- -> &'tcx Substs<'tcx>
-{
- let types =
- ty_generics.types.map(
- |def| tcx.mk_param_from_def(def));
-
- let regions =
- ty_generics.regions.map(
- |def| def.to_early_bound_region());
+pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+ span: Span,
+ def_id: DefId)
+ -> &'tcx Substs<'tcx> {
+ let tcx = astconv.tcx();
+ // FIXME(eddyb) Do this request from Substs::for_item in librustc.
+ if let Err(ErrorReported) = astconv.get_generics(span, def_id) {
+ // No convenient way to recover from a cycle here. Just bail. Sorry!
+ tcx.sess.abort_if_errors();
+ bug!("ErrorReported returned, but no errors reports?")
+ }
- tcx.mk_substs(Substs::new(types, regions))
+ Substs::for_item(tcx, def_id,
+ |def, _| def.to_early_bound_region(),
+ |def, _| tcx.mk_param_from_def(def))
}
/// Checks that all the type parameters on an impl
fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
- ast_generics: &hir::Generics,
+ generics: &hir::Generics,
impl_predicates: &mut ty::GenericPredicates<'tcx>,
impl_def_id: DefId)
{
let impl_scheme = ccx.tcx.lookup_item_type(impl_def_id);
let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id);
- assert!(impl_predicates.predicates.is_empty_in(FnSpace));
- assert!(impl_predicates.predicates.is_empty_in(SelfSpace));
-
// The trait reference is an input, so find all type parameters
// reachable from there, to start (if this is an inherent impl,
// then just examine the self type).
input_parameters.extend(ctp::parameters_for(trait_ref, false));
}
- ctp::setup_constraining_predicates(impl_predicates.predicates.get_mut_slice(TypeSpace),
+ ctp::setup_constraining_predicates(&mut impl_predicates.predicates,
impl_trait_ref,
&mut input_parameters);
- for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
- let param_ty = ty::ParamTy { space: TypeSpace,
- idx: index as u32,
- name: ty_param.name };
+ let ty_generics = generics_of_def_id(ccx, impl_def_id);
+ for (ty_param, param) in ty_generics.types.iter().zip(&generics.ty_params) {
+ let param_ty = ty::ParamTy::for_def(ty_param);
if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
- report_unused_parameter(ccx, ty_param.span, "type", ¶m_ty.to_string());
+ report_unused_parameter(ccx, param.span, "type", ¶m_ty.to_string());
}
}
}
.collect();
for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
- let region = ty::EarlyBoundRegion { space: TypeSpace,
- index: index as u32,
- name: lifetime_def.lifetime.name };
+ let region = ty::EarlyBoundRegion {
+ index: index as u32,
+ name: lifetime_def.lifetime.name
+ };
if
lifetimes_in_associated_types.contains(®ion) && // (*)
!input_parameters.contains(&ctp::Parameter::Region(region))
// E0141,
// E0159, // use of trait `{}` as struct constructor
// E0163, // merged into E0071
- E0167,
+// E0167,
// E0168,
// E0173, // manual implementations of unboxed closure traits are experimental
// E0174,
// E0235, // structure constructor specifies a structure of type but
// E0236, // no lang item for range syntax
// E0237, // no lang item for range syntax
- E0238, // parenthesized parameters may only be used with a trait
+// E0238, // parenthesized parameters may only be used with a trait
// E0239, // `next` method of `Iterator` trait has unexpected type
// E0240,
// E0241,
pub mod variance;
pub struct TypeAndSubsts<'tcx> {
- pub substs: Substs<'tcx>,
+ pub substs: &'tcx Substs<'tcx>,
pub ty: Ty<'tcx>,
}
_ => ()
}
let main_def_id = tcx.map.local_def_id(main_id);
- let substs = tcx.mk_substs(Substs::empty());
+ let substs = Substs::empty(tcx);
let se_ty = tcx.mk_fn_def(main_def_id, substs,
tcx.mk_bare_fn(ty::BareFnTy {
unsafety: hir::Unsafety::Normal,
}
let start_def_id = ccx.tcx.map.local_def_id(start_id);
- let substs = tcx.mk_substs(Substs::empty());
+ let substs = Substs::empty(tcx);
let se_ty = tcx.mk_fn_def(start_def_id, substs,
tcx.mk_bare_fn(ty::BareFnTy {
unsafety: hir::Unsafety::Normal,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use rustc::ty::{self, TyCtxt};
+use rustc::hir::def_id::DefId;
+use rustc::ty;
use rustc::ty::subst::Substs;
+use astconv::AstConv;
+
use std::cell::Cell;
use syntax_pos::Span;
}
#[derive(Copy, Clone)]
-pub struct AnonTypeScope<'a> {
- generics: &'a ty::Generics<'a>
+pub struct AnonTypeScope {
+ enclosing_item: DefId
}
-impl<'a, 'b, 'gcx, 'tcx> AnonTypeScope<'a> {
- pub fn new(generics: &'a ty::Generics<'a>) -> AnonTypeScope<'a> {
+impl<'gcx: 'tcx, 'tcx> AnonTypeScope {
+ pub fn new(enclosing_item: DefId) -> AnonTypeScope {
AnonTypeScope {
- generics: generics
+ enclosing_item: enclosing_item
}
}
- pub fn fresh_substs(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> {
+ pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span)
+ -> &'tcx Substs<'tcx> {
use collect::mk_item_substs;
- mk_item_substs(tcx, self.generics)
+ mk_item_substs(astconv, span, self.enclosing_item)
}
}
/// A scope wrapper which optionally allows anonymized types.
#[derive(Copy, Clone)]
-pub struct MaybeWithAnonTypes<'a, R> {
+pub struct MaybeWithAnonTypes<R> {
base_scope: R,
- anon_scope: Option<AnonTypeScope<'a>>
+ anon_scope: Option<AnonTypeScope>
}
-impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R> {
- pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope<'a>>) -> Self {
+impl<R: RegionScope> MaybeWithAnonTypes<R> {
+ pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope>) -> Self {
MaybeWithAnonTypes {
base_scope: base_scope,
anon_scope: anon_scope
}
}
-impl<'a, R: RegionScope> RegionScope for MaybeWithAnonTypes<'a, R> {
+impl<R: RegionScope> RegionScope for MaybeWithAnonTypes<R> {
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
self.base_scope.object_lifetime_default(span)
}
use dep_graph::DepTrackingMapConfig;
use hir::def_id::DefId;
use middle::resolve_lifetime as rl;
-use rustc::ty::subst;
-use rustc::ty::subst::ParamSpace;
+use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::maps::ItemVariances;
use rustc::hir::map as hir_map;
let tcx = self.terms_cx.tcx;
assert!(is_lifetime(&tcx.map, param_id));
match tcx.named_region_map.defs.get(¶m_id) {
- Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id))
+ Some(&rl::DefEarlyBoundRegion(_, lifetime_decl_id))
=> lifetime_decl_id,
Some(_) => bug!("should not encounter non early-bound cases"),
param_def_id: DefId,
item_def_id: DefId,
kind: ParamKind,
- space: ParamSpace,
index: usize)
-> VarianceTermPtr<'a> {
assert_eq!(param_def_id.krate, item_def_id.krate);
// variance already inferred, just look it up.
let variances = self.tcx().item_variances(item_def_id);
let variance = match kind {
- TypeParam => *variances.types.get(space, index),
- RegionParam => *variances.regions.get(space, index),
+ TypeParam => variances.types[index],
+ RegionParam => variances.regions[index],
};
self.constant_term(variance)
}
self.add_constraints_from_substs(
generics,
trait_ref.def_id,
- trait_def.generics.types.as_slice(),
- trait_def.generics.regions.as_slice(),
+ &trait_def.generics.types,
+ &trait_def.generics.regions,
trait_ref.substs,
variance);
}
// README.md for a discussion on dep-graph management.
self.tcx().dep_graph.read(ItemVariances::to_dep_node(&def.did));
- // All type parameters on enums and structs should be
- // in the TypeSpace.
- assert!(item_type.generics.types.is_empty_in(subst::SelfSpace));
- assert!(item_type.generics.types.is_empty_in(subst::FnSpace));
- assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace));
- assert!(item_type.generics.regions.is_empty_in(subst::FnSpace));
-
self.add_constraints_from_substs(
generics,
def.did,
- item_type.generics.types.get_slice(subst::TypeSpace),
- item_type.generics.regions.get_slice(subst::TypeSpace),
+ &item_type.generics.types,
+ &item_type.generics.regions,
substs,
variance);
}
self.add_constraints_from_substs(
generics,
trait_ref.def_id,
- trait_def.generics.types.as_slice(),
- trait_def.generics.regions.as_slice(),
+ &trait_def.generics.types,
+ &trait_def.generics.regions,
trait_ref.substs,
variance);
}
ty::TyTrait(ref data) => {
- let poly_trait_ref =
- data.principal_trait_ref_with_self_ty(self.tcx(),
- self.tcx().types.err);
-
// The type `Foo<T+'a>` is contravariant w/r/t `'a`:
let contra = self.contravariant(variance);
- self.add_constraints_from_region(generics, data.bounds.region_bound, contra);
+ self.add_constraints_from_region(generics, data.region_bound, contra);
- // Ignore the SelfSpace, it is erased.
+ let poly_trait_ref =
+ data.principal.with_self_ty(self.tcx(), self.tcx().types.err);
self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
- let projections = data.projection_bounds_with_self_ty(self.tcx(),
- self.tcx().types.err);
- for projection in &projections {
+ for projection in &data.projection_bounds {
self.add_constraints_from_ty(generics, projection.0.ty, self.invariant);
}
}
ty::TyParam(ref data) => {
- let def_id = generics.types.get(data.space, data.idx as usize).def_id;
+ assert_eq!(generics.parent, None);
+ assert!((data.idx as usize) < generics.types.len());
+ let def_id = generics.types[data.idx as usize].def_id;
let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
match self.terms_cx.inferred_map.get(&node_id) {
Some(&index) => {
def_id: DefId,
type_param_defs: &[ty::TypeParameterDef<'tcx>],
region_param_defs: &[ty::RegionParameterDef],
- substs: &subst::Substs<'tcx>,
+ substs: &Substs<'tcx>,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
def_id,
for p in type_param_defs {
let variance_decl =
- self.declared_variance(p.def_id, def_id, TypeParam,
- p.space, p.index as usize);
+ self.declared_variance(p.def_id, def_id, TypeParam, p.index as usize);
let variance_i = self.xform(variance, variance_decl);
- let substs_ty = *substs.types.get(p.space, p.index as usize);
+ let substs_ty = substs.type_for_def(p);
debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
variance_decl, variance_i);
self.add_constraints_from_ty(generics, substs_ty, variance_i);
for p in region_param_defs {
let variance_decl =
- self.declared_variance(p.def_id, def_id,
- RegionParam, p.space, p.index as usize);
+ self.declared_variance(p.def_id, def_id, RegionParam, p.index as usize);
let variance_i = self.xform(variance, variance_decl);
- let substs_r = *substs.regions.get(p.space, p.index as usize);
+ let substs_r = substs.region_for_def(p);
self.add_constraints_from_region(generics, substs_r, variance_i);
}
}
variance: VarianceTermPtr<'a>) {
match region {
ty::ReEarlyBound(ref data) => {
- let def_id =
- generics.regions.get(data.space, data.index as usize).def_id;
+ assert_eq!(generics.parent, None);
+ assert!((data.index as usize) < generics.regions.len());
+ let def_id = generics.regions[data.index as usize].def_id;
let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
if self.is_to_be_inferred(node_id) {
let index = self.inferred_index(node_id);
//! optimal solution to the constraints. The final variance for each
//! inferred is then written into the `variance_map` in the tcx.
-use rustc::ty::subst::VecPerParamSpace;
use rustc::ty;
use std::rc::Rc;
let num_inferred = self.terms_cx.num_inferred();
while index < num_inferred {
let item_id = inferred_infos[index].item_id;
- let mut types = VecPerParamSpace::empty();
- let mut regions = VecPerParamSpace::empty();
+
+ let mut item_variances = ty::ItemVariances::empty();
while index < num_inferred && inferred_infos[index].item_id == item_id {
let info = &inferred_infos[index];
let variance = solutions[index];
- debug!("Index {} Info {} / {:?} / {:?} Variance {:?}",
- index, info.index, info.kind, info.space, variance);
+ debug!("Index {} Info {} / {:?} Variance {:?}",
+ index, info.index, info.kind, variance);
match info.kind {
- TypeParam => { types.push(info.space, variance); }
- RegionParam => { regions.push(info.space, variance); }
+ TypeParam => {
+ assert_eq!(item_variances.types.len(), info.index);
+ item_variances.types.push(variance);
+ }
+ RegionParam => {
+ assert_eq!(item_variances.regions.len(), info.index);
+ item_variances.regions.push(variance);
+ }
}
index += 1;
}
- let item_variances = ty::ItemVariances {
- types: types,
- regions: regions
- };
debug!("item_id={} item_variances={:?}",
item_id,
item_variances);
use arena::TypedArena;
use dep_graph::DepTrackingMapConfig;
-use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace};
use rustc::ty::{self, TyCtxt};
use rustc::ty::maps::ItemVariances;
use std::fmt;
pub struct InferredInfo<'a> {
pub item_id: ast::NodeId,
pub kind: ParamKind,
- pub space: ParamSpace,
pub index: usize,
pub param_id: ast::NodeId,
pub term: VarianceTermPtr<'a>,
// cache and share the variance struct used for items with
// no type/region parameters
- empty_variances: Rc::new(ty::ItemVariances {
- types: VecPerParamSpace::empty(),
- regions: VecPerParamSpace::empty()
- })
+ empty_variances: Rc::new(ty::ItemVariances::empty())
};
// See README.md for a discussion on dep-graph management.
let inferreds_on_entry = self.num_inferred();
- if has_self {
- self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id);
- }
-
for (i, p) in generics.lifetimes.iter().enumerate() {
let id = p.lifetime.id;
- self.add_inferred(item_id, RegionParam, TypeSpace, i, id);
+ self.add_inferred(item_id, RegionParam, i, id);
}
+ if has_self {
+ self.add_inferred(item_id, TypeParam, 0, item_id);
+ }
for (i, p) in generics.ty_params.iter().enumerate() {
- self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id);
+ let i = has_self as usize + i;
+ self.add_inferred(item_id, TypeParam, i, p.id);
}
// If this item has no type or lifetime parameters,
fn add_inferred(&mut self,
item_id: ast::NodeId,
kind: ParamKind,
- space: ParamSpace,
index: usize,
param_id: ast::NodeId) {
let inf_index = InferredIndex(self.inferred_infos.len());
let term = self.arena.alloc(InferredTerm(inf_index));
- let initial_variance = self.pick_initial_variance(item_id, space, index);
+ let initial_variance = self.pick_initial_variance(item_id, index);
self.inferred_infos.push(InferredInfo { item_id: item_id,
kind: kind,
- space: space,
index: index,
param_id: param_id,
term: term,
debug!("add_inferred(item_path={}, \
item_id={}, \
kind={:?}, \
- space={:?}, \
index={}, \
param_id={}, \
inf_index={:?}, \
initial_variance={:?})",
self.tcx.item_path_str(self.tcx.map.local_def_id(item_id)),
- item_id, kind, space, index, param_id, inf_index,
+ item_id, kind, index, param_id, inf_index,
initial_variance);
}
fn pick_initial_variance(&self,
item_id: ast::NodeId,
- space: ParamSpace,
index: usize)
-> ty::Variance
{
- match space {
- SelfSpace | FnSpace => {
- ty::Bivariant
- }
-
- TypeSpace => {
- match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
- Some(&(_, ref variances)) => variances[index],
- None => ty::Bivariant
- }
- }
+ match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
+ Some(&(_, ref variances)) => variances[index],
+ None => ty::Bivariant
}
}
use rustc::hir::def_id::DefId;
use rustc::hir::print as pprust;
use rustc::ty::{self, TyCtxt};
-use rustc::ty::subst;
use rustc_const_eval::lookup_const_by_id;
let def = tcx.lookup_trait_def(did);
let trait_items = tcx.trait_items(did).clean(cx);
let predicates = tcx.lookup_predicates(did);
- let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
+ let generics = (def.generics, &predicates).clean(cx);
let generics = filter_non_trait_generics(did, generics);
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
clean::Trait {
let predicates = tcx.lookup_predicates(did);
clean::Function {
decl: decl,
- generics: (&t.generics, &predicates, subst::FnSpace).clean(cx),
+ generics: (t.generics, &predicates).clean(cx),
unsafety: style,
constness: constness,
abi: abi,
&[..] if variant.kind == ty::VariantKind::Tuple => doctree::Tuple,
_ => doctree::Plain,
},
- generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
+ generics: (t.generics, &predicates).clean(cx),
fields: variant.fields.clean(cx),
fields_stripped: false,
}
match t.ty.sty {
ty::TyEnum(edef, _) if !tcx.sess.cstore.is_typedef(did) => {
return clean::EnumItem(clean::Enum {
- generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
+ generics: (t.generics, &predicates).clean(cx),
variants_stripped: false,
variants: edef.variants.clean(cx),
})
clean::TypedefItem(clean::Typedef {
type_: t.ty.clean(cx),
- generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
+ generics: (t.generics, &predicates).clean(cx),
}, false)
}
}
ty::TypeTraitItem(ref assoc_ty) => {
let did = assoc_ty.def_id;
- let type_scheme = ty::TypeScheme {
- ty: assoc_ty.ty.unwrap(),
- generics: ty::Generics::empty()
+ let typedef = clean::Typedef {
+ type_: assoc_ty.ty.unwrap().clean(cx),
+ generics: clean::Generics {
+ lifetimes: vec![],
+ type_params: vec![],
+ where_predicates: vec![]
+ }
};
- // Not sure the choice of ParamSpace actually matters here,
- // because an associated type won't have generics on the LHS
- let typedef = (type_scheme, ty::GenericPredicates::empty(),
- subst::ParamSpace::TypeSpace).clean(cx);
Some(clean::Item {
name: Some(assoc_ty.name.clean(cx)),
inner: clean::TypedefItem(typedef, true),
provided_trait_methods: provided,
trait_: trait_,
for_: for_,
- generics: (&ty.generics, &predicates, subst::TypeSpace).clean(cx),
+ generics: (ty.generics, &predicates).clean(cx),
items: trait_items,
polarity: polarity.map(|p| { p.clean(cx) }),
}),
/// its associated types as well. We specifically move these clauses to the
/// associated types instead when displaying, so when we're genering the
/// generics for the trait itself we need to be sure to remove them.
+/// We also need to remove the implied "recursive" Self: Trait bound.
///
/// The inverse of this filtering logic can be found in the `Clean`
/// implementation for `AssociatedType`
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics)
-> clean::Generics {
+ for pred in &mut g.where_predicates {
+ match *pred {
+ clean::WherePredicate::BoundPredicate {
+ ty: clean::Generic(ref s),
+ ref mut bounds
+ } if *s == "Self" => {
+ bounds.retain(|bound| {
+ match *bound {
+ clean::TyParamBound::TraitBound(clean::PolyTrait {
+ trait_: clean::ResolvedPath { did, .. },
+ ..
+ }, _) => did != trait_did,
+ _ => true
+ }
+ });
+ }
+ _ => {}
+ }
+ }
+
g.where_predicates.retain(|pred| {
match *pred {
clean::WherePredicate::BoundPredicate {
self_type: box clean::Generic(ref s),
trait_: box clean::ResolvedPath { did, .. },
name: ref _name,
- }, ..
- } => *s != "Self" || did != trait_did,
+ }, ref bounds
+ } => !(*s == "Self" && did == trait_did) && !bounds.is_empty(),
_ => true,
}
});
use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::fold::Folder;
use rustc::hir::print as pprust;
-use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace};
+use rustc::ty::subst::Substs;
use rustc::ty;
use rustc::middle::stability;
}
}
-impl<T: Clean<U>, U> Clean<VecPerParamSpace<U>> for VecPerParamSpace<T> {
- fn clean(&self, cx: &DocContext) -> VecPerParamSpace<U> {
- self.map(|x| x.clean(cx))
- }
-}
-
impl<T: Clean<U>, U> Clean<U> for P<T> {
fn clean(&self, cx: &DocContext) -> U {
(**self).clean(cx)
}
}
-impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> {
- fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) {
- let mut tp_bounds = vec![];
- self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b)));
- for bb in &self.builtin_bounds {
- tp_bounds.push(bb.clean(cx));
- }
-
- let mut bindings = vec![];
- for &ty::Binder(ref pb) in &self.projection_bounds {
- bindings.push(TypeBinding {
- name: pb.projection_ty.item_name.clean(cx),
- ty: pb.ty.clean(cx)
- });
- }
-
- (tp_bounds, bindings)
- }
-}
-
-fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
- bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
- let lifetimes = substs.regions.get_slice(subst::TypeSpace)
- .iter()
- .filter_map(|v| v.clean(cx))
- .collect();
- let types = substs.types.get_slice(subst::TypeSpace).to_vec();
+fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
+ bindings: Vec<TypeBinding>, substs: &Substs) -> PathParameters {
+ let lifetimes = substs.regions.iter().filter_map(|v| v.clean(cx)).collect();
+ let types = substs.types[has_self as usize..].to_vec();
match (trait_did, cx.tcx_opt()) {
// Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
// from Fn<(A, B,), C> to Fn(A, B) -> C
-fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>,
- bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
+fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self: bool,
+ bindings: Vec<TypeBinding>, substs: &Substs) -> Path {
Path {
global: false,
segments: vec![PathSegment {
name: name.to_string(),
- params: external_path_params(cx, trait_did, bindings, substs)
+ params: external_path_params(cx, trait_did, has_self, bindings, substs)
}],
}
}
Some(tcx) => tcx,
None => return RegionBound(Lifetime::statik())
};
- let empty = subst::Substs::empty();
+ let empty = Substs::empty(tcx);
let (did, path) = match *self {
ty::BoundSend =>
(tcx.lang_items.send_trait().unwrap(),
- external_path(cx, "Send", None, vec![], &empty)),
+ external_path(cx, "Send", None, false, vec![], empty)),
ty::BoundSized =>
(tcx.lang_items.sized_trait().unwrap(),
- external_path(cx, "Sized", None, vec![], &empty)),
+ external_path(cx, "Sized", None, false, vec![], empty)),
ty::BoundCopy =>
(tcx.lang_items.copy_trait().unwrap(),
- external_path(cx, "Copy", None, vec![], &empty)),
+ external_path(cx, "Copy", None, false, vec![], empty)),
ty::BoundSync =>
(tcx.lang_items.sync_trait().unwrap(),
- external_path(cx, "Sync", None, vec![], &empty)),
+ external_path(cx, "Sync", None, false, vec![], empty)),
};
inline::record_extern_fqn(cx, did, TypeTrait);
TraitBound(PolyTrait {
};
inline::record_extern_fqn(cx, self.def_id, TypeTrait);
let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
- Some(self.def_id), vec![], self.substs);
+ Some(self.def_id), true, vec![], self.substs);
- debug!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n",
- self.substs.types.get_slice(ParamSpace::TypeSpace));
+ debug!("ty::TraitRef\n substs.types: {:?}\n",
+ &self.input_types()[1..]);
// collect any late bound regions
let mut late_bounds = vec![];
- for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) {
+ for &ty_s in &self.input_types()[1..] {
if let ty::TyTuple(ts) = ty_s.sty {
for &ty_s in ts {
if let ty::TyRef(ref reg, _) = ty_s.sty {
}
}
-impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
+impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
let mut v = Vec::new();
- v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound));
+ v.extend(self.regions.iter().filter_map(|r| r.clean(cx))
+ .map(RegionBound));
v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
trait_: t.clean(cx),
lifetimes: vec![]
impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
fn clean(&self, cx: &DocContext) -> WherePredicate {
WherePredicate::BoundPredicate {
- ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(),
+ ty: self.trait_ref.self_ty().clean(cx),
bounds: vec![self.trait_ref.clean(cx)]
}
}
}
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
- &'a ty::GenericPredicates<'tcx>,
- subst::ParamSpace) {
+ &'a ty::GenericPredicates<'tcx>) {
fn clean(&self, cx: &DocContext) -> Generics {
use self::WherePredicate as WP;
- let (gens, preds, space) = *self;
+ let (gens, preds) = *self;
// Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove
// them.
- let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
- tp.clean(cx)
+ let stripped_typarams = gens.types.iter().filter_map(|tp| {
+ if tp.name == keywords::SelfType.name() {
+ assert_eq!(tp.index, 0);
+ None
+ } else {
+ Some(tp.clean(cx))
+ }
}).collect::<Vec<_>>();
- let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
+ let stripped_lifetimes = gens.regions.iter().map(|rp| {
let mut srp = rp.clone();
srp.bounds = Vec::new();
srp.clean(cx)
}).collect::<Vec<_>>();
- let mut where_predicates = preds.predicates.get_slice(space)
- .to_vec().clean(cx);
+ let mut where_predicates = preds.predicates.to_vec().clean(cx);
// Type parameters and have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
fn clean(&self, cx: &DocContext) -> Item {
- let generics = (&self.generics, &self.predicates,
- subst::FnSpace).clean(cx);
+ let generics = (self.generics, &self.predicates).clean(cx);
let mut decl = (self.def_id, &self.fty.sig).clean(cx);
match self.explicit_self {
ty::ExplicitSelfCategory::ByValue => {
fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime {
let def = self.tcx.named_region_map.defs.get(<.id).cloned();
match def {
- Some(DefEarlyBoundRegion(_, _, node_id)) |
+ Some(DefEarlyBoundRegion(_, node_id)) |
Some(DefLateBoundRegion(_, node_id)) |
Some(DefFreeRegion(_, node_id)) => {
if let Some(lt) = self.lt_substs.get(&node_id).cloned() {
};
inline::record_extern_fqn(cx, did, kind);
let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
- None, vec![], substs);
+ None, false, vec![], substs);
ResolvedPath {
path: path,
typarams: None,
is_generic: false,
}
}
- ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
- let did = principal.def_id();
+ ty::TyTrait(ref obj) => {
+ let did = obj.principal.def_id();
inline::record_extern_fqn(cx, did, TypeTrait);
- let (typarams, bindings) = bounds.clean(cx);
+
+ let mut typarams = vec![];
+ obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b)));
+ for bb in &obj.builtin_bounds {
+ typarams.push(bb.clean(cx));
+ }
+
+ let mut bindings = vec![];
+ for &ty::Binder(ref pb) in &obj.projection_bounds {
+ bindings.push(TypeBinding {
+ name: pb.item_name.clean(cx),
+ ty: pb.ty.clean(cx)
+ });
+ }
+
let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
- Some(did), bindings, principal.substs());
+ Some(did), false, bindings, obj.principal.0.substs);
ResolvedPath {
path: path,
typarams: Some(typarams),
let item_predicates = cx.tcx().lookup_predicates(def_id);
let substs = cx.tcx().lift(&substs).unwrap();
let bounds = item_predicates.instantiate(cx.tcx(), substs);
- let predicates = bounds.predicates.into_vec();
- ImplTrait(predicates.into_iter().filter_map(|predicate| {
+ ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| {
predicate.to_opt_poly_trait_ref().clean(cx)
}).collect())
}
// applied to this associated type in question.
let def = cx.tcx().lookup_trait_def(did);
let predicates = cx.tcx().lookup_predicates(did);
- let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
+ let generics = (def.generics, &predicates).clean(cx);
generics.where_predicates.iter().filter_map(|pred| {
let (name, self_type, trait_, bounds) = match *pred {
WherePredicate::BoundPredicate {
}
}
-impl<'a> Clean<Typedef> for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>,
- ParamSpace) {
- fn clean(&self, cx: &DocContext) -> Typedef {
- let (ref ty_scheme, ref predicates, ps) = *self;
- Typedef {
- type_: ty_scheme.ty.clean(cx),
- generics: (&ty_scheme.generics, predicates, ps).clean(cx)
- }
- }
-}
-
fn lang_struct(cx: &DocContext, did: Option<DefId>,
t: ty::Ty, name: &str,
fallback: fn(Box<Type>) -> Type) -> Type {
use std::collections::BTreeMap;
use rustc::hir::def_id::DefId;
-use rustc::ty::subst;
+use rustc::ty;
use clean::PathParameters as PP;
use clean::WherePredicate as WP;
-use clean::{self, Clean};
+use clean;
use core::DocContext;
pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
if child == trait_ {
return true
}
- let def = cx.tcx().lookup_trait_def(child);
- let predicates = cx.tcx().lookup_predicates(child);
- let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
- generics.where_predicates.iter().filter_map(|pred| {
- match *pred {
- clean::WherePredicate::BoundPredicate {
- ty: clean::Generic(ref s),
- ref bounds
- } if *s == "Self" => Some(bounds),
- _ => None,
- }
- }).flat_map(|bounds| bounds).any(|bound| {
- let poly_trait = match *bound {
- clean::TraitBound(ref t, _) => t,
- _ => return false,
- };
- match poly_trait.trait_ {
- clean::ResolvedPath { did, .. } => {
- trait_is_same_or_supertrait(cx, did, trait_)
+ let predicates = cx.tcx().lookup_super_predicates(child).predicates;
+ predicates.iter().filter_map(|pred| {
+ if let ty::Predicate::Trait(ref pred) = *pred {
+ if pred.0.trait_ref.self_ty().is_self() {
+ Some(pred.def_id())
+ } else {
+ None
}
- _ => false,
+ } else {
+ None
}
- })
+ }).any(|did| trait_is_same_or_supertrait(cx, did, trait_))
}
url.push_str("/index.html");
}
_ => {
- url.push_str(shortty.to_static_str());
+ url.push_str(shortty.css_class());
url.push_str(".");
url.push_str(fqp.last().unwrap());
url.push_str(".html");
AssociatedConst = 18,
}
+
+#[derive(Copy, Eq, PartialEq, Clone)]
+pub enum NameSpace {
+ Type,
+ Value,
+ Macro,
+}
+
impl ItemType {
pub fn from_item(item: &clean::Item) -> ItemType {
let inner = match item.inner {
}
}
- pub fn to_static_str(&self) -> &'static str {
+ pub fn css_class(&self) -> &'static str {
match *self {
ItemType::Module => "mod",
ItemType::ExternCrate => "externcrate",
ItemType::AssociatedConst => "associatedconstant",
}
}
+
+ pub fn name_space(&self) -> NameSpace {
+ match *self {
+ ItemType::Struct |
+ ItemType::Enum |
+ ItemType::Module |
+ ItemType::Typedef |
+ ItemType::Trait |
+ ItemType::Primitive |
+ ItemType::AssociatedType => NameSpace::Type,
+
+ ItemType::ExternCrate |
+ ItemType::Import |
+ ItemType::Function |
+ ItemType::Static |
+ ItemType::Impl |
+ ItemType::TyMethod |
+ ItemType::Method |
+ ItemType::StructField |
+ ItemType::Variant |
+ ItemType::Constant |
+ ItemType::AssociatedConst => NameSpace::Value,
+
+ ItemType::Macro => NameSpace::Macro,
+ }
+ }
}
impl fmt::Display for ItemType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.css_class().fmt(f)
+ }
+}
+
+pub const NAMESPACE_TYPE: &'static str = "t";
+pub const NAMESPACE_VALUE: &'static str = "v";
+pub const NAMESPACE_MACRO: &'static str = "m";
+
+impl NameSpace {
+ pub fn to_static_str(&self) -> &'static str {
+ match *self {
+ NameSpace::Type => NAMESPACE_TYPE,
+ NameSpace::Value => NAMESPACE_VALUE,
+ NameSpace::Macro => NAMESPACE_MACRO,
+ }
+ }
+}
+
+impl fmt::Display for NameSpace {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.to_static_str().fmt(f)
}
pub struct Page<'a> {
pub title: &'a str,
- pub ty: &'a str,
+ pub css_class: &'a str,
pub root_path: &'a str,
pub description: &'a str,
pub keywords: &'a str,
</form>
</nav>
- <section id='main' class="content {ty}">{content}</section>
+ <section id='main' class="content {css_class}">{content}</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
},
content = *t,
root_path = page.root_path,
- ty = page.ty,
+ css_class = page.css_class,
logo = if layout.logo.is_empty() {
"".to_string()
} else {
use std::default::Default;
use std::error;
use std::fmt::{self, Display, Formatter};
-use std::fs::{self, File};
+use std::fs::{self, File, OpenOptions};
use std::io::prelude::*;
use std::io::{self, BufWriter, BufReader};
use std::iter::repeat;
for &(did, ref item) in orphan_methods {
if let Some(&(ref fqp, _)) = paths.get(&did) {
search_index.push(IndexItem {
- ty: shortty(item),
+ ty: item_type(item),
name: item.name.clone().unwrap(),
path: fqp[..fqp.len() - 1].join("::"),
desc: Escape(&shorter(item.doc_value())).to_string(),
for line in BufReader::new(File::open(path)?).lines() {
let line = line?;
if !line.starts_with(key) {
- continue
+ continue;
}
if line.starts_with(&format!(r#"{}["{}"]"#, key, krate)) {
- continue
+ continue;
}
ret.push(line.to_string());
}
try_err!(mkdir(&mydst), &mydst);
}
mydst.push(&format!("{}.{}.js",
- remote_item_type.to_static_str(),
+ remote_item_type.css_class(),
remote_path[remote_path.len() - 1]));
let all_implementors = try_err!(collect(&mydst, &krate.name,
"implementors"),
}
/// Returns a documentation-level item type from the item.
-fn shortty(item: &clean::Item) -> ItemType {
+fn item_type(item: &clean::Item) -> ItemType {
ItemType::from_item(item)
}
let mut fname = p.file_name().expect("source has no filename")
.to_os_string();
fname.push(".html");
- cur.push(&fname[..]);
+ cur.push(&fname);
href.push_str(&fname.to_string_lossy());
let mut w = BufWriter::new(File::create(&cur)?);
let desc = format!("Source to the Rust file `{}`.", filename);
let page = layout::Page {
title: &title,
- ty: "source",
+ css_class: "source",
root_path: &root_path,
description: &desc,
keywords: BASIC_KEYWORDS,
// inserted later on when serializing the search-index.
if item.def_id.index != CRATE_DEF_INDEX {
self.search_index.push(IndexItem {
- ty: shortty(&item),
+ ty: item_type(&item),
name: s.to_string(),
path: path.join("::").to_string(),
desc: Escape(&shorter(item.doc_value())).to_string(),
self.access_levels.is_public(item.def_id)
{
self.paths.insert(item.def_id,
- (self.stack.clone(), shortty(&item)));
+ (self.stack.clone(), item_type(&item)));
}
}
// link variants to their parent enum because pages aren't emitted
clean::PrimitiveItem(..) if item.visibility.is_some() => {
self.paths.insert(item.def_id, (self.stack.clone(),
- shortty(&item)));
+ item_type(&item)));
}
_ => {}
Ok(())
}
- /// Non-parallelized version of rendering an item. This will take the input
- /// item, render its contents, and then invoke the specified closure with
- /// all sub-items which need to be rendered.
- ///
- /// The rendering driver uses this closure to queue up more work.
- fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
- F: FnMut(&mut Context, clean::Item),
- {
- fn render(writer: &mut io::Write, cx: &Context, it: &clean::Item,
- pushname: bool) -> io::Result<()> {
- // A little unfortunate that this is done like this, but it sure
- // does make formatting *a lot* nicer.
- CURRENT_LOCATION_KEY.with(|slot| {
- *slot.borrow_mut() = cx.current.clone();
- });
+ fn render_item(&self,
+ writer: &mut io::Write,
+ it: &clean::Item,
+ pushname: bool)
+ -> io::Result<()> {
+ // A little unfortunate that this is done like this, but it sure
+ // does make formatting *a lot* nicer.
+ CURRENT_LOCATION_KEY.with(|slot| {
+ *slot.borrow_mut() = self.current.clone();
+ });
- let mut title = if it.is_primitive() {
- // No need to include the namespace for primitive types
- String::new()
- } else {
- cx.current.join("::")
- };
- if pushname {
- if !title.is_empty() {
- title.push_str("::");
- }
- title.push_str(it.name.as_ref().unwrap());
+ let mut title = if it.is_primitive() {
+ // No need to include the namespace for primitive types
+ String::new()
+ } else {
+ self.current.join("::")
+ };
+ if pushname {
+ if !title.is_empty() {
+ title.push_str("::");
}
- title.push_str(" - Rust");
- let tyname = shortty(it).to_static_str();
- let desc = if it.is_crate() {
- format!("API documentation for the Rust `{}` crate.",
- cx.shared.layout.krate)
- } else {
- format!("API documentation for the Rust `{}` {} in crate `{}`.",
- it.name.as_ref().unwrap(), tyname, cx.shared.layout.krate)
- };
- let keywords = make_item_keywords(it);
- let page = layout::Page {
- ty: tyname,
- root_path: &cx.root_path,
- title: &title,
- description: &desc,
- keywords: &keywords,
- };
+ title.push_str(it.name.as_ref().unwrap());
+ }
+ title.push_str(" - Rust");
+ let tyname = item_type(it).css_class();
+ let desc = if it.is_crate() {
+ format!("API documentation for the Rust `{}` crate.",
+ self.shared.layout.krate)
+ } else {
+ format!("API documentation for the Rust `{}` {} in crate `{}`.",
+ it.name.as_ref().unwrap(), tyname, self.shared.layout.krate)
+ };
+ let keywords = make_item_keywords(it);
+ let page = layout::Page {
+ css_class: tyname,
+ root_path: &self.root_path,
+ title: &title,
+ description: &desc,
+ keywords: &keywords,
+ };
- reset_ids(true);
+ reset_ids(true);
- if !cx.render_redirect_pages {
- layout::render(writer, &cx.shared.layout, &page,
- &Sidebar{ cx: cx, item: it },
- &Item{ cx: cx, item: it },
- cx.shared.css_file_extension.is_some())?;
- } else {
- let mut url = repeat("../").take(cx.current.len())
- .collect::<String>();
- if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
- for name in &names[..names.len() - 1] {
- url.push_str(name);
- url.push_str("/");
- }
- url.push_str(&item_path(ty, names.last().unwrap()));
- layout::redirect(writer, &url)?;
+ if !self.render_redirect_pages {
+ layout::render(writer, &self.shared.layout, &page,
+ &Sidebar{ cx: self, item: it },
+ &Item{ cx: self, item: it },
+ self.shared.css_file_extension.is_some())?;
+ } else {
+ let mut url = repeat("../").take(self.current.len())
+ .collect::<String>();
+ if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
+ for name in &names[..names.len() - 1] {
+ url.push_str(name);
+ url.push_str("/");
}
+ url.push_str(&item_path(ty, names.last().unwrap()));
+ layout::redirect(writer, &url)?;
}
- Ok(())
}
+ Ok(())
+ }
+ /// Non-parallelized version of rendering an item. This will take the input
+ /// item, render its contents, and then invoke the specified closure with
+ /// all sub-items which need to be rendered.
+ ///
+ /// The rendering driver uses this closure to queue up more work.
+ fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
+ F: FnMut(&mut Context, clean::Item),
+ {
// Stripped modules survive the rustdoc passes (i.e. `strip-private`)
// if they contain impls for public types. These modules can also
// contain items such as publicly reexported structures.
let item = item.take().unwrap();
let mut buf = Vec::new();
- render(&mut buf, this, &item, false).unwrap();
+ this.render_item(&mut buf, &item, false).unwrap();
// buf will be empty if the module is stripped and there is no redirect for it
if !buf.is_empty() {
let joint_dst = this.dst.join("index.html");
_ => unreachable!()
};
- // render sidebar-items.js used throughout this module
+ // Render sidebar-items.js used throughout this module.
if !this.render_redirect_pages {
let items = this.build_sidebar_items(&m);
let js_dst = this.dst.join("sidebar-items.js");
for item in m.items {
f(this,item);
}
+
Ok(())
- })
+ })?;
} else if item.name.is_some() {
let mut buf = Vec::new();
- render(&mut buf, self, &item, true).unwrap();
+ self.render_item(&mut buf, &item, true).unwrap();
// buf will be empty if the item is stripped and there is no redirect for it
if !buf.is_empty() {
- let joint_dst = self.dst.join(&item_path(shortty(&item),
- item.name.as_ref().unwrap()));
+ let name = item.name.as_ref().unwrap();
+ let item_type = item_type(&item);
+ let file_name = &item_path(item_type, name);
+ let joint_dst = self.dst.join(file_name);
try_err!(fs::create_dir_all(&self.dst), &self.dst);
let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
try_err!(dst.write_all(&buf), &joint_dst);
+
+ // Redirect from a sane URL using the namespace to Rustdoc's
+ // URL for the page.
+ let redir_name = format!("{}.{}.html", name, item_type.name_space());
+ let redir_dst = self.dst.join(redir_name);
+ if let Ok(mut redirect_out) = OpenOptions::new().create_new(true)
+ .write(true)
+ .open(&redir_dst) {
+ try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst);
+ }
}
- Ok(())
- } else {
- Ok(())
}
+ Ok(())
}
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<NameDoc>> {
for item in &m.items {
if self.maybe_ignore_item(item) { continue }
- let short = shortty(item).to_static_str();
+ let short = item_type(item).css_class();
let myname = match item.name {
None => continue,
Some(ref s) => s.to_string(),
}
Some(format!("{path}{file}?gotosrc={goto}",
path = path,
- file = item_path(shortty(self.item), external_path.last().unwrap()),
+ file = item_path(item_type(self.item), external_path.last().unwrap()),
goto = self.item.def_id.index.as_usize()))
}
}
}
}
write!(fmt, "<a class='{}' href=''>{}</a>",
- shortty(self.item), self.item.name.as_ref().unwrap())?;
+ item_type(self.item), self.item.name.as_ref().unwrap())?;
write!(fmt, "</span>")?; // in-band
write!(fmt, "<span class='out-of-band'>")?;
fn item_path(ty: ItemType, name: &str) -> String {
match ty {
ItemType::Module => format!("{}/index.html", name),
- _ => format!("{}.{}.html", ty.to_static_str(), name),
+ _ => format!("{}.{}.html", ty.css_class(), name),
}
}
}
fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering {
- let ty1 = shortty(i1);
- let ty2 = shortty(i2);
+ let ty1 = item_type(i1);
+ let ty2 = item_type(i2);
if ty1 != ty2 {
return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2))
}
continue;
}
- let myty = Some(shortty(myitem));
+ let myty = Some(item_type(myitem));
if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) {
// Put `extern crate` and `use` re-exports in the same section.
curty = myty;
name = *myitem.name.as_ref().unwrap(),
stab_docs = stab_docs,
docs = shorter(Some(&Markdown(doc_value).to_string())),
- class = shortty(myitem),
+ class = item_type(myitem),
stab = myitem.stability_class(),
- href = item_path(shortty(myitem), myitem.name.as_ref().unwrap()),
+ href = item_path(item_type(myitem), myitem.name.as_ref().unwrap()),
title = full_path(cx, myitem))?;
}
}
fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item)
-> fmt::Result {
let name = m.name.as_ref().unwrap();
- let id = derive_id(format!("{}.{}", shortty(m), name));
- write!(w, "<h3 id='{id}' class='method stab {stab}'><code>",
+ let item_type = item_type(m);
+ let id = derive_id(format!("{}.{}", item_type, name));
+ let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+ write!(w, "<h3 id='{id}' class='method stab {stab}'>\
+ <span id='{ns_id}' class='invisible'><code>",
id = id,
- stab = m.stability_class())?;
+ stab = m.stability_class(),
+ ns_id = ns_id)?;
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)))?;
write!(w, "</code>")?;
render_stability_since(w, m, t)?;
- write!(w, "</h3>")?;
+ write!(w, "</span></h3>")?;
document(w, cx, m)?;
Ok(())
}
let (ref path, _) = cache.external_paths[&it.def_id];
path[..path.len() - 1].join("/")
},
- ty = shortty(it).to_static_str(),
+ ty = item_type(it).css_class(),
name = *it.name.as_ref().unwrap())?;
Ok(())
}
use html::item_type::ItemType::*;
let name = it.name.as_ref().unwrap();
- let ty = match shortty(it) {
+ let ty = match item_type(it) {
Typedef | AssociatedType => AssociatedType,
s@_ => s,
};
link: AssocItemLink)
-> fmt::Result {
let name = meth.name.as_ref().unwrap();
- let anchor = format!("#{}.{}", shortty(meth), name);
+ let anchor = format!("#{}.{}", item_type(meth), name);
let href = match link {
AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
AssocItemLink::Anchor(None) => anchor,
if fields.peek().is_some() {
write!(w, "<h2 class='fields'>Fields</h2>")?;
for (field, ty) in fields {
- write!(w, "<span id='{shortty}.{name}' class='{shortty}'><code>{name}: {ty}</code>
- </span><span class='stab {stab}'></span>",
- shortty = ItemType::StructField,
+ let id = derive_id(format!("{}.{}",
+ ItemType::StructField,
+ field.name.as_ref().unwrap()));
+ let ns_id = derive_id(format!("{}.{}",
+ field.name.as_ref().unwrap(),
+ ItemType::StructField.name_space()));
+ write!(w, "<span id='{id}' class='{item_type}'>
+ <span id='{ns_id}' class='invisible'>
+ <code>{name}: {ty}</code>
+ </span></span><span class='stab {stab}'></span>",
+ item_type = ItemType::StructField,
+ id = id,
+ ns_id = ns_id,
stab = field.stability_class(),
name = field.name.as_ref().unwrap(),
ty = ty)?;
if !e.variants.is_empty() {
write!(w, "<h2 class='variants'>Variants</h2>\n")?;
for variant in &e.variants {
- write!(w, "<span id='{shortty}.{name}' class='variant'><code>{name}",
- shortty = ItemType::Variant,
+ let id = derive_id(format!("{}.{}",
+ ItemType::Variant,
+ variant.name.as_ref().unwrap()));
+ let ns_id = derive_id(format!("{}.{}",
+ variant.name.as_ref().unwrap(),
+ ItemType::Variant.name_space()));
+ write!(w, "<span id='{id}' class='variant'>\
+ <span id='{ns_id}' class='invisible'><code>{name}",
+ id = id,
+ ns_id = ns_id,
name = variant.name.as_ref().unwrap())?;
if let clean::VariantItem(ref var) = variant.inner {
if let clean::TupleVariant(ref tys) = var.kind {
write!(w, ")")?;
}
}
- write!(w, "</code></span>")?;
+ write!(w, "</code></span></span>")?;
document(w, cx, variant)?;
use clean::{Variant, StructVariant};
for field in &s.fields {
use clean::StructFieldItem;
if let StructFieldItem(ref ty) = field.inner {
+ let id = derive_id(format!("variant.{}.field.{}",
+ variant.name.as_ref().unwrap(),
+ field.name.as_ref().unwrap()));
+ let ns_id = derive_id(format!("{}.{}.{}.{}",
+ variant.name.as_ref().unwrap(),
+ ItemType::Variant.name_space(),
+ field.name.as_ref().unwrap(),
+ ItemType::StructField.name_space()));
write!(w, "<tr><td \
- id='variant.{v}.field.{f}'>\
- <code>{f}: {t}</code></td><td>",
- v = variant.name.as_ref().unwrap(),
+ id='{id}'>\
+ <span id='{ns_id}' class='invisible'>\
+ <code>{f}: {t}</code></span></td><td>",
+ id = id,
+ ns_id = ns_id,
f = field.name.as_ref().unwrap(),
t = *ty)?;
document(w, cx, field)?;
}
}
- fn doctraititem(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
- link: AssocItemLink, render_static: bool,
- is_default_item: bool, outer_version: Option<&str>,
- trait_: Option<&clean::Trait>) -> fmt::Result {
- let shortty = shortty(item);
+ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
+ link: AssocItemLink, render_static: bool,
+ is_default_item: bool, outer_version: Option<&str>,
+ trait_: Option<&clean::Trait>) -> fmt::Result {
+ let item_type = item_type(item);
let name = item.name.as_ref().unwrap();
let is_static = match item.inner {
clean::MethodItem(..) | clean::TyMethodItem(..) => {
// Only render when the method is not static or we allow static methods
if !is_static || render_static {
- let id = derive_id(format!("{}.{}", shortty, name));
- write!(w, "<h4 id='{}' class='{}'>", id, shortty)?;
+ let id = derive_id(format!("{}.{}", item_type, name));
+ let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+ write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<span id='{}' class='invisible'>", ns_id)?;
write!(w, "<code>")?;
render_assoc_item(w, item, link.anchor(&id))?;
write!(w, "</code>")?;
render_stability_since_raw(w, item.stable_since(), outer_version)?;
- write!(w, "</h4>\n")?;
+ write!(w, "</span></h4>\n")?;
}
}
clean::TypedefItem(ref tydef, _) => {
let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name));
- write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
+ let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+ write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
- write!(w, "</code></h4>\n")?;
+ write!(w, "</code></span></h4>\n")?;
}
clean::AssociatedConstItem(ref ty, ref default) => {
- let id = derive_id(format!("{}.{}", shortty, name));
- write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
+ let id = derive_id(format!("{}.{}", item_type, name));
+ let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+ write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
- write!(w, "</code></h4>\n")?;
+ write!(w, "</code></span></h4>\n")?;
}
clean::ConstantItem(ref c) => {
- let id = derive_id(format!("{}.{}", shortty, name));
- write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
+ let id = derive_id(format!("{}.{}", item_type, name));
+ let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+ write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?;
- write!(w, "</code></h4>\n")?;
+ write!(w, "</code></span></h4>\n")?;
}
clean::AssociatedTypeItem(ref bounds, ref default) => {
- let id = derive_id(format!("{}.{}", shortty, name));
- write!(w, "<h4 id='{}' class='{}'><code>", id, shortty)?;
+ let id = derive_id(format!("{}.{}", item_type, name));
+ let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
+ write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
+ write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
- write!(w, "</code></h4>\n")?;
+ write!(w, "</code></span></h4>\n")?;
}
clean::StrippedItem(..) => return Ok(()),
_ => panic!("can't make docs for trait item with name {:?}", item.name)
write!(w, "<div class='impl-items'>")?;
for trait_item in &i.inner_impl().items {
- doctraititem(w, cx, trait_item, link, render_header,
- false, outer_version, trait_)?;
+ doc_impl_item(w, cx, trait_item, link, render_header,
+ false, outer_version, trait_)?;
}
fn render_default_items(w: &mut fmt::Formatter,
let did = i.trait_.as_ref().unwrap().def_id().unwrap();
let assoc_link = AssocItemLink::GotoSource(did, &i.provided_trait_methods);
- doctraititem(w, cx, trait_item, assoc_link, render_static, true,
- outer_version, None)?;
+ doc_impl_item(w, cx, trait_item, assoc_link, render_static, true,
+ outer_version, None)?;
}
Ok(())
}
relpath: '{path}'\
}};</script>",
name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""),
- ty = shortty(it).to_static_str(),
+ ty = item_type(it).css_class(),
path = relpath)?;
if parentlen == 0 {
// there is no sidebar-items.js beyond the crate root path
font-size: 21px;
}
-h4 > code, h3 > code {
+h4 > code, h3 > code, invisible > code {
position: inherit;
}
z-index: 5;
}
+.invisible {
+ background: rgba(0, 0, 0, 0);
+ width: 100%;
+ display: inline-block;
+}
+
.content .in-band {
margin: 0px;
padding: 0px;
:target > code {
background: #FDFFD3;
+ opacity: 1;
}
/* Media Queries */
h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
border-bottom-color: #DDDDDD;
}
-.in-band, code {
+.in-band {
background-color: white;
}
fn keys_val<'a, 'new>(v: Keys<'a, u8, &'static str>) -> Keys<'a, u8, &'new str> { v }
fn values_key<'a, 'new>(v: Values<'a, &'static str, u8>) -> Values<'a, &'new str, u8> { v }
fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> { v }
+ fn drain<'new>(d: Drain<'static, &'static str, &'static str>)
+ -> Drain<'new, &'new str, &'new str> { d }
}
#[cfg(test)]
-> Intersection<'a, &'new str, RandomState> { v }
fn union<'a, 'new>(v: Union<'a, &'static str, RandomState>)
-> Union<'a, &'new str, RandomState> { v }
+ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
}
#[cfg(test)]
use mem::{align_of, size_of};
use mem;
use ops::{Deref, DerefMut};
-use ptr::{self, Unique};
+use ptr::{self, Unique, Shared};
use self::BucketState::*;
hashes_end: hashes_end,
marker: marker::PhantomData,
},
- table: self,
+ table: unsafe { Shared::new(self) },
+ marker: marker::PhantomData,
}
}
/// Iterator over the entries in a table, clearing the table.
pub struct Drain<'a, K: 'a, V: 'a> {
- table: &'a mut RawTable<K, V>,
+ table: Shared<RawTable<K, V>>,
iter: RawBuckets<'static, K, V>,
+ marker: marker::PhantomData<&'a RawTable<K, V>>,
}
unsafe impl<'a, K: Sync, V: Sync> Sync for Drain<'a, K, V> {}
#[inline]
fn next(&mut self) -> Option<(SafeHash, K, V)> {
self.iter.next().map(|bucket| {
- self.table.size -= 1;
unsafe {
+ (**self.table).size -= 1;
(SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) },
ptr::read(bucket.key),
ptr::read(bucket.val))
}
fn size_hint(&self) -> (usize, Option<usize>) {
- let size = self.table.size();
+ let size = unsafe { (**self.table).size() };
(size, Some(size))
}
}
impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
fn len(&self) -> usize {
- self.table.size()
+ unsafe {
+ (**self.table).size()
+ }
}
}
--- /dev/null
+// Copyright 2016 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.
+
+//! This is a shim file to ease the transition to the final procedural macro interface for
+//! Macros 2.0. It currently exposes the `libsyntax` operations that the quasiquoter's
+//! output needs to compile correctly, along with the following operators:
+//!
+//! - `build_block_emitter`, which produces a `block` output macro result from the
+//! provided TokenStream.
+
+use ast;
+use codemap::Span;
+use parse::parser::Parser;
+use ptr::P;
+use tokenstream::TokenStream;
+use ext::base::*;
+
+/// Take a `ExtCtxt`, `Span`, and `TokenStream`, and produce a Macro Result that parses
+/// the TokenStream as a block and returns it as an `Expr`.
+pub fn build_block_emitter<'cx>(cx: &'cx mut ExtCtxt, sp: Span, output: TokenStream)
+ -> Box<MacResult + 'cx> {
+ let parser = cx.new_parser_from_tts(&output.to_tts());
+
+ struct Result<'a> {
+ prsr: Parser<'a>,
+ span: Span,
+ }; //FIXME is this the right lifetime
+
+ impl<'a> Result<'a> {
+ fn block(&mut self) -> P<ast::Block> {
+ let res = self.prsr.parse_block().unwrap();
+ res
+ }
+ }
+
+ impl<'a> MacResult for Result<'a> {
+ fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
+ let mut me = *self;
+ Some(P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::ExprKind::Block(me.block()),
+ span: me.span,
+ attrs: ast::ThinVec::new(),
+ }))
+
+ }
+ }
+
+ Box::new(Result {
+ prsr: parser,
+ span: sp,
+ })
+}
+
+pub mod prelude {
+ pub use ext::proc_macro_shim::build_block_emitter;
+ pub use ast::Ident;
+ pub use codemap::{DUMMY_SP, Span};
+ pub use ext::base::{ExtCtxt, MacResult};
+ pub use parse::token::{self, Token, DelimToken, keywords, str_to_ident};
+ pub use tokenstream::{TokenTree, TokenStream};
+}
pub mod build;
pub mod expand;
pub mod hygiene;
+ pub mod proc_macro_shim;
pub mod quote;
pub mod source_util;
TokenStream::mk_leaf(Rc::new(trees), span)
}
+ /// Convert a vector of Tokens into a TokenStream.
+ pub fn from_tokens(tokens: Vec<Token>) -> TokenStream {
+ // FIXME do something nicer with the spans
+ TokenStream::from_tts(tokens.into_iter().map(|t| TokenTree::Token(DUMMY_SP, t)).collect())
+ }
+
/// Manually change a TokenStream's span.
pub fn respan(self, span: Span) -> TokenStream {
match self.ts {
name = "log"
version = "0.0.0"
+[[package]]
+name = "proc_macro"
+version = "0.0.0"
+dependencies = [
+ "log 0.0.0",
+ "rustc_plugin 0.0.0",
+ "syntax 0.0.0",
+ "syntax_pos 0.0.0",
+]
+
[[package]]
name = "rbml"
version = "0.0.0"
"flate 0.0.0",
"graphviz 0.0.0",
"log 0.0.0",
+ "proc_macro 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
"rustc_borrowck 0.0.0",
// For the non-generic foo(), we should generate a codegen-item even if it
// is not called anywhere
- //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0]<u64, i32>
+ //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0]<i32, u64>
}
// Non-generic impl of generic trait
//~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, &str>
let _ = 2i8.bar("&str");
- //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u64, i32, char>
+ //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i32, u64, char>
0i32.bar(0u64, 'c');
- //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u64, i32, &str>
+ //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i32, u64, &str>
0i32.bar(0u64, "&str");
- //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i8, u32, &[char; 1]>
+ //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i8, &[char; 1]>
0u32.bar(0i8, &['c']);
- //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i16, u32, ()>
+ //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i16, ()>
0u32.bar(0i16, ());
}
}
pub fn test<A: Foo, B: Foo>() {
- let _array: [u32; <A as Foo>::Y]; //~ error: the parameter type
+ let _array: [u32; <A as Foo>::Y];
+ //~^ ERROR the trait bound `A: Foo` is not satisfied
}
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern: overflow representing the type `S`
+// error-pattern: overflow representing the type
-#![feature(rustc_attrs)]
trait Mirror { type It: ?Sized; }
impl<T: ?Sized> Mirror for T { type It = Self; }
struct S(Option<<S as Mirror>::It>);
-#[rustc_no_mir] // FIXME #27840 MIR tries to represent `std::option::Option<S>` first.
fn main() {
let _s = S(None);
}
#![feature(default_type_parameter_fallback)]
-fn avg<T=T::Item>(_: T) {} //~ ERROR associated type `Item` not found for `T`
+fn avg<T=T::Item>(_: T) {}
+//~^ ERROR type parameters with a default cannot use forward declared identifiers
+
fn main() {}
}
#[rustc_variance]
-struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[];[]], regions=[[-];[];[]])
+struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[+], regions=[-])
field: (T, &'a ())
}
#[rustc_variance]
-struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[];[]], regions=[[o];[];[]])
+struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[o], regions=[o])
field: <T as Trait<'a>>::Type
}
// For better or worse, associated types are invariant, and hence we
// get an invariant result for `'a`.
#[rustc_variance]
-struct Foo<'a> { //~ ERROR regions=[[o];[];[]]
+struct Foo<'a> { //~ ERROR regions=[o]
x: Box<Fn(i32) -> &'a i32 + 'static>
}
#![feature(rustc_attrs)]
#[rustc_variance]
-trait Foo: 'static { //~ ERROR types=[[];[o];[]]
+trait Foo: 'static { //~ ERROR types=[o]
}
#[rustc_variance]
-trait Bar<T> { //~ ERROR types=[[o];[o];[]]
+trait Bar<T> { //~ ERROR types=[o, o]
fn do_it(&self)
where T: 'static;
}
// Regions that just appear in normal spots are contravariant:
#[rustc_variance]
-struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
+struct Test2<'a, 'b, 'c> { //~ ERROR regions=[-, -, -]
x: &'a isize,
y: &'b [isize],
c: &'c str
// Those same annotations in function arguments become covariant:
#[rustc_variance]
-struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
+struct Test3<'a, 'b, 'c> { //~ ERROR regions=[+, +, +]
x: extern "Rust" fn(&'a isize),
y: extern "Rust" fn(&'b [isize]),
c: extern "Rust" fn(&'c str),
// Mutability induces invariance:
#[rustc_variance]
-struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]]
+struct Test4<'a, 'b:'a> { //~ ERROR regions=[-, o]
x: &'a mut &'b isize,
}
// contravariant context:
#[rustc_variance]
-struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[];[]]
+struct Test5<'a, 'b:'a> { //~ ERROR regions=[+, o]
x: extern "Rust" fn(&'a mut &'b isize),
}
// argument list occurs in an invariant context.
#[rustc_variance]
-struct Test6<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]]
+struct Test6<'a, 'b:'a> { //~ ERROR regions=[-, o]
x: &'a mut extern "Rust" fn(&'b isize),
}
// No uses at all is bivariant:
#[rustc_variance]
-struct Test7<'a> { //~ ERROR regions=[[*];[];[]]
+struct Test7<'a> { //~ ERROR regions=[*]
//~^ ERROR parameter `'a` is never used
x: isize
}
// Try enums too.
#[rustc_variance]
-enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
+enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[+, -, o]
Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]),
Test8C(&'b mut &'c str),
#![feature(rustc_attrs)]
#[rustc_variance]
-enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]]
+enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[+, -, o, *]
//~^ ERROR parameter `'d` is never used
Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]),
}
#[rustc_variance]
-struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]]
+struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[*, o, -, +]
//~^ ERROR parameter `'w` is never used
f: Base<'z, 'y, 'x, 'w>
}
#[rustc_variance] // Combine - and + to yield o
-struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]]
+struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[o, o, *]
//~^ ERROR parameter `'c` is never used
f: Base<'a, 'a, 'b, 'c>
}
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
-struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]]
+struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[o, -, *]
//~^ ERROR parameter `'c` is never used
f: Base<'a, 'b, 'a, 'c>
}
#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
-struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
+struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[+, -, o]
f: Base<'a, 'b, 'c, 'a>
}
// influence variance.
#[rustc_variance]
-trait Getter<T> { //~ ERROR types=[[o];[o];[]]
+trait Getter<T> { //~ ERROR types=[o, o]
fn get(&self) -> T;
}
#[rustc_variance]
-trait Setter<T> { //~ ERROR types=[[o];[o];[]]
+trait Setter<T> { //~ ERROR types=[o, o]
fn get(&self, T);
}
#[rustc_variance]
-struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[[+, +];[];[]]
+struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[+, +]
t: T, u: U
}
#[rustc_variance]
-enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[[*, +];[];[]]
+enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[*, +]
//~^ ERROR parameter `U` is never used
Foo(T)
}
#[rustc_variance]
-trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[o, o];[o];[]]
+trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[o, o, o]
fn getter(&self, u: U) -> T;
}
#[rustc_variance]
-trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[o];[o];[]]
+trait TestTrait2<U> : Getter<U> { //~ ERROR types=[o, o]
}
#[rustc_variance]
-trait TestTrait3<U> { //~ ERROR types=[[o];[o];[]]
+trait TestTrait3<U> { //~ ERROR types=[o, o]
fn getter<T:Getter<U>>(&self);
}
#[rustc_variance]
-struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[[*, +];[];[]]
+struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[*, +]
//~^ ERROR parameter `U` is never used
t: T
}
#[rustc_variance]
-struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[[*, +];[];[]]
+struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[*, +]
//~^ ERROR parameter `U` is never used
t: T
}
trait T { fn foo(&self); }
#[rustc_variance]
-struct TOption<'a> { //~ ERROR regions=[[-];[];[]]
+struct TOption<'a> { //~ ERROR regions=[-]
v: Option<Box<T + 'a>>,
}
#![feature(rustc_attrs)]
#[rustc_variance]
-struct TestImm<A, B> { //~ ERROR types=[[+, +];[];[]]
+struct TestImm<A, B> { //~ ERROR types=[+, +]
x: A,
y: B,
}
#[rustc_variance]
-struct TestMut<A, B:'static> { //~ ERROR types=[[+, o];[];[]]
+struct TestMut<A, B:'static> { //~ ERROR types=[+, o]
x: A,
y: &'static mut B,
}
#[rustc_variance]
-struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[+, o];[];[]]
+struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[+, o]
m: TestMut<A, B>
}
#[rustc_variance]
-struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[[o, o];[];[]]
+struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[o, o]
n: TestMut<A, B>,
m: TestMut<B, A>
}
#[rustc_variance]
-trait Getter<A> { //~ ERROR types=[[o];[o];[]]
+trait Getter<A> { //~ ERROR types=[o, o]
fn get(&self) -> A;
}
#[rustc_variance]
-trait Setter<A> { //~ ERROR types=[[o];[o];[]]
+trait Setter<A> { //~ ERROR types=[o, o]
fn set(&mut self, a: A);
}
#[rustc_variance]
-trait GetterSetter<A> { //~ ERROR types=[[o];[o];[]]
+trait GetterSetter<A> { //~ ERROR types=[o, o]
fn get(&self) -> A;
fn set(&mut self, a: A);
}
#[rustc_variance]
-trait GetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
+trait GetterInTypeBound<A> { //~ ERROR types=[o, o]
// Here, the use of `A` in the method bound *does* affect
// variance. Think of it as if the method requested a dictionary
// for `T:Getter<A>`. Since this dictionary is an input, it is
}
#[rustc_variance]
-trait SetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
+trait SetterInTypeBound<A> { //~ ERROR types=[o, o]
fn do_it<T:Setter<A>>(&self);
}
#[rustc_variance]
-struct TestObject<A, R> { //~ ERROR types=[[o, o];[];[]]
+struct TestObject<A, R> { //~ ERROR types=[o, o]
n: Box<Setter<A>+Send>,
m: Box<Getter<R>+Send>,
}
// not considered bivariant.
#[rustc_variance]
-struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[];[]], regions=[[-];[];[]]
+struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[o, o], regions=[-]
t: &'a mut (A,B)
}
#[rustc_variance]
-struct InvariantCell<A> { //~ ERROR types=[[o];[];[]]
+struct InvariantCell<A> { //~ ERROR types=[o]
t: Cell<A>
}
#[rustc_variance]
-struct InvariantIndirect<A> { //~ ERROR types=[[o];[];[]]
+struct InvariantIndirect<A> { //~ ERROR types=[o]
t: InvariantCell<A>
}
#[rustc_variance]
-struct Covariant<A> { //~ ERROR types=[[+];[];[]]
+struct Covariant<A> { //~ ERROR types=[+]
t: A, u: fn() -> A
}
#[rustc_variance]
-struct Contravariant<A> { //~ ERROR types=[[-];[];[]]
+struct Contravariant<A> { //~ ERROR types=[-]
t: fn(A)
}
#[rustc_variance]
-enum Enum<A,B,C> { //~ ERROR types=[[+, -, o];[];[]]
+enum Enum<A,B,C> { //~ ERROR types=[+, -, o]
Foo(Covariant<A>),
Bar(Contravariant<B>),
Zed(Covariant<C>,Contravariant<C>)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-tidy-linelength
+
fn main() {
let a = 0;
{
// StorageLive(tmp1); // scope 1 at storage_ranges.rs:14:18: 14:25
// StorageLive(tmp2); // scope 1 at storage_ranges.rs:14:23: 14:24
// tmp2 = var0; // scope 1 at storage_ranges.rs:14:23: 14:24
-// tmp1 = std::prelude::v1::Some<i32>(tmp2,); // scope 1 at storage_ranges.rs:14:18: 14:25
+// tmp1 = std::option::Option<i32>::Some(tmp2,); // scope 1 at storage_ranges.rs:14:18: 14:25
// var1 = &tmp1; // scope 1 at storage_ranges.rs:14:17: 14:25
// StorageDead(tmp2); // scope 1 at storage_ranges.rs:14:23: 14:24
// tmp0 = (); // scope 2 at storage_ranges.rs:13:5: 15:6
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(unused_parens)]
+#![feature(plugin)]
+#![feature(plugin_registrar)]
+#![feature(rustc_private)]
+#![plugin(proc_macro)]
+
+extern crate rustc_plugin;
+extern crate proc_macro;
+extern crate syntax;
+
+use proc_macro::build::ident_eq;
+
+use syntax::ext::base::{ExtCtxt, MacResult};
+use syntax::ext::proc_macro_shim::build_block_emitter;
+use syntax::tokenstream::{TokenTree, TokenStream};
+use syntax::parse::token::str_to_ident;
+use syntax::codemap::Span;
+
+use rustc_plugin::Registry;
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("cond", cond);
+}
+
+fn cond<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
+ let output = cond_rec(TokenStream::from_tts(tts.clone().to_owned()));
+ build_block_emitter(cx, sp, output)
+}
+
+fn cond_rec(input: TokenStream) -> TokenStream {
+ if input.is_empty() {
+ return qquote!();
+ }
+
+ let next = input.slice(0..1);
+ let rest = input.slice_from(1..);
+
+ let clause : TokenStream = match next.maybe_delimited() {
+ Some(ts) => ts,
+ _ => panic!("Invalid input"),
+ };
+
+ // clause is ([test]) [rhs]
+ if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) }
+
+ let test: TokenStream = clause.slice(0..1);
+ let rhs: TokenStream = clause.slice_from(1..);
+
+ if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
+ qquote!({unquote(rhs)})
+ } else {
+ qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
+ }
+}
--- /dev/null
+// Copyright 2016 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.
+
+#![allow(unused_parens)]
+#![feature(plugin)]
+#![feature(plugin_registrar)]
+#![feature(rustc_private)]
+#![plugin(proc_macro)]
+
+extern crate rustc_plugin;
+extern crate proc_macro;
+extern crate syntax;
+
+use proc_macro::prelude::*;
+
+use rustc_plugin::Registry;
+
+use syntax::ast::Ident;
+use syntax::codemap::{DUMMY_SP, Span};
+use syntax::ext::proc_macro_shim::build_block_emitter;
+use syntax::ext::base::{ExtCtxt, MacResult};
+use syntax::parse::token::{self, Token, DelimToken, keywords, str_to_ident};
+use syntax::tokenstream::{TokenTree, TokenStream};
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("cond", cond);
+}
+
+fn cond<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
+ let output = cond_rec(TokenStream::from_tts(tts.clone().to_owned()));
+ build_block_emitter(cx, sp, output)
+}
+
+fn cond_rec(input: TokenStream) -> TokenStream {
+ if input.is_empty() {
+ return qquote!();
+ }
+
+ let next = input.slice(0..1);
+ let rest = input.slice_from(1..);
+
+ let clause : TokenStream = match next.maybe_delimited() {
+ Some(ts) => ts,
+ _ => panic!("Invalid input"),
+ };
+
+ // clause is ([test]) [rhs]
+ if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) }
+
+ let test: TokenStream = clause.slice(0..1);
+ let rhs: TokenStream = clause.slice_from(1..);
+
+ if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
+ qquote!({unquote(rhs)})
+ } else {
+ qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
+ }
+}
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(unused_parens)]
+#![feature(plugin)]
+#![feature(plugin_registrar)]
+#![feature(rustc_private)]
+#![plugin(proc_macro)]
+
+extern crate rustc_plugin;
+extern crate proc_macro;
+extern crate syntax;
+
+use syntax::ext::proc_macro_shim::prelude::*;
+use proc_macro::prelude::*;
+
+use rustc_plugin::Registry;
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("cond", cond);
+}
+
+fn cond<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'cx> {
+ let output = cond_rec(TokenStream::from_tts(tts.clone().to_owned()));
+ build_block_emitter(cx, sp, output)
+}
+
+fn cond_rec(input: TokenStream) -> TokenStream {
+ if input.is_empty() {
+ return qquote!();
+ }
+
+ let next = input.slice(0..1);
+ let rest = input.slice_from(1..);
+
+ let clause : TokenStream = match next.maybe_delimited() {
+ Some(ts) => ts,
+ _ => panic!("Invalid input"),
+ };
+
+ // clause is ([test]) [rhs]
+ if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) }
+
+ let test: TokenStream = clause.slice(0..1);
+ let rhs: TokenStream = clause.slice_from(1..);
+
+ if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
+ qquote!({unquote(rhs)})
+ } else {
+ qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
+ }
+}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-stage1
+
+#![feature(plugin)]
+#![feature(rustc_private)]
+#![plugin(proc_macro)]
+
+extern crate proc_macro;
+use proc_macro::prelude::*;
+
+extern crate syntax;
+use syntax::ast::Ident;
+use syntax::codemap::DUMMY_SP;
+use syntax::parse::token::{self, Token, keywords, str_to_ident};
+
+fn main() {
+ let lex_true = lex("true");
+ assert_eq!(qquote!(true).eq_unspanned(&lex_true), true);
+}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:cond_plugin.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![feature(rustc_private)]
+#![plugin(cond_plugin)]
+
+fn fact(n : i64) -> i64 {
+ if n == 0 {
+ 1
+ } else {
+ n * fact(n - 1)
+ }
+}
+
+fn fact_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ (else (n * fact_cond(n-1)))
+ )
+}
+
+fn fib(n : i64) -> i64 {
+ if n == 0 || n == 1 {
+ 1
+ } else {
+ fib(n-1) + fib(n-2)
+ }
+}
+
+fn fib_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ ((n == 1) 1)
+ (else (fib_cond(n-1) + fib_cond(n-2)))
+ )
+}
+
+fn main() {
+ assert_eq!(fact(3), fact_cond(3));
+ assert_eq!(fact(5), fact_cond(5));
+ assert_eq!(fib(5), fib_cond(5));
+ assert_eq!(fib(8), fib_cond(8));
+}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:cond_noprelude_plugin.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![feature(rustc_private)]
+#![plugin(cond_noprelude_plugin)]
+
+fn fact(n : i64) -> i64 {
+ if n == 0 {
+ 1
+ } else {
+ n * fact(n - 1)
+ }
+}
+
+fn fact_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ (else (n * fact_cond(n-1)))
+ )
+}
+
+fn fib(n : i64) -> i64 {
+ if n == 0 || n == 1 {
+ 1
+ } else {
+ fib(n-1) + fib(n-2)
+ }
+}
+
+fn fib_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ ((n == 1) 1)
+ (else (fib_cond(n-1) + fib_cond(n-2)))
+ )
+}
+
+fn main() {
+ assert_eq!(fact(3), fact_cond(3));
+ assert_eq!(fact(5), fact_cond(5));
+ assert_eq!(fib(5), fib_cond(5));
+ assert_eq!(fib(8), fib_cond(8));
+}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:cond_prelude_plugin.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![feature(rustc_private)]
+#![plugin(cond_prelude_plugin)]
+
+fn fact(n : i64) -> i64 {
+ if n == 0 {
+ 1
+ } else {
+ n * fact(n - 1)
+ }
+}
+
+fn fact_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ (else (n * fact_cond(n-1)))
+ )
+}
+
+fn fib(n : i64) -> i64 {
+ if n == 0 || n == 1 {
+ 1
+ } else {
+ fib(n-1) + fib(n-2)
+ }
+}
+
+fn fib_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ ((n == 1) 1)
+ (else (fib_cond(n-1) + fib_cond(n-2)))
+ )
+}
+
+fn main() {
+ assert_eq!(fact(3), fact_cond(3));
+ assert_eq!(fact(5), fact_cond(5));
+ assert_eq!(fib(5), fib_cond(5));
+ assert_eq!(fib(8), fib_cond(8));
+}
// @has assoc_types/trait.Index.html
pub trait Index<I: ?Sized> {
// @has - '//*[@id="associatedtype.Output"]//code' 'type Output: ?Sized'
+ // @has - '//*[@id="Output.t"]//code' 'type Output: ?Sized'
type Output: ?Sized;
+ // @has - '//*[@id="index.v"]//code' 'fn index'
// @has - '//*[@id="tymethod.index"]//code' \
// "fn index<'a>(&'a self, index: I) -> &'a Self::Output"
fn index<'a>(&'a self, index: I) -> &'a Self::Output;
fn deref(&self) -> &Foo { loop {} }
}
+// @has issue_19190/Bar.t.html
// @has issue_19190/struct.Bar.html
+// @has - '//*[@id="foo.v"]' 'fn foo(&self)'
// @has - '//*[@id="method.foo"]' 'fn foo(&self)'
+// @!has - '//*[@id="static_foo.v"]' 'fn static_foo()'
// @!has - '//*[@id="method.static_foo"]' 'fn static_foo()'
extern crate issue_21092;
+// @has issue_21092/Bar.t.html
// @has issue_21092/struct.Bar.html
// @has - '//*[@id="associatedtype.Bar"]' 'type Bar = i32'
pub use issue_21092::{Foo, Bar};
impl Foo<u8> {
// @has - '//*[@id="method.pass"]//code' 'fn pass()'
+ // @has - '//*[@id="pass.v"]//code' 'fn pass()'
pub fn pass() {}
}
impl Foo<u16> {
// @has - '//*[@id="method.pass-1"]//code' 'fn pass() -> usize'
+ // @has - '//*[@id="pass.v-1"]//code' 'fn pass() -> usize'
pub fn pass() -> usize { 42 }
}
impl Foo<u32> {
// @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize'
+ // @has - '//*[@id="pass.v-2"]//code' 'fn pass() -> isize'
pub fn pass() -> isize { 42 }
}
// @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/src-links.rs.html'
pub mod baz {
/// Dox
+ // @has foo/bar/baz/baz.v.html
// @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/src-links.rs.html'
pub fn baz() { }
}
/// Dox
+ // @has foo/bar/Foobar.t.html
// @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/src-links.rs.html'
pub trait Foobar { fn dummy(&self) { } }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// @has structfields/Foo.t.html
+// @has - struct.Foo.html
// @has structfields/struct.Foo.html
pub struct Foo {
// @has - //pre "pub a: ()"
pub d: usize,
}
+// @has structfields/Bar.t.html
+// @has - struct.Bar.html
// @has structfields/struct.Bar.html
pub struct Bar {
// @has - //pre "pub a: ()"
// @!has - //pre "// some fields omitted"
}
+// @has structfields/Qux.t.html
+// @has - enum.Qux.html
// @has structfields/enum.Qux.html
pub enum Qux {
Quz {
continue
}
+ // We want the compiler to depend on the proc_macro crate so that it is built and
+ // included in the end, but we don't want to actually use it in the compiler.
+ if toml.contains("name = \"rustc_driver\"") && krate == "proc_macro" {
+ continue
+ }
+
if !librs.contains(&format!("extern crate {}", krate)) {
println!("{} doesn't have `extern crate {}`, but Cargo.toml \
depends on it", libfile.display(), krate);