mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-22 02:00:00 +03:00
Merge branch 'master' into E0403-update-error-format
This commit is contained in:
+5
-3
@@ -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
|
||||
|
||||
@@ -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) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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].
|
||||
|
||||
@@ -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" }
|
||||
@@ -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())
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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())))
|
||||
}
|
||||
@@ -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::*;
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ")?;
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
@@ -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> {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -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
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
@@ -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)
|
||||
//
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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())?;
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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 = ¶m_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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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(|| {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, &[])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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, ®ion_substs, t))
|
||||
.collect();
|
||||
|
||||
let assoc_bindings: Vec<_> =
|
||||
data.bindings.iter()
|
||||
.map(|b| ConvertedBinding { item_name: b.name,
|
||||
ty: self.ast_ty_to_ty(rscope, &b.ty),
|
||||
span: b.span })
|
||||
.collect();
|
||||
|
||||
(region_substs, types, assoc_bindings)
|
||||
(substs, assoc_bindings)
|
||||
}
|
||||
|
||||
/// Returns the appropriate lifetime to use for any output lifetimes
|
||||
@@ -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, ®ion_substs, a_t))
|
||||
.collect::<Vec<Ty<'tcx>>>();
|
||||
|
||||
let inputs: Vec<_> = data.inputs.iter().map(|a_t| {
|
||||
self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t)
|
||||
}).collect();
|
||||
let input_params = vec![String::new(); inputs.len()];
|
||||
let implied_output_region = self.find_implied_output_region(&inputs, input_params);
|
||||
|
||||
let input_ty = self.tcx().mk_tup(inputs);
|
||||
|
||||
let (output, output_span) = match data.output {
|
||||
Some(ref output_ty) => {
|
||||
(self.convert_ty_with_lifetime_elision(implied_output_region,
|
||||
@@ -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,
|
||||
®ion_bounds,
|
||||
existential_principal,
|
||||
builtin_bounds);
|
||||
|
||||
let region_bound = match region_bound {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
match rscope.object_lifetime_default(span) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
span_err!(self.tcx().sess, span, E0228,
|
||||
"the lifetime bound for this object type cannot be deduced \
|
||||
from context; please supply an explicit bound");
|
||||
ty::ReStatic
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let object_trait_ref =
|
||||
object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
|
||||
|
||||
debug!("region_bound: {:?}", region_bound);
|
||||
|
||||
// ensure the super predicates and stop if we encountered an error
|
||||
if self.ensure_super_predicates(span, principal.def_id()).is_err() {
|
||||
@@ -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,
|
||||
®ion_bounds,
|
||||
principal_trait_ref,
|
||||
builtin_bounds);
|
||||
|
||||
let region_bound = match region_bound {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
match rscope.object_lifetime_default(span) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
span_err!(self.tcx().sess, span, E0228,
|
||||
"the lifetime bound for this object type cannot be deduced \
|
||||
from context; please supply an explicit bound");
|
||||
ty::ReStatic
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
debug!("region_bound: {:?}", region_bound);
|
||||
|
||||
ty::ExistentialBounds::new(region_bound, builtin_bounds, projection_bounds)
|
||||
let trait_ref = &trait_bound.trait_ref;
|
||||
let trait_def_id = self.trait_def_id(trait_ref);
|
||||
self.trait_path_to_object_type(rscope,
|
||||
trait_ref.path.span,
|
||||
PathParamMode::Explicit,
|
||||
trait_def_id,
|
||||
trait_ref.ref_id,
|
||||
trait_ref.path.segments.last().unwrap(),
|
||||
span,
|
||||
partitioned_bounds)
|
||||
}
|
||||
|
||||
/// Given the bounds on an object, determines what single region bound (if any) we can
|
||||
@@ -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"
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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(|_| {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user