Merge branch 'master' into E0403-update-error-format

This commit is contained in:
Chris Stankus
2016-08-17 12:31:20 -05:00
151 changed files with 4447 additions and 4285 deletions
+5 -3
View File
@@ -60,7 +60,7 @@ RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_
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
@@ -100,6 +100,7 @@ DEPS_test := std getopts term native:rust_test_helpers
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
@@ -114,8 +115,9 @@ DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_m
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
+9 -6
View File
@@ -1453,10 +1453,11 @@ fn into_iter(mut self) -> IntoIter<T> {
} else {
begin.offset(self.len() as isize) as *const T
};
let buf = ptr::read(&self.buf);
let cap = self.buf.cap();
mem::forget(self);
IntoIter {
_buf: buf,
buf: Shared::new(begin),
cap: cap,
ptr: begin,
end: end,
}
@@ -1708,8 +1709,9 @@ fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
_buf: RawVec<T>,
ptr: *mut T,
buf: Shared<T>,
cap: usize,
ptr: *const T,
end: *const T,
}
@@ -1750,7 +1752,7 @@ pub fn as_slice(&self) -> &[T] {
#[unstable(feature = "vec_into_iter_as_slice", issue = "35601")]
pub fn as_mut_slice(&self) -> &mut [T] {
unsafe {
slice::from_raw_parts_mut(self.ptr, self.len())
slice::from_raw_parts_mut(self.ptr as *mut T, self.len())
}
}
}
@@ -1846,9 +1848,10 @@ impl<T> Drop for IntoIter<T> {
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) {
// destroy the remaining elements
for _x in self {}
for _x in self.by_ref() {}
// RawVec handles deallocation
let _ = unsafe { RawVec::from_raw_parts(*self.buf, self.cap) };
}
}
+18
View File
@@ -645,6 +645,24 @@ fn test_iter_size_hints() {
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];
+2 -1
View File
@@ -11,7 +11,7 @@
use std::borrow::Cow;
use std::iter::{FromIterator, repeat};
use std::mem::size_of;
use std::vec::Drain;
use std::vec::{Drain, IntoIter};
use test::Bencher;
@@ -537,6 +537,7 @@ fn test_cow_from() {
#[allow(dead_code)]
fn assert_covariance() {
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> { i }
}
#[bench]
+8
View File
@@ -37,6 +37,7 @@
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;
@@ -996,6 +997,13 @@ impl<'a, T> Clone for Iter<'a, T> {
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].
+15
View File
@@ -0,0 +1,15 @@
[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" }
+89
View File
@@ -0,0 +1,89 @@
// 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())
}
+137
View File
@@ -0,0 +1,137 @@
// 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);
}
+26
View File
@@ -0,0 +1,26 @@
// 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())))
}
+12
View File
@@ -0,0 +1,12 @@
// 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::*;
+470
View File
@@ -0,0 +1,470 @@
// 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
}
}
+2 -3
View File
@@ -9,7 +9,6 @@
// except according to those terms.
use hir::def_id::DefId;
use ty::subst::ParamSpace;
use util::nodemap::NodeMap;
use syntax::ast;
use hir;
@@ -31,7 +30,7 @@ pub enum Def {
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
@@ -122,7 +121,7 @@ pub fn def_id(&self) -> DefId {
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
+2 -3
View File
@@ -82,7 +82,6 @@
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;
@@ -1366,10 +1365,10 @@ fn rebuild_arg_ty_or_output(&self,
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();
+42 -87
View File
@@ -25,9 +25,7 @@
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};
@@ -1172,15 +1170,6 @@ pub fn next_ty_var(&self) -> Ty<'tcx> {
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))
}
@@ -1205,89 +1194,55 @@ pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region {
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()
/// Create a region inference variable for the given
/// region parameter definition.
pub fn region_var_for_def(&self,
span: Span,
def: &ty::RegionParameterDef)
-> ty::Region {
self.next_region_var(EarlyBoundRegion(span, def.name))
}
// 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,
span: Span,
space: subst::ParamSpace,
substs: &mut Substs<'tcx>,
defs: &[ty::TypeParameterDef<'tcx>]) {
/// 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
}
});
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);
}
let ty_var_id = self.type_variables
.borrow_mut()
.new_var(false, default);
self.tcx.mk_var(ty_var_id)
}
/// 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)));
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));
}
self.tcx.mk_substs(substs)
}
/// 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;
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 {
+9 -7
View File
@@ -154,7 +154,7 @@ fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
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>;
@@ -162,6 +162,8 @@ fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> 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>;
@@ -187,8 +189,7 @@ fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
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>>;
@@ -334,7 +335,7 @@ fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
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")
}
@@ -344,6 +345,8 @@ fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-> 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") }
@@ -379,8 +382,7 @@ fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
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") }
@@ -583,7 +585,7 @@ pub unsafe fn unsafe_with_encoding_context<F, R>(f: F) -> R
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;
}
+17 -8
View File
@@ -88,15 +88,24 @@ fn insert_def_id(&mut self, def_id: DefId) {
fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
use ty::TypeVariants::{TyEnum, TyStruct};
// 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),
_ => (),
});
let def = self.tcx.expect_def(id);
// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
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)
}
_ => {}
}
}
}
_ => {}
}
match def {
Def::Const(_) | Def::AssociatedConst(..) => {
self.check_def_id(def.def_id());
+24 -36
View File
@@ -24,9 +24,7 @@
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;
@@ -41,8 +39,7 @@
#[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),
@@ -90,10 +87,11 @@ struct LifetimeContext<'a, 'tcx: 'a> {
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>),
@@ -159,8 +157,7 @@ fn visit_item(&mut self, item: &hir::Item) {
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);
});
@@ -181,11 +178,7 @@ fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
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);
})
}
@@ -203,14 +196,13 @@ fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl,
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));
@@ -263,7 +255,7 @@ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
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 {
@@ -469,7 +461,7 @@ fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
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
@@ -557,7 +549,6 @@ fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
/// 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
@@ -576,7 +567,7 @@ fn visit_early_late<F>(&mut self,
.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);
@@ -606,11 +597,19 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
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;
}
@@ -672,7 +671,7 @@ fn resolve_free_lifetime_ref(&mut self,
break;
}
EarlyScope(_, lifetimes, s) |
EarlyScope(lifetimes, s) |
LateScope(lifetimes, s) => {
search_result = search_lifetimes(lifetimes, lifetime_ref);
if search_result.is_some() {
@@ -768,7 +767,7 @@ fn check_lifetime_def_for_shadowing(&self,
return;
}
EarlyScope(_, lifetimes, s) |
EarlyScope(lifetimes, s) |
LateScope(lifetimes, s) => {
if let Some((_, lifetime_def)) = search_lifetimes(lifetimes, lifetime) {
signal_shadowing_problem(
@@ -963,14 +962,3 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
}
}
}
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"),
}
}
}
+2 -7
View File
@@ -1073,10 +1073,7 @@ fn fmt_tuple(fmt: &mut Formatter, lvs: &[Operand]) -> fmt::Result {
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(()),
@@ -1169,9 +1166,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
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 ")?;
+3 -7
View File
@@ -14,7 +14,6 @@
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;
@@ -160,12 +159,9 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
// 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);
@@ -231,7 +227,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
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
}
@@ -275,7 +271,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
}
ty::TyTrait(ref tt) => {
tt.principal_def_id().is_local()
tt.principal.def_id().is_local()
}
ty::TyError => {
+9 -35
View File
@@ -31,7 +31,7 @@
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;
@@ -167,29 +167,6 @@ fn report_projection_error(&self,
});
}
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.
@@ -244,18 +221,19 @@ fn impl_similar_to(&self,
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);
@@ -293,14 +271,10 @@ fn on_unimplemented_note(&self,
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| {
+2 -3
View File
@@ -142,7 +142,7 @@ pub fn must_defer(tcx: TyCtxt<'a, 'gcx, 'tcx>,
// 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;
}
@@ -160,10 +160,9 @@ pub fn try_select(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
// 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(),
+2 -2
View File
@@ -17,7 +17,7 @@
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;
@@ -272,7 +272,7 @@ pub enum Vtable<'tcx, N> {
#[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>
}
+10 -19
View File
@@ -20,7 +20,6 @@
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;
@@ -146,10 +145,7 @@ fn supertraits_reference_self(self, trait_def_id: DefId) -> bool {
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(..) |
@@ -166,25 +162,20 @@ fn supertraits_reference_self(self, trait_def_id: DefId) -> bool {
}
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 {
@@ -214,7 +205,7 @@ fn object_safety_violation_for_method(self,
{
// 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;
}
@@ -231,7 +222,7 @@ pub fn is_vtable_safe_method(self,
-> 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;
}
@@ -274,7 +265,7 @@ fn virtual_call_violation_for_method(self,
}
// 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);
}
@@ -330,7 +321,7 @@ fn contains_illegal_self_type_reference(self,
ty.maybe_walk(|ty| {
match ty.sty {
ty::TyParam(ref param_ty) => {
if param_ty.space == SelfSpace {
if param_ty.is_self() {
error = true;
}
+4 -5
View File
@@ -811,7 +811,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
// 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,
@@ -1133,10 +1133,9 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
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);
+68 -66
View File
@@ -36,12 +36,13 @@
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;
@@ -1214,7 +1215,7 @@ fn match_projection_obligation_against_definition_bounds(
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(
@@ -1528,7 +1529,7 @@ fn assemble_candidates_from_object_ty(&mut self,
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);
@@ -1538,7 +1539,7 @@ fn assemble_candidates_from_object_ty(&mut self,
_ => {}
}
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");
@@ -1602,7 +1603,7 @@ fn assemble_candidates_for_unsizing(&mut self,
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);
@@ -1622,7 +1623,7 @@ fn assemble_candidates_for_unsizing(&mut self,
// 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.
@@ -1935,7 +1936,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
// 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) => {
@@ -2179,10 +2180,9 @@ fn confirm_default_impl_object_candidate(&mut self,
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();
@@ -2315,7 +2315,7 @@ fn confirm_object_candidate(&mut self,
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,
@@ -2476,7 +2476,8 @@ fn confirm_builtin_unsize_candidate(&mut self,
// 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);
@@ -2486,13 +2487,12 @@ fn confirm_builtin_unsize_candidate(&mut self,
// 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)
@@ -2503,8 +2503,8 @@ fn confirm_builtin_unsize_candidate(&mut self,
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()));
@@ -2512,12 +2512,12 @@ fn confirm_builtin_unsize_candidate(&mut self,
// 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)
}) {
@@ -2534,10 +2534,10 @@ fn confirm_builtin_unsize_candidate(&mut self,
};
// 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
@@ -2553,14 +2553,13 @@ fn confirm_builtin_unsize_candidate(&mut self,
}
// 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());
}
@@ -2586,17 +2585,15 @@ fn confirm_builtin_unsize_candidate(&mut self,
} 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);
}
@@ -2604,12 +2601,16 @@ fn confirm_builtin_unsize_candidate(&mut self,
// 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);
}
}
@@ -2620,11 +2621,15 @@ fn confirm_builtin_unsize_candidate(&mut self,
// 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)
@@ -2693,12 +2698,11 @@ fn match_impl(&mut self,
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,
@@ -2892,20 +2896,18 @@ fn impl_or_trait_obligations(&mut 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)
}
}
+9 -13
View File
@@ -18,7 +18,7 @@
// 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;
@@ -44,11 +44,10 @@ pub struct OverlapError {
/// 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:
///
@@ -101,7 +100,7 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
};
// 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?
@@ -141,11 +140,8 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
// 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()
@@ -188,10 +184,10 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
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,
@@ -122,19 +122,18 @@ fn insert(&mut self,
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))
+3 -20
View File
@@ -9,10 +9,8 @@
// 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;
@@ -349,20 +347,6 @@ pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a,
(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,
@@ -402,7 +386,7 @@ pub fn trait_ref_for_builtin_bound(self,
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) => {
@@ -422,7 +406,7 @@ pub fn predicate_for_trait_def(self,
{
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)
}
@@ -510,10 +494,9 @@ pub fn closure_trait_ref_and_return_type(self,
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))
}
+21 -27
View File
@@ -23,13 +23,13 @@
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};
@@ -63,6 +63,7 @@ pub struct CtxtArenas<'tcx> {
layout: TypedArena<Layout>,
// references
generics: TypedArena<ty::Generics<'tcx>>,
trait_defs: TypedArena<ty::TraitDef<'tcx>>,
adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
}
@@ -78,6 +79,7 @@ pub fn new() -> CtxtArenas<'tcx> {
stability: TypedArena::new(),
layout: TypedArena::new(),
generics: TypedArena::new(),
trait_defs: TypedArena::new(),
adt_defs: TypedArena::new()
}
@@ -341,7 +343,8 @@ pub struct GlobalCtxt<'tcx> {
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
@@ -583,13 +586,19 @@ pub fn node_type_insert(self, id: NodeId, ty: Ty<'gcx>) {
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
}
@@ -711,6 +720,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
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),
@@ -1150,12 +1160,6 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
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> {
@@ -1288,18 +1292,9 @@ pub fn mk_fn_ptr(self, fty: &'tcx 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,
@@ -1351,18 +1346,17 @@ pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> {
}
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> {
+2 -3
View File
@@ -9,7 +9,6 @@
// except according to those terms.
use hir::def_id::DefId;
use ty::subst;
use infer::type_variable;
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
@@ -243,7 +242,7 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
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))
@@ -258,7 +257,7 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
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()
+1 -1
View File
@@ -61,7 +61,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
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))
+12 -17
View File
@@ -8,7 +8,7 @@
// 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 {
@@ -77,7 +77,7 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
&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);
@@ -116,17 +116,16 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
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) => {
@@ -199,23 +198,19 @@ fn add_region(&mut self, r: ty::Region) {
}
}
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);
}
}
+3 -12
View File
@@ -40,7 +40,7 @@
//! 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};
@@ -140,17 +140,13 @@ fn fold_mt(&mut self, t: &ty::TypeAndMut<'tcx>) -> ty::TypeAndMut<'tcx> {
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)
}
@@ -177,11 +173,6 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
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)
+1 -1
View File
@@ -322,7 +322,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
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) |
+3 -2
View File
@@ -10,7 +10,7 @@
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};
@@ -30,7 +30,8 @@ fn to_dep_node(key: &$key) -> DepNode<DefId> { DepNode::$node_name(*key) }
}
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>> }
+132 -148
View File
@@ -28,7 +28,7 @@
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;
@@ -54,11 +54,13 @@
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};
@@ -171,15 +173,14 @@ pub fn with_fresh_ty_vars(selcx: &mut traits::SelectionContext<'a, 'gcx, 'tcx>,
-> 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);
@@ -346,7 +347,7 @@ pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
#[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,
@@ -358,7 +359,7 @@ pub struct Method<'tcx> {
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,
@@ -425,8 +426,17 @@ pub struct AssociatedType<'tcx> {
#[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)]
@@ -442,7 +452,7 @@ pub struct MethodCallee<'tcx> {
/// 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
@@ -713,7 +723,6 @@ pub enum ObjectLifetimeDefault {
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>>,
@@ -724,7 +733,6 @@ pub struct TypeParameterDef<'tcx> {
pub struct RegionParameterDef {
pub name: Name,
pub def_id: DefId,
pub space: subst::ParamSpace,
pub index: u32,
pub bounds: Vec<ty::Region>,
}
@@ -732,7 +740,6 @@ pub struct RegionParameterDef {
impl RegionParameterDef {
pub fn to_early_bound_region(&self) -> ty::Region {
ty::ReEarlyBound(ty::EarlyBoundRegion {
space: self.space,
index: self.index,
name: self.name,
})
@@ -747,59 +754,53 @@ pub fn to_bound_region(&self) -> ty::BoundRegion {
/// 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)
}
}
pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
-> InstantiatedPredicates<'tcx> {
InstantiatedPredicates {
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()
}
}
}
@@ -808,7 +809,7 @@ pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
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
@@ -833,9 +834,9 @@ pub enum Predicate<'tcx> {
/// 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),
}
@@ -971,7 +972,7 @@ fn dep_node(&self) -> DepNode<DefId> {
}
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> {
@@ -1113,7 +1114,7 @@ impl<'tcx> Predicate<'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()
@@ -1128,7 +1129,7 @@ pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
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))
@@ -1193,12 +1194,12 @@ pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
/// [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 {
@@ -1212,7 +1213,7 @@ pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
}
pub fn self_ty(&self) -> Ty<'tcx> {
self.substs.self_ty().unwrap()
self.substs.types[0]
}
pub fn input_types(&self) -> &[Ty<'tcx>] {
@@ -1220,7 +1221,7 @@ 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
}
}
@@ -1286,23 +1287,17 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
// 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))
}
_ => {
@@ -1320,11 +1315,8 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
// 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) => {
@@ -1334,8 +1326,6 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
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)
@@ -1345,8 +1335,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
};
tcx.construct_parameter_environment(
trait_item.span,
method_generics,
method_bounds,
method_ty.def_id,
extent)
}
_ => {
@@ -1363,13 +1352,10 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
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(..) |
@@ -1379,20 +1365,14 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
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))
}
_ => {
@@ -1413,11 +1393,8 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
}
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)
}
_ => {
@@ -1450,7 +1427,7 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
/// `lookup_predicates`.
#[derive(Clone, Debug)]
pub struct TypeScheme<'tcx> {
pub generics: Generics<'tcx>,
pub generics: &'tcx Generics<'tcx>,
pub ty: Ty<'tcx>,
}
@@ -1905,9 +1882,7 @@ fn sized_constraint_for_ty(
};
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) {
@@ -2158,7 +2133,7 @@ pub fn node_id_to_type_opt(self, id: NodeId) -> Option<Ty<'gcx>> {
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(),
}
@@ -2496,27 +2471,36 @@ pub fn item_name(self, id: DefId) -> ast::Name {
}
// 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
}
}
@@ -2545,6 +2529,13 @@ pub fn lookup_adt_def(self, did: DefId) -> AdtDef<'gcx> {
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(
@@ -2800,18 +2791,18 @@ pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
}
}
/// 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
@@ -2825,18 +2816,20 @@ pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> {
/// 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
}
}
@@ -2848,7 +2841,7 @@ pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
// 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
@@ -2860,30 +2853,21 @@ pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
/// 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.
@@ -2891,8 +2875,7 @@ pub fn construct_free_substs(self, generics: &Generics<'gcx>,
/// 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>
{
@@ -2900,16 +2883,17 @@ pub fn construct_parameter_environment(self,
// 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
@@ -2925,7 +2909,7 @@ pub fn construct_parameter_environment(self,
//
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,
+67 -111
View File
@@ -14,7 +14,7 @@
//! 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;
@@ -145,82 +145,21 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
-> RelateResult<'tcx, &'tcx Substs<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
let mut substs = Substs::empty();
let tcx = relation.tcx();
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);
}
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()?;
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 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()?;
Ok(relation.tcx().mk_substs(substs))
}
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())));
}
(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> {
@@ -326,24 +265,33 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
}
}
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
@@ -361,27 +309,6 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
}
}
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,
@@ -416,6 +343,23 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
}
}
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>,
@@ -466,7 +410,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
}
(&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)
}
@@ -478,11 +422,23 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
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))
+66 -86
View File
@@ -9,8 +9,8 @@
// 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;
@@ -80,10 +80,20 @@ fn lift_to_tcx(&self, _: TyCtxt) -> Option<ty::Region> {
}
}
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
})
@@ -141,6 +151,19 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
}
}
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> {
@@ -427,26 +450,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> {
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> {
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)
}
}
@@ -599,8 +616,17 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
}
}
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 {
@@ -666,13 +692,11 @@ fn 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 {
@@ -741,30 +765,11 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
}
}
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,
@@ -805,7 +810,6 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
ty::RegionParameterDef {
name: self.name,
def_id: self.def_id,
space: self.space,
index: self.index,
bounds: self.bounds.fold_with(folder),
}
@@ -816,31 +820,6 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
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 {
@@ -893,6 +872,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
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 {
@@ -986,19 +979,6 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
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 {
+97 -95
View File
@@ -13,7 +13,7 @@
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;
@@ -152,7 +152,7 @@ pub enum TypeVariants<'tcx> {
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`.
@@ -291,57 +291,11 @@ fn decode<D: Decoder>(d: &mut D) -> Result<ClosureSubsts<'tcx>, D::Error> {
}
#[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,
@@ -350,8 +304,8 @@ pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
/// 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.
@@ -392,6 +346,42 @@ pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
}
}
/// 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 ==
@@ -508,33 +498,34 @@ pub fn variadic(&self) -> bool {
#[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
}
}
}
@@ -686,7 +677,6 @@ pub enum Region {
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub struct EarlyBoundRegion {
pub space: subst::ParamSpace,
pub index: u32,
pub name: Name,
}
@@ -730,27 +720,40 @@ pub enum InferTy {
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
})
}
}
@@ -942,16 +945,16 @@ pub fn is_phantom_data(&self) -> bool {
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
}
}
@@ -1185,7 +1188,7 @@ pub fn is_fn(&self) -> bool {
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),
@@ -1209,21 +1212,20 @@ pub fn regions(&self) -> Vec<ty::Region> {
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(_) |
+145 -463
View File
@@ -10,61 +10,93 @@
// 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>
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
t: Vec<Ty<'tcx>>,
r: Vec<ty::Region>)
-> &'tcx Substs<'tcx>
{
Substs { types: t, regions: r }
tcx.mk_substs(Substs { types: t, regions: r })
}
pub fn new_type(t: Vec<Ty<'tcx>>,
r: Vec<ty::Region>)
-> Substs<'tcx>
{
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
}
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()))
t.insert(0, s);
Substs::new(tcx, t, r)
}
pub fn empty() -> Substs<'tcx> {
Substs {
types: VecPerParamSpace::empty(),
regions: VecPerParamSpace::empty(),
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)
};
substs.fill_item(tcx, defs, &mut mk_region, &mut mk_type);
Substs::new(tcx, substs.types, substs.regions)
}
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);
}
for def in &defs.regions {
let region = mk_region(def, self);
assert_eq!(def.index as usize, self.regions.len());
self.regions.push(region);
}
for def in &defs.types {
let ty = mk_type(def, self);
assert_eq!(def.index as usize, self.types.len());
self.types.push(ty);
}
}
@@ -73,69 +105,32 @@ pub fn is_noop(&self) -> bool {
}
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)
self.types[ty_param_def.index as usize]
}
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
self.types.get_self().cloned()
pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region {
self.regions[def.index as usize]
}
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
}
pub fn erase_regions(self) -> Substs<'tcx> {
let Substs { types, regions } = self;
let regions = regions.map(|_| ty::ReErased);
Substs { types: types, regions: regions }
}
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 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 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 }
}
/// 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);
@@ -144,384 +139,16 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
}
}
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`
@@ -596,7 +223,7 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
// 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)
}
@@ -606,10 +233,9 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
span,
"Region parameter out of range \
when substituting in region {} (root type={:?}) \
(space={:?}, index={})",
(index={})",
data.name,
self.root_ty,
data.space,
data.index);
}
}
@@ -652,18 +278,17 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
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);
@@ -733,3 +358,60 @@ fn shift_region_through_binders(&self, region: ty::Region) -> ty::Region {
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)
}
})
}
}
+2 -2
View File
@@ -34,7 +34,7 @@ pub struct TraitDef<'tcx> {
/// `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>,
@@ -76,7 +76,7 @@ pub struct TraitDef<'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> {
+8 -12
View File
@@ -11,7 +11,6 @@
//! 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};
@@ -451,21 +450,21 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
// 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);
}
@@ -477,7 +476,6 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
self.hash(tys.len());
}
TyParam(p) => {
self.hash(p.space);
self.hash(p.idx);
self.hash(p.name.as_str());
}
@@ -695,12 +693,10 @@ fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
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
+7 -7
View File
@@ -79,28 +79,28 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
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) => {
+9 -15
View File
@@ -261,7 +261,6 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
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(),
@@ -406,13 +405,13 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
// 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(),
@@ -476,7 +475,7 @@ fn nominal_obligations(&mut self,
.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 { }
@@ -512,10 +511,10 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) {
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));
@@ -534,7 +533,7 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) {
/// `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>
{
@@ -543,13 +542,8 @@ pub fn object_region_bounds<'a, 'gcx, 'tcx>(
// 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)
}
+137 -152
View File
@@ -10,7 +10,7 @@
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};
@@ -56,78 +56,75 @@ fn fn_sig(f: &mut fmt::Formatter,
}
/// 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);
}
}
@@ -170,23 +167,11 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
Ok(())
};
print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?;
print_regions(f, "<", &substs.regions[..num_regions])?;
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
}
})
};
let tps = &substs.types[..num_types];
let tps = substs.types.get_slice(subst::TypeSpace);
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)?;
}
@@ -204,7 +189,7 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
if ns == Ns::Value {
empty.set(true);
if substs.self_ty().is_some() {
if has_self {
write!(f, ">")?;
}
@@ -212,10 +197,10 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
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)?;
}
@@ -288,7 +273,8 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
/// 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 {
@@ -306,29 +292,32 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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)?;
}
@@ -337,7 +326,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 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)?;
}
@@ -348,19 +337,19 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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)
}
}
@@ -379,7 +368,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
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)
@@ -397,10 +386,20 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 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, &[])
})
}
}
@@ -448,11 +447,38 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
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(())
}
}
@@ -509,8 +535,7 @@ impl fmt::Debug for ty::Region {
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)
}
@@ -668,38 +693,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
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();
@@ -814,8 +807,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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, &[])
}
}
@@ -868,9 +860,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
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) => {
@@ -893,12 +883,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
!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, &[])
}
})
}
@@ -910,14 +895,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// 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() {
@@ -1034,7 +1019,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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)
}
}
@@ -16,7 +16,7 @@
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;
@@ -859,10 +859,7 @@ fn unelaborated_free_block<'a>(
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 {
+8 -8
View File
@@ -22,8 +22,9 @@
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;
@@ -93,7 +94,7 @@ fn variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId)
/// 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) {
@@ -110,7 +111,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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
@@ -1045,16 +1047,14 @@ fn infer<'a, 'tcx>(i: ConstInt,
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(),
+2 -1
View File
@@ -33,4 +33,5 @@ rustc_metadata = { path = "../librustc_metadata" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
syntax_pos = { path = "../libsyntax_pos" }
syntax_pos = { path = "../libsyntax_pos" }
proc_macro = { path = "../libproc_macro" }
+13 -16
View File
@@ -20,8 +20,7 @@
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};
@@ -276,19 +275,17 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
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,
})
@@ -674,12 +671,12 @@ fn subst_ty_renumber_bound() {
// 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 = {
@@ -709,12 +706,12 @@ fn subst_ty_renumber_some_bounds() {
// 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))
//
@@ -755,7 +752,7 @@ fn escaping() {
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());
@@ -771,12 +768,12 @@ fn subst_region_renumber_region() {
// 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)
//
+4 -7
View File
@@ -465,16 +465,14 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
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,
};
@@ -898,7 +896,7 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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 =
@@ -918,8 +916,7 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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.
+10 -59
View File
@@ -34,7 +34,7 @@
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;
@@ -413,7 +413,7 @@ fn tr(&self, dcx: &DecodeContext) -> Def {
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);
@@ -507,7 +507,7 @@ fn read_method_callee<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
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()
@@ -524,16 +524,8 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
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>);
@@ -556,39 +548,6 @@ fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'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;
@@ -610,7 +569,7 @@ fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapt
}
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)));
@@ -879,10 +838,8 @@ fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> 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>)
@@ -902,7 +859,7 @@ fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, '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> {
@@ -927,7 +884,7 @@ fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
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(
@@ -988,14 +945,8 @@ fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
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))
@@ -1189,7 +1140,7 @@ fn decode_side_tables(dcx: &DecodeContext,
}
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);
+6 -12
View File
@@ -196,20 +196,14 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f
// 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;
+11 -4
View File
@@ -86,7 +86,7 @@ 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>
{
self.dep_graph.read(DepNode::MetaData(def));
let cdata = self.get_crate_data(def.krate);
@@ -109,6 +109,14 @@ fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
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));
@@ -231,11 +239,10 @@ fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
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)
+30 -71
View File
@@ -35,7 +35,6 @@
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};
@@ -265,11 +264,6 @@ fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata:
})
}
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,
@@ -384,7 +378,7 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd,
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);
@@ -494,7 +488,7 @@ fn get_struct_variant<'tcx>(cdata: Cmd,
// 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);
@@ -514,7 +508,7 @@ fn get_struct_variant<'tcx>(cdata: Cmd,
} 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);
@@ -531,7 +525,7 @@ pub fn get_predicates<'a, 'tcx>(cdata: Cmd,
-> 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,
@@ -543,17 +537,20 @@ 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> {
@@ -961,8 +958,8 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a
}))
}
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,
@@ -1394,10 +1391,7 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
}
}
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,
@@ -1406,10 +1400,6 @@ pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd,
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
}
}
@@ -1538,11 +1528,7 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd,
};
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,
};
@@ -1574,31 +1560,13 @@ pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
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,
@@ -1622,21 +1590,12 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
{
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));
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()
}
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 { predicates: predicates }
}
pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool {
+20 -51
View File
@@ -26,7 +26,6 @@
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;
@@ -176,8 +175,7 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
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);
}
@@ -511,56 +509,29 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
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();
}
@@ -571,8 +542,7 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
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 {
@@ -653,9 +623,9 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
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,
@@ -702,7 +672,7 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
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);
}
@@ -1141,9 +1111,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
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);
+1 -1
View File
@@ -74,7 +74,7 @@ fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx> {
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)
};
+90 -67
View File
@@ -20,8 +20,7 @@
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;
@@ -129,24 +128,48 @@ fn parse_size(&mut self) -> Option<usize> {
}
}
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());
}
r
assert_eq!(self.next(), '|');
while self.peek() != ']' {
types.push(self.parse_ty());
}
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 {
@@ -196,13 +219,10 @@ pub fn parse_region(&mut self) -> ty::Region {
}
'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
})
@@ -302,9 +322,17 @@ fn parse_str(&mut self, term: char) -> String {
}
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> {
@@ -336,23 +364,41 @@ 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()),
@@ -380,7 +426,7 @@ pub fn parse_ty(&mut self) -> Ty<'tcx> {
}
'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' => {
@@ -426,7 +472,7 @@ 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 self.tcx.mk_struct(def, self.tcx.mk_substs(substs));
return self.tcx.mk_struct(def, substs);
}
'k' => {
assert_eq!(self.next(), '[');
@@ -438,7 +484,7 @@ pub fn parse_ty(&mut self) -> Ty<'tcx> {
}
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(), '[');
@@ -451,7 +497,7 @@ pub fn parse_ty(&mut self) -> Ty<'tcx> {
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;
@@ -495,10 +541,6 @@ fn parse_u32(&mut self) -> u32 {
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 == ']');
@@ -588,11 +630,17 @@ fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
}
}
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();
@@ -602,7 +650,6 @@ pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
ty::TypeParameterDef {
name: name,
def_id: def_id,
space: space,
index: index,
default_def_id: default_def_id,
default: default,
@@ -610,11 +657,9 @@ pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
}
}
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![];
@@ -630,7 +675,6 @@ pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
ty::RegionParameterDef {
name: name,
def_id: def_id,
space: space,
index: index,
bounds: bounds,
}
@@ -649,27 +693,6 @@ fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
}
}
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 {
+80 -68
View File
@@ -19,9 +19,7 @@
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;
@@ -104,11 +102,26 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
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) => {
@@ -149,8 +162,8 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
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));
@@ -235,27 +248,42 @@ fn enc_opt<T, F>(w: &mut Cursor<Vec<u8>>, t: Option<T>, enc_f: F) where
}
}
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) {
@@ -266,8 +294,7 @@ 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);
}
@@ -344,6 +371,12 @@ pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
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"),
@@ -386,7 +419,7 @@ fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
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"),
@@ -399,42 +432,19 @@ pub fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinB
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);
@@ -489,7 +499,9 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
}
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");
@@ -509,10 +521,10 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
}
}
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);
}
+2 -5
View File
@@ -89,7 +89,7 @@
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;
@@ -750,10 +750,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-> 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,
+3 -3
View File
@@ -147,16 +147,16 @@ pub fn trait_method(&mut self,
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,
});
}
}
+8 -24
View File
@@ -49,7 +49,6 @@
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};
@@ -561,7 +560,7 @@ fn visit_variant(&mut self,
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,
};
@@ -629,10 +628,6 @@ enum TypeParameters<'a, 'b> {
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>),
}
@@ -1617,12 +1612,9 @@ fn resolve_item(&mut self, item: &Item) {
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));
}
@@ -1638,10 +1630,7 @@ fn resolve_item(&mut self, item: &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);
@@ -1664,7 +1653,6 @@ fn resolve_item(&mut self, item: &Item) {
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)
@@ -1733,10 +1721,10 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
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 = HashMap::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);
@@ -1751,7 +1739,7 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
// 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));
}
@@ -1923,10 +1911,7 @@ fn resolve_implementation(&mut self,
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);
@@ -1959,7 +1944,6 @@ fn resolve_implementation(&mut self,
// 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);
+2 -3
View File
@@ -299,8 +299,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
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));
}
@@ -491,7 +490,7 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
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),
+1 -1
View File
@@ -895,7 +895,7 @@ fn compare_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
&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)
}
+2 -2
View File
@@ -48,7 +48,7 @@
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;
@@ -544,7 +544,7 @@ fn find_ptr<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> Option<DiscrField> {
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| {
+1 -1
View File
@@ -252,7 +252,7 @@ pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
// 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())
+10 -20
View File
@@ -39,7 +39,7 @@
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;
@@ -218,7 +218,7 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// 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))
@@ -562,14 +562,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
// 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))
}
@@ -675,14 +670,9 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx
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) {
@@ -1418,7 +1408,7 @@ pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
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));
@@ -2183,7 +2173,7 @@ fn create_entry_fn(ccx: &CrateContext,
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 =
@@ -2480,8 +2470,8 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
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
+11 -15
View File
@@ -22,7 +22,7 @@
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};
@@ -105,13 +105,12 @@ pub fn method<'blk>(bcx: Block<'blk, 'tcx>,
/// 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)
@@ -144,24 +143,21 @@ pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>,
/// 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
@@ -275,7 +271,7 @@ pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>)
/// 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)
@@ -427,7 +423,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
/// - `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();
+30 -41
View File
@@ -195,7 +195,7 @@
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;
@@ -732,7 +732,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
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);
}
@@ -753,8 +753,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
.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,
@@ -770,7 +769,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
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);
}
@@ -854,26 +853,15 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
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!()
}
@@ -903,13 +891,12 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
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:
@@ -919,10 +906,10 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
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))
}
@@ -1055,8 +1042,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
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) {
@@ -1077,7 +1063,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
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
}
@@ -1233,38 +1219,41 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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);
+2 -2
View File
@@ -523,7 +523,7 @@ pub fn eh_personality(&self) -> ValueRef {
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() {
@@ -550,7 +550,7 @@ pub fn eh_unwind_resume(&self) -> Callee<'tcx> {
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 {
+4 -4
View File
@@ -208,7 +208,7 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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);
@@ -222,7 +222,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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);
@@ -271,7 +271,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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();
@@ -1160,7 +1160,7 @@ pub fn trans_static(ccx: &CrateContext,
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())?;
+4 -16
View File
@@ -30,7 +30,7 @@
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;
@@ -571,16 +571,9 @@ pub fn translation_items(&self) -> &RefCell<FnvHashSet<TransItem<'tcx>>> {
/// 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> {
@@ -999,11 +992,6 @@ pub fn translation_items(&self) -> &RefCell<FnvHashSet<TransItem<'tcx>>> {
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>);
+2 -2
View File
@@ -401,7 +401,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, '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
}
@@ -429,6 +429,6 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
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
}
+5 -5
View File
@@ -27,7 +27,7 @@
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};
@@ -315,7 +315,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
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.
@@ -346,7 +346,7 @@ fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
// 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('<');
@@ -627,7 +627,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// 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(): {:?}",
@@ -1086,7 +1086,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
// 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,
}
+16 -5
View File
@@ -266,7 +266,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// 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,
@@ -358,7 +358,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
name_to_append_suffix_to: &mut String)
-> DIArray
{
let actual_types = param_substs.types.as_slice();
let actual_types = &param_substs.types;
if actual_types.is_empty() {
return create_DIArray(DIB(cx), &[]);
@@ -381,10 +381,11 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// 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),
@@ -403,6 +404,16 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
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) {
+2 -2
View File
@@ -12,7 +12,7 @@
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;
@@ -173,7 +173,7 @@ fn push_item_name(cx: &CrateContext,
// 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;
+1 -1
View File
@@ -175,7 +175,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
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,
+2 -2
View File
@@ -50,7 +50,7 @@ pub fn trans_exchange_free_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
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
}
@@ -356,7 +356,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
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,
+29 -30
View File
@@ -15,8 +15,7 @@
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::*;
@@ -137,8 +136,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
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);
@@ -347,12 +346,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
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]);
@@ -363,11 +362,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
}
}
(_, "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]);
@@ -377,12 +376,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
}
}
(_, "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 {
@@ -396,22 +395,22 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
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);
@@ -423,7 +422,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
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))
}
@@ -442,7 +441,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
copy_intrinsic(bcx,
false,
false,
*substs.types.get(FnSpace, 0),
substs.types[0],
llargs[1],
llargs[0],
llargs[2],
@@ -452,7 +451,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
copy_intrinsic(bcx,
true,
false,
*substs.types.get(FnSpace, 0),
substs.types[0],
llargs[1],
llargs[0],
llargs[2],
@@ -461,7 +460,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
(_, "write_bytes") => {
memset_intrinsic(bcx,
false,
*substs.types.get(FnSpace, 0),
substs.types[0],
llargs[0],
llargs[1],
llargs[2],
@@ -472,7 +471,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
copy_intrinsic(bcx,
false,
true,
*substs.types.get(FnSpace, 0),
substs.types[0],
llargs[0],
llargs[1],
llargs[2],
@@ -482,7 +481,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
copy_intrinsic(bcx,
true,
true,
*substs.types.get(FnSpace, 0),
substs.types[0],
llargs[0],
llargs[1],
llargs[2],
@@ -491,14 +490,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
(_, "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());
@@ -510,7 +509,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
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]));
@@ -610,10 +609,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
},
(_, "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)
}
@@ -664,7 +663,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
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],
@@ -683,7 +682,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
}
"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 {
@@ -696,7 +695,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
}
"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 {
@@ -735,7 +734,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
_ => 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 {
@@ -1284,7 +1283,7 @@ fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
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],
+14 -15
View File
@@ -15,8 +15,7 @@
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::*;
@@ -221,20 +220,20 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
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()
@@ -260,7 +259,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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;
}
@@ -270,15 +269,13 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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);
@@ -289,7 +286,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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;
}
@@ -309,8 +306,9 @@ pub struct ImplMethod<'tcx> {
/// 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>
{
@@ -322,6 +320,7 @@ pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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(|| {
+3 -6
View File
@@ -232,12 +232,9 @@ fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
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);
+2 -3
View File
@@ -12,7 +12,6 @@
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;
@@ -33,7 +32,7 @@
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());
@@ -174,7 +173,7 @@ pub struct Instance<'tcx> {
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, &[])
}
}
+2 -1
View File
@@ -486,7 +486,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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));
}
+7 -8
View File
@@ -28,7 +28,7 @@
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};
@@ -352,8 +352,7 @@ pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
},
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)
},
};
@@ -476,10 +475,10 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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 } ) |
@@ -561,8 +560,8 @@ fn push_item_name(tcx: TyCtxt,
}
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;
@@ -577,7 +576,7 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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);
+2 -9
View File
@@ -11,7 +11,6 @@
#![allow(non_camel_case_types)]
use rustc::hir::def_id::DefId;
use rustc::ty::subst;
use abi::FnType;
use adt;
use common::*;
@@ -257,18 +256,13 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
// 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")
}
@@ -336,8 +330,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
// 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[..])
}
}
+393 -518
View File
@@ -55,8 +55,7 @@
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;
@@ -82,6 +81,10 @@ pub trait AstConv<'gcx, 'tcx> {
/// 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.
@@ -116,11 +119,15 @@ fn trait_defines_associated_type_named(&self, trait_def_id: DefId, name: ast::Na
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
@@ -166,6 +173,11 @@ struct ConvertedBinding<'tcx> {
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) {
@@ -195,9 +207,8 @@ pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime)
issue_32330))
}
Some(&rl::DefEarlyBoundRegion(space, index, _)) => {
Some(&rl::DefEarlyBoundRegion(index, _)) => {
ty::ReEarlyBound(ty::EarlyBoundRegion {
space: space,
index: index,
name: lifetime.name
})
@@ -340,66 +351,87 @@ pub fn ast_path_substs_for_ty(&self,
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);
@@ -415,184 +447,112 @@ fn create_region_substs(&self,
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);
}
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.
}
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);
}
// 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);
}
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 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;
}
}
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 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
}
}
});
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
})]
}
};
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;
}
}
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
}
}
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, &region_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
@@ -657,29 +617,18 @@ fn convert_ty_with_lifetime_elision(&self,
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, &region_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,
@@ -698,13 +647,13 @@ fn convert_parenthesized_parameters(&self,
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>
{
@@ -729,7 +678,7 @@ pub fn instantiate_poly_trait_ref(&self,
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);
@@ -755,32 +704,12 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
}
}
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>>)
@@ -803,21 +732,14 @@ fn ast_path_to_poly_trait_ref(&self,
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);
@@ -829,7 +751,7 @@ fn ast_path_to_mono_trait_ref(&self,
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>
{
@@ -849,7 +771,7 @@ fn create_substs_for_ast_trait_ref(&self,
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>>)
{
@@ -865,8 +787,8 @@ fn create_substs_for_ast_trait_ref(&self,
}
};
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 {
@@ -877,10 +799,8 @@ fn create_substs_for_ast_trait_ref(&self,
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 {
@@ -889,26 +809,21 @@ fn create_substs_for_ast_trait_ref(&self,
"\
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>
{
@@ -962,62 +877,39 @@ fn ast_type_binding_to_poly_projection_predicate(
// 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,
}
}))
}
@@ -1030,10 +922,8 @@ fn ast_path_to_ty(&self,
-> 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;
}
@@ -1042,23 +932,24 @@ fn ast_path_to_ty(&self,
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
@@ -1071,33 +962,32 @@ fn ast_ty_to_trait_ref(&self,
* 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));
@@ -1136,44 +1026,93 @@ fn ast_ty_to_trait_ref(&self,
}
}
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,
&region_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() {
@@ -1193,7 +1132,7 @@ fn make_object_type(&self,
}
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
@@ -1203,7 +1142,7 @@ fn make_object_type(&self,
})
.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);
@@ -1219,7 +1158,14 @@ fn make_object_type(&self,
.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,
@@ -1379,8 +1325,9 @@ fn associated_path_def_to_ty(&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,
@@ -1390,10 +1337,13 @@ fn associated_path_def_to_ty(&self,
}
}
_ => {
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);
}
};
@@ -1453,7 +1403,7 @@ fn qpath_to_ty(&self,
span,
param_mode,
trait_def_id,
Some(self_ty),
self_ty,
trait_segment);
debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
@@ -1468,24 +1418,20 @@ fn qpath_to_ty(&self,
/// # 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)
@@ -1515,23 +1461,17 @@ fn base_def_to_ty(&self,
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);
@@ -1541,9 +1481,25 @@ fn base_def_to_ty(&self,
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).
@@ -1671,18 +1627,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
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 {
@@ -1759,7 +1704,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
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};
@@ -1767,7 +1712,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
// 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`.
@@ -1778,7 +1723,8 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
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
@@ -1829,7 +1775,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
// 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)
}
};
@@ -1846,7 +1792,7 @@ pub fn ty_of_arg(&self,
{
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),
}
}
@@ -2068,8 +2014,7 @@ pub fn ty_of_closure(&self,
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!(),
@@ -2087,28 +2032,7 @@ pub fn ty_of_closure(&self,
}
}
/// 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])
@@ -2116,75 +2040,24 @@ fn conv_ty_poly_trait_ref(&self,
{
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,
&region_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
@@ -2195,7 +2068,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds(&self,
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
{
@@ -2226,7 +2099,7 @@ fn compute_object_lifetime_bound(&self,
// 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.
@@ -2279,7 +2152,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
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,
@@ -2310,7 +2183,9 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
}
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"
+7 -12
View File
@@ -547,10 +547,7 @@ fn check_pat_path(&self,
}
// 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);
}
@@ -607,18 +604,16 @@ fn check_pat_tuple_struct(&self,
}
// 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.
+1 -1
View File
@@ -101,7 +101,7 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
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);
+1 -1
View File
@@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
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() {
+6 -8
View File
@@ -13,7 +13,6 @@
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;
@@ -102,12 +101,11 @@ fn deduce_expectations_from_expected_type(&self, expected_ty: Ty<'tcx>)
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)) => {
@@ -205,7 +203,7 @@ fn deduce_sig_from_projection(&self,
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);
+24 -37
View File
@@ -13,7 +13,7 @@
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_};
@@ -95,8 +95,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}
}
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{} \
@@ -194,10 +194,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// 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);
@@ -208,7 +206,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
impl_m,
&trait_m.generics,
&impl_m.generics,
&trait_to_skol_substs,
trait_to_skol_substs,
impl_to_skol_substs) {
return;
}
@@ -216,58 +214,49 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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);
let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap());
let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
debug!("compare_impl_method: impl_bounds={:?}", impl_bounds);
// 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);
@@ -322,7 +311,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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,
@@ -390,8 +379,8 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-> 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={:?} \
@@ -453,16 +442,14 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
// 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(|_| {
+11 -19
View File
@@ -15,7 +15,7 @@
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;
@@ -41,16 +41,14 @@
/// 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,
@@ -73,8 +71,7 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()>
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;
@@ -93,8 +90,8 @@ fn ensure_drop_params_and_item_params_correspond<'a, '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) {
@@ -131,7 +128,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
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`.
@@ -179,10 +176,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
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
@@ -190,10 +184,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
// '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
@@ -446,7 +438,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
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)
}
+9 -9
View File
@@ -13,7 +13,7 @@
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};
@@ -36,11 +36,11 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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 {
@@ -49,7 +49,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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 \
@@ -70,7 +70,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
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;
@@ -316,12 +316,12 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
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 {
+53 -68
View File
@@ -12,7 +12,7 @@
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};
@@ -42,10 +42,6 @@ struct InstantiatedMethodSig<'tcx> {
/// 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>,
@@ -105,9 +101,8 @@ fn confirm(&mut self,
// 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.
@@ -198,7 +193,7 @@ fn adjust_self_ty(&mut self,
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 => {
@@ -210,7 +205,7 @@ fn fresh_receiver_substs(&mut self,
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
@@ -222,16 +217,16 @@ fn fresh_receiver_substs(&mut self,
// 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
})
}
@@ -249,35 +244,36 @@ fn fresh_receiver_substs(&mut self,
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
@@ -288,7 +284,7 @@ fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R wh
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,
}
})
@@ -303,59 +299,49 @@ fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R wh
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,
@@ -382,7 +368,7 @@ 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={:?})",
@@ -393,7 +379,7 @@ fn instantiate_method_sig(&mut self,
// 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);
@@ -411,20 +397,19 @@ fn instantiate_method_sig(&mut self,
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,
+17 -23
View File
@@ -13,7 +13,7 @@
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};
@@ -182,31 +182,25 @@ pub fn lookup_method_in_trait_adjusted(&self,
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();
@@ -226,8 +220,8 @@ pub fn lookup_method_in_trait_adjusted(&self,
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);
+55 -67
View File
@@ -16,8 +16,7 @@
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};
@@ -80,9 +79,9 @@ struct Candidate<'tcx> {
#[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,
@@ -290,8 +289,8 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
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, _) => {
@@ -421,10 +420,10 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
}
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.
@@ -445,7 +444,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
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);
@@ -456,7 +455,7 @@ fn assemble_inherent_candidates_from_object(&mut self,
// 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);
@@ -519,14 +518,10 @@ fn assemble_inherent_candidates_from_param(&mut self,
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
@@ -665,7 +660,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
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);
@@ -753,14 +748,19 @@ fn assemble_closure_candidates(&mut self,
// 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(),
@@ -799,7 +799,7 @@ fn assemble_projection_candidates(&mut self,
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
@@ -1192,7 +1192,7 @@ fn record_static_candidate(&mut self, source: CandidateSource) {
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() {
@@ -1205,7 +1205,7 @@ fn xform_self_ty(&self,
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={:?})",
@@ -1220,64 +1220,52 @@ fn xform_method_self_ty(&self,
// 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 impl_ty = self.tcx.lookup_item_type(impl_def_id).ty;
let type_vars =
impl_pty.generics.types.map(
|_| self.next_ty_var());
let substs = Substs::for_item(self.tcx, impl_def_id,
|_, _| ty::ReErased,
|_, _| self.next_ty_var());
let region_placeholders =
impl_pty.generics.regions.map(
|_| ty::ReErased); // see erase_late_bound_regions() for an expl of why 'erased
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
+3 -5
View File
@@ -54,10 +54,8 @@ fn is_fn_ty(&self, ty: &Ty<'tcx>, span: Span) -> bool {
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,
@@ -358,7 +356,7 @@ fn is_local(ty: Ty) -> bool {
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,
+245 -426
View File
@@ -88,9 +88,8 @@
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};
@@ -745,26 +744,20 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
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);
@@ -872,9 +865,9 @@ fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}
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")
}) {
@@ -893,6 +886,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}) {
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 {}",
@@ -1300,6 +1294,12 @@ fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>> {
&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>
{
@@ -1333,7 +1333,7 @@ fn get_type_parameter_bounds(&self,
.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
@@ -1357,27 +1357,15 @@ fn trait_defines_associated_type_named(&self,
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
})
});
fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
self.next_ty_var()
}
let ty_var = self.next_ty_var_with_default(default);
// 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,
@@ -1624,8 +1612,14 @@ fn instantiate_bounds(&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
}
}
@@ -1701,26 +1695,24 @@ pub fn instantiate_type_path(&self,
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
@@ -2784,22 +2776,11 @@ pub fn impl_self_ty(&self,
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 }
}
@@ -3246,13 +3227,13 @@ pub fn check_struct_path(&self,
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
}
@@ -3260,14 +3241,14 @@ pub fn check_struct_path(&self,
_ => 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,
@@ -3466,10 +3447,7 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
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);
@@ -4059,54 +4037,19 @@ fn check_block_with_expected(&self,
*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
@@ -4180,54 +4123,37 @@ pub fn instantiate_value_path(&self,
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 {
@@ -4237,16 +4163,16 @@ pub fn instantiate_value_path(&self,
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
@@ -4254,52 +4180,41 @@ pub fn instantiate_value_path(&self,
// 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*
@@ -4308,20 +4223,88 @@ pub fn instantiate_value_path(&self,
// 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);
self.adjust_region_parameters(span, space, region_defs, &mut substs);
assert_eq!(substs.regions.len(space), region_defs.len(space));
}
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
};
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.
@@ -4332,7 +4315,7 @@ pub fn instantiate_value_path(&self,
// 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 {
@@ -4341,10 +4324,6 @@ pub fn instantiate_value_path(&self,
// 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) {
@@ -4371,243 +4350,83 @@ pub fn instantiate_value_path(&self,
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[..])
}
Some(&hir::ParenthesizedParameters(_)) => {
span_bug!(span, "parenthesized parameters cannot appear in ExprPath");
}
None => (&[][..], &[][..], &[][..])
};
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);
}
}
}
let count = |n| {
format!("{} parameter{}", n, if n == 1 { "" } else { "s" })
};
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;
}
}
// 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()));
}
if !data.bindings.is_empty() {
span_err!(self.tcx.sess, data.bindings[0].span, E0182,
// 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
}
});
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 type_defs.len() != required_len { "at least " } else { "" };
span_err!(self.tcx.sess, span, E0089,
"too few type parameters provided: \
expected {}{}, found {}",
qualifier,
count(required_len),
count(types.len()));
}
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)");
}
{
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;
}
}
}
}
/// 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 qualifier =
if desired.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);
}
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;
}
// 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)
+4 -6
View File
@@ -824,11 +824,11 @@ fn walk_cast(&mut self,
}
/*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),
@@ -1571,10 +1571,7 @@ fn projection_must_outlive(&self,
// 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");
@@ -1757,6 +1754,7 @@ fn declared_projection_bounds_from_trait(&self,
//
// 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| {
+16 -40
View File
@@ -14,13 +14,11 @@
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;
@@ -455,13 +453,14 @@ fn check_variances_for_type_defn(&self,
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();
@@ -469,53 +468,30 @@ fn check_variances_for_type_defn(&self,
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
}
}
@@ -542,10 +518,10 @@ fn report_bivariance(&self,
}
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);
}
@@ -621,7 +597,7 @@ fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
// 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 => {
+19 -21
View File
@@ -18,7 +18,6 @@
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;
@@ -68,7 +67,7 @@ pub fn resolve_type_vars_in_fn(&self,
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);
}
}
@@ -104,22 +103,19 @@ fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> {
}
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);
}
}
}
@@ -300,11 +296,13 @@ fn visit_closures(&self) {
}
}
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);
@@ -345,9 +343,9 @@ fn visit_anon_types(&self) {
}
});
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)
});
}
}

Some files were not shown because too many files have changed in this diff Show More