From 949d1fffcad67579bf6732a932ba535dd6c75f7a Mon Sep 17 00:00:00 2001 From: Richard Diamond Date: Tue, 17 Feb 2015 12:00:58 -0600 Subject: [PATCH 01/25] Add cfgs to `liblibc` for NaCl targets. --- src/liblibc/lib.rs | 479 +++++++++++++++++++++++---------------------- 1 file changed, 241 insertions(+), 238 deletions(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index bf0cc9b4ad5e1..8d8f6a406f5d4 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -76,6 +76,7 @@ //! one from Berkeley after the lawsuits died down and the CSRG dissolved. #![allow(bad_style, raw_pointer_derive)] +#![cfg_attr(target_os = "nacl", allow(unused_imports))] #[cfg(feature = "cargo-build")] extern crate "std" as core; #[cfg(not(feature = "cargo-build"))] extern crate core; @@ -86,78 +87,33 @@ // you can write more-platform-agnostic code if you stick to just these // symbols. -pub use types::common::c95::{FILE, c_void, fpos_t}; -pub use types::common::c99::{int8_t, int16_t, int32_t, int64_t}; -pub use types::common::c99::{uint8_t, uint16_t, uint32_t, uint64_t}; -pub use types::common::posix88::{DIR, dirent_t}; -pub use types::os::common::posix01::{timeval}; -pub use types::os::common::bsd44::{addrinfo, in_addr, in6_addr, sockaddr_storage}; -pub use types::os::common::bsd44::{ip_mreq, ip6_mreq, sockaddr, sockaddr_un}; -pub use types::os::common::bsd44::{sa_family_t, sockaddr_in, sockaddr_in6, socklen_t}; -pub use types::os::arch::c95::{c_char, c_double, c_float, c_int, c_uint}; -pub use types::os::arch::c95::{c_long, c_short, c_uchar, c_ulong, wchar_t}; -pub use types::os::arch::c95::{c_ushort, clock_t, ptrdiff_t, c_schar}; -pub use types::os::arch::c95::{size_t, time_t, suseconds_t}; -pub use types::os::arch::c99::{c_longlong, c_ulonglong}; -pub use types::os::arch::c99::{intptr_t, uintptr_t}; -pub use types::os::arch::c99::{intmax_t, uintmax_t}; -pub use types::os::arch::posix88::{dev_t, ino_t, mode_t}; -pub use types::os::arch::posix88::{off_t, pid_t, ssize_t}; - -pub use consts::os::c95::{_IOFBF, _IOLBF, _IONBF, BUFSIZ, EOF}; -pub use consts::os::c95::{EXIT_FAILURE, EXIT_SUCCESS}; -pub use consts::os::c95::{FILENAME_MAX, FOPEN_MAX, L_tmpnam}; -pub use consts::os::c95::{RAND_MAX, SEEK_CUR, SEEK_END}; -pub use consts::os::c95::{SEEK_SET, TMP_MAX}; -pub use consts::os::posix88::{F_OK, O_APPEND, O_CREAT, O_EXCL}; -pub use consts::os::posix88::{O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}; -pub use consts::os::posix88::{R_OK, S_IEXEC, S_IFBLK, S_IFCHR}; -pub use consts::os::posix88::{S_IFDIR, S_IFIFO, S_IFMT, S_IFREG, S_IFLNK}; -pub use consts::os::posix88::{S_IREAD, S_IRUSR, S_IRWXU, S_IWUSR}; -pub use consts::os::posix88::{STDERR_FILENO, STDIN_FILENO, S_IXUSR}; -pub use consts::os::posix88::{STDOUT_FILENO, W_OK, X_OK}; -pub use consts::os::bsd44::{AF_INET, AF_INET6, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW}; -pub use consts::os::bsd44::{IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, TCP_NODELAY}; -pub use consts::os::bsd44::{SOL_SOCKET, SO_KEEPALIVE, SO_ERROR}; -pub use consts::os::bsd44::{SO_REUSEADDR, SO_BROADCAST, SHUT_WR, IP_MULTICAST_LOOP}; -pub use consts::os::bsd44::{IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP}; -pub use consts::os::bsd44::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP}; -pub use consts::os::bsd44::{IP_MULTICAST_TTL, IP_TTL, IP_HDRINCL, SHUT_RD}; -pub use consts::os::extra::{IPPROTO_RAW}; - -pub use funcs::c95::ctype::{isalnum, isalpha, iscntrl, isdigit}; -pub use funcs::c95::ctype::{islower, isprint, ispunct, isspace}; -pub use funcs::c95::ctype::{isupper, isxdigit, tolower, toupper}; - -pub use funcs::c95::stdio::{fclose, feof, ferror, fflush, fgetc}; -pub use funcs::c95::stdio::{fgetpos, fgets, fopen, fputc, fputs}; -pub use funcs::c95::stdio::{fread, freopen, fseek, fsetpos, ftell}; -pub use funcs::c95::stdio::{fwrite, perror, puts, remove, rename, rewind}; -pub use funcs::c95::stdio::{setbuf, setvbuf, tmpfile, ungetc}; - -pub use funcs::c95::stdlib::{abs, atof, atoi, calloc, exit, _exit, atexit}; -pub use funcs::c95::stdlib::{free, getenv, labs, malloc, rand}; -pub use funcs::c95::stdlib::{realloc, srand, strtod, strtol}; -pub use funcs::c95::stdlib::{strtoul, system}; - -pub use funcs::c95::string::{memchr, memcmp}; -pub use funcs::c95::string::{strcat, strchr, strcmp}; -pub use funcs::c95::string::{strcoll, strcpy, strcspn, strerror}; -pub use funcs::c95::string::{strlen, strncat, strncmp, strncpy}; -pub use funcs::c95::string::{strpbrk, strrchr, strspn, strstr}; -pub use funcs::c95::string::{strtok, strxfrm}; - -pub use funcs::posix88::fcntl::{open, creat}; -pub use funcs::posix88::stat_::{chmod, fstat, mkdir, stat}; -pub use funcs::posix88::stdio::{fdopen, fileno, pclose, popen}; -pub use funcs::posix88::unistd::{access, chdir, close, dup, dup2}; -pub use funcs::posix88::unistd::{execv, execve, execvp, getcwd}; -pub use funcs::posix88::unistd::{getpid, isatty, lseek, pipe, read}; -pub use funcs::posix88::unistd::{rmdir, unlink, write}; - -pub use funcs::bsd43::{socket, setsockopt, bind, send, recv, recvfrom}; -pub use funcs::bsd43::{listen, sendto, accept, connect, getpeername, getsockname}; -pub use funcs::bsd43::{shutdown}; +pub use types::common::c95::*; +pub use types::common::c99::*; +pub use types::common::posix88::*; +pub use types::os::common::posix01::*; +pub use types::os::common::bsd44::*; +pub use types::os::arch::c95::*; +pub use types::os::arch::c99::*; +pub use types::os::arch::posix88::*; +pub use types::os::arch::posix01::*; +pub use types::os::arch::extra::*; + +pub use consts::os::c95::*; +pub use consts::os::posix88::*; +pub use consts::os::posix01::*; +pub use consts::os::bsd44::*; +pub use consts::os::extra::*; + +pub use funcs::c95::ctype::*; +pub use funcs::c95::stdio::*; +pub use funcs::c95::stdlib::*; +pub use funcs::c95::string::*; +pub use funcs::posix88::fcntl::*; +pub use funcs::posix88::stat_::*; +pub use funcs::posix88::stdio::*; +pub use funcs::posix88::unistd::*; + +pub use funcs::bsd43::*; // But we also reexport most everything // if you're interested in writing platform-specific code. @@ -169,149 +125,43 @@ pub use funcs::bsd43::{shutdown}; // // So the following exports don't follow any particular plan. -#[cfg(unix)] pub use consts::os::sysconf::{_SC_PAGESIZE}; -#[cfg(unix)] pub use consts::os::posix88::{PROT_READ, PROT_WRITE, PROT_EXEC}; -#[cfg(unix)] pub use consts::os::posix88::{MAP_FIXED, MAP_FILE, MAP_ANON, MAP_PRIVATE, MAP_FAILED}; -#[cfg(unix)] pub use consts::os::posix88::{EACCES, EBADF, EINVAL, ENODEV, ENOMEM}; -#[cfg(unix)] pub use consts::os::posix88::{ECONNREFUSED, ECONNRESET, EPERM, EPIPE}; -#[cfg(unix)] pub use consts::os::posix88::{ENOTCONN, ECONNABORTED, EADDRNOTAVAIL, EINTR}; -#[cfg(unix)] pub use consts::os::posix88::{EADDRINUSE, ENOENT, EISDIR, EAGAIN, EWOULDBLOCK}; -#[cfg(unix)] pub use consts::os::posix88::{ECANCELED, SIGINT, EINPROGRESS}; -#[cfg(unix)] pub use consts::os::posix88::{ENOSYS, ENOTTY, ETIMEDOUT, EMFILE}; -#[cfg(unix)] pub use consts::os::posix88::{SIGTERM, SIGKILL, SIGPIPE, PROT_NONE}; -#[cfg(unix)] pub use consts::os::posix01::{SIG_IGN, F_GETFL, F_SETFL}; -#[cfg(unix)] pub use consts::os::bsd44::{AF_UNIX}; -#[cfg(unix)] pub use consts::os::extra::{O_NONBLOCK}; - -#[cfg(unix)] pub use types::os::common::posix01::{pthread_t, timespec, timezone}; - -#[cfg(unix)] pub use types::os::arch::posix88::{uid_t, gid_t}; -#[cfg(unix)] pub use types::os::arch::posix01::{pthread_attr_t}; -#[cfg(unix)] pub use types::os::arch::posix01::{stat, utimbuf}; -#[cfg(unix)] pub use types::os::common::bsd44::{ifaddrs}; -#[cfg(unix)] pub use funcs::posix88::unistd::{sysconf, setgid, setsid, setuid, pread, pwrite}; -#[cfg(unix)] pub use funcs::posix88::unistd::{getgid, getuid, getsid}; -#[cfg(unix)] pub use funcs::posix88::unistd::{_PC_NAME_MAX, utime, nanosleep, pathconf, link}; -#[cfg(unix)] pub use funcs::posix88::unistd::{chown}; -#[cfg(unix)] pub use funcs::posix88::mman::{mmap, munmap, mprotect}; -#[cfg(unix)] pub use funcs::posix88::dirent::{opendir, readdir_r, closedir}; -#[cfg(unix)] pub use funcs::posix88::fcntl::{fcntl}; -#[cfg(unix)] pub use funcs::posix88::net::{if_nametoindex}; -#[cfg(unix)] pub use funcs::posix01::stat_::{lstat}; -#[cfg(unix)] pub use funcs::posix01::unistd::{fsync, ftruncate}; -#[cfg(unix)] pub use funcs::posix01::unistd::{readlink, symlink}; -#[cfg(unix)] pub use funcs::bsd43::{getifaddrs, freeifaddrs}; - -#[cfg(windows)] pub use consts::os::c95::{WSAECONNREFUSED, WSAECONNRESET, WSAEACCES}; -#[cfg(windows)] pub use consts::os::c95::{WSAEWOULDBLOCK, WSAENOTCONN, WSAECONNABORTED}; -#[cfg(windows)] pub use consts::os::c95::{WSAEADDRNOTAVAIL, WSAEADDRINUSE, WSAEINTR}; -#[cfg(windows)] pub use consts::os::c95::{WSAEINPROGRESS, WSAEINVAL, WSAEMFILE}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_INSUFFICIENT_BUFFER}; -#[cfg(windows)] pub use consts::os::extra::{O_BINARY, O_NOINHERIT, PAGE_NOACCESS}; -#[cfg(windows)] pub use consts::os::extra::{PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE}; -#[cfg(windows)] pub use consts::os::extra::{PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}; -#[cfg(windows)] pub use consts::os::extra::{MEM_COMMIT, MEM_RESERVE, MEM_RELEASE}; -#[cfg(windows)] pub use consts::os::extra::{FILE_MAP_READ, FILE_MAP_WRITE, FILE_MAP_EXECUTE}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_ALREADY_EXISTS, ERROR_NO_DATA}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_NAME}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_BROKEN_PIPE, ERROR_INVALID_FUNCTION}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_CALL_NOT_IMPLEMENTED}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_NOTHING_TO_TERMINATE}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_INVALID_HANDLE}; -#[cfg(windows)] pub use consts::os::extra::{TRUE, FALSE, INFINITE}; -#[cfg(windows)] pub use consts::os::extra::{PROCESS_TERMINATE, PROCESS_QUERY_INFORMATION}; -#[cfg(windows)] pub use consts::os::extra::{STILL_ACTIVE, DETACHED_PROCESS}; -#[cfg(windows)] pub use consts::os::extra::{CREATE_NEW_PROCESS_GROUP, CREATE_UNICODE_ENVIRONMENT}; -#[cfg(windows)] pub use consts::os::extra::{FILE_BEGIN, FILE_END, FILE_CURRENT}; -#[cfg(windows)] pub use consts::os::extra::{FILE_GENERIC_READ, FILE_GENERIC_WRITE}; -#[cfg(windows)] pub use consts::os::extra::{FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE}; -#[cfg(windows)] pub use consts::os::extra::{TRUNCATE_EXISTING, CREATE_ALWAYS, OPEN_EXISTING}; -#[cfg(windows)] pub use consts::os::extra::{CREATE_NEW, FILE_APPEND_DATA, FILE_WRITE_DATA}; -#[cfg(windows)] pub use consts::os::extra::{OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL}; -#[cfg(windows)] pub use consts::os::extra::{FILE_FLAG_BACKUP_SEMANTICS, INVALID_HANDLE_VALUE}; -#[cfg(windows)] pub use consts::os::extra::{MOVEFILE_REPLACE_EXISTING}; -#[cfg(windows)] pub use consts::os::extra::{GENERIC_READ, GENERIC_WRITE}; -#[cfg(windows)] pub use consts::os::extra::{VOLUME_NAME_DOS}; -#[cfg(windows)] pub use consts::os::extra::{PIPE_ACCESS_DUPLEX, FILE_FLAG_FIRST_PIPE_INSTANCE}; -#[cfg(windows)] pub use consts::os::extra::{FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE}; -#[cfg(windows)] pub use consts::os::extra::{PIPE_READMODE_BYTE, PIPE_WAIT}; -#[cfg(windows)] pub use consts::os::extra::{PIPE_UNLIMITED_INSTANCES, ERROR_ACCESS_DENIED}; -#[cfg(windows)] pub use consts::os::extra::{FILE_WRITE_ATTRIBUTES, FILE_READ_ATTRIBUTES}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_BUSY, ERROR_IO_PENDING}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_CONNECTED, WAIT_OBJECT_0}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_NOT_FOUND}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_OPERATION_ABORTED}; -#[cfg(windows)] pub use consts::os::extra::{FIONBIO}; -#[cfg(windows)] pub use types::os::common::bsd44::{SOCKET}; -#[cfg(windows)] pub use types::os::common::posix01::{stat, utimbuf}; -#[cfg(windows)] pub use types::os::arch::extra::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES}; -#[cfg(windows)] pub use types::os::arch::extra::{LPCSTR, WORD, DWORD, BYTE, FILETIME}; -#[cfg(windows)] pub use types::os::arch::extra::{LARGE_INTEGER, LPVOID, LONG}; -#[cfg(windows)] pub use types::os::arch::extra::{time64_t, OVERLAPPED, LPCWSTR}; -#[cfg(windows)] pub use types::os::arch::extra::{LPOVERLAPPED, SIZE_T, LPDWORD}; -#[cfg(windows)] pub use types::os::arch::extra::{SECURITY_ATTRIBUTES, WIN32_FIND_DATAW}; -#[cfg(windows)] pub use funcs::c95::string::{wcslen}; -#[cfg(windows)] pub use funcs::posix88::stat_::{wstat, wutime, wchmod, wrmdir}; -#[cfg(windows)] pub use funcs::bsd43::{closesocket}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetCurrentDirectoryW, GetLastError}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetEnvironmentVariableW, SetEnvironmentVariableW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetModuleFileNameW, SetCurrentDirectoryW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetSystemInfo, VirtualAlloc, VirtualFree}; -#[cfg(windows)] pub use funcs::extra::kernel32::{CreateFileMappingW, MapViewOfFile}; -#[cfg(windows)] pub use funcs::extra::kernel32::{UnmapViewOfFile, CloseHandle}; -#[cfg(windows)] pub use funcs::extra::kernel32::{WaitForSingleObject, GetSystemTimeAsFileTime}; -#[cfg(windows)] pub use funcs::extra::kernel32::{QueryPerformanceCounter}; -#[cfg(windows)] pub use funcs::extra::kernel32::{QueryPerformanceFrequency}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetExitCodeProcess, TerminateProcess}; -#[cfg(windows)] pub use funcs::extra::kernel32::{ReadFile, WriteFile, SetFilePointerEx}; -#[cfg(windows)] pub use funcs::extra::kernel32::{SetEndOfFile, CreateFileW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{CreateDirectoryW, FindFirstFileW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{FindNextFileW, FindClose, DeleteFileW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{CreateHardLinkW, CreateEventW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{FlushFileBuffers, CreateNamedPipeW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{SetNamedPipeHandleState, WaitNamedPipeW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetOverlappedResult, ConnectNamedPipe}; -#[cfg(windows)] pub use funcs::extra::kernel32::{DisconnectNamedPipe, OpenProcess}; -#[cfg(windows)] pub use funcs::extra::kernel32::{MoveFileExW, VirtualProtect}; -#[cfg(windows)] pub use funcs::extra::kernel32::{RemoveDirectoryW}; -#[cfg(windows)] pub use funcs::extra::msvcrt::{get_osfhandle, open_osfhandle}; -#[cfg(windows)] pub use funcs::extra::winsock::{ioctlsocket}; - -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "openbsd"))] -pub use consts::os::posix01::{CLOCK_REALTIME, CLOCK_MONOTONIC}; - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use funcs::posix01::unistd::{fdatasync}; -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use types::os::arch::extra::{sockaddr_ll}; -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use consts::os::extra::{AF_PACKET}; - -#[cfg(all(unix, not(any(target_os = "freebsd", target_os = "bitrig", target_os = "openbsd"))))] -pub use consts::os::extra::{MAP_STACK}; - -#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] -pub use consts::os::bsd44::{TCP_KEEPIDLE}; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub use consts::os::bsd44::{TCP_KEEPALIVE}; -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub use consts::os::extra::{F_FULLFSYNC}; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub use types::os::arch::extra::{mach_timebase_info}; - - -#[cfg(not(windows))] +#[cfg(unix)] pub use consts::os::sysconf::*; + +#[cfg(unix)] pub use funcs::posix88::mman::*; +#[cfg(unix)] pub use funcs::posix88::dirent::*; +#[cfg(unix)] pub use funcs::posix88::net::*; +#[cfg(unix)] pub use funcs::posix01::stat_::*; +#[cfg(unix)] pub use funcs::posix01::unistd::*; + + +#[cfg(windows)] pub use funcs::extra::kernel32::*; +#[cfg(windows)] pub use funcs::extra::winsock::*; +#[cfg(windows)] pub use funcs::extra::msvcrt::*; + +// On NaCl, these libraries are static. Thus it would be a Bad Idea to link them +// in when creating a test crate. +#[cfg(not(any(windows, all(target_os = "nacl", test))))] #[link(name = "c")] #[link(name = "m")] extern {} +// libnacl provides functions that require a trip through the IRT to work. +// ie: _exit, mmap, nanosleep, etc. Anything that would otherwise require a trip +// to the kernel. +#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))] +#[link(name = "nacl", kind = "static")] +extern {} + +// pnaclmm provides a number of functions that the toolchain's Clang emits calls +// to when codegening atomic ops. All the functions within wrap various atomic +// operations. +// Yes, it could be linked by rustc explicitly, however by linking it here +// instead we save a bit of time where bins are involved (by not running the +// optimizations on the whole pnaclmm foreach binary built). +#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))] +#[link(name = "pnaclmm", kind = "static")] +extern {} + pub mod types { // Types tend to vary *per architecture* so we pull their definitions out @@ -362,7 +212,7 @@ pub mod types { // Standard types that are scalar but vary by OS and arch. - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] pub mod os { pub mod common { pub mod posix01 { @@ -370,7 +220,10 @@ pub mod types { use types::os::arch::c95::{c_char, c_ulong, size_t, time_t, suseconds_t, c_long}; + #[cfg(not(target_os = "nacl"))] pub type pthread_t = c_ulong; + #[cfg(target_os = "nacl")] + pub type pthread_t = *mut c_void; #[repr(C)] #[derive(Copy)] pub struct glob_t { @@ -467,10 +320,10 @@ pub mod types { #[cfg(target_os = "linux")] pub ai_canonname: *mut c_char, - #[cfg(target_os = "android")] + #[cfg(any(target_os = "android", target_os = "nacl"))] pub ai_canonname: *mut c_char, - #[cfg(target_os = "android")] + #[cfg(any(target_os = "android", target_os = "nacl"))] pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, @@ -499,7 +352,8 @@ pub mod types { target_arch = "arm", target_arch = "mips", target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "powerpc", + target_arch = "le32"))] pub mod arch { pub mod c95 { pub type c_char = i8; @@ -531,7 +385,8 @@ pub mod types { #[cfg(any(target_arch = "x86", target_arch = "mips", target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "powerpc", + target_arch = "le32"))] pub mod posix88 { pub type off_t = i32; pub type dev_t = u64; @@ -556,6 +411,7 @@ pub mod types { pub type ssize_t = i32; } #[cfg(any(target_arch = "x86", + target_arch = "le32", target_arch = "powerpc"))] pub mod posix01 { use types::os::arch::c95::{c_short, c_long, time_t}; @@ -2480,7 +2336,7 @@ pub mod consts { pub const SHUT_RDWR: c_int = 2; } pub mod extra { - use SOCKET; + use types::os::common::bsd44::SOCKET; use types::os::arch::c95::{c_int, c_long}; use types::os::arch::extra::{WORD, DWORD, BOOL, HANDLE}; @@ -2715,7 +2571,7 @@ pub mod consts { } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] pub mod os { pub mod c95 { use types::os::arch::c95::{c_int, c_uint}; @@ -2742,6 +2598,7 @@ pub mod consts { target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", + target_arch = "le32", target_arch = "powerpc"))] pub mod posix88 { use types::os::arch::c95::c_int; @@ -3165,6 +3022,7 @@ pub mod consts { pub const EDQUOT: c_int = 1133; } + #[cfg(not(target_os = "nacl"))] pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; @@ -3175,7 +3033,6 @@ pub mod consts { pub const F_SETFL : c_int = 4; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_ERR : c_int = 1 << 0; @@ -3247,12 +3104,81 @@ pub mod consts { pub const CLOCK_REALTIME: c_int = 0; pub const CLOCK_MONOTONIC: c_int = 1; } + #[cfg(target_os = "nacl")] + pub mod posix01 { + use types::os::arch::c95::{c_int, size_t}; + + pub const F_DUPFD : c_int = 0; + pub const F_GETFD : c_int = 1; + pub const F_SETFD : c_int = 2; + pub const F_GETFL : c_int = 3; + pub const F_SETFL : c_int = 4; + + pub const SIGTRAP : c_int = 5; + pub const SIG_IGN: size_t = 1; + + pub const GLOB_ERR : c_int = 1 << 0; + pub const GLOB_MARK : c_int = 1 << 1; + pub const GLOB_NOSORT : c_int = 1 << 2; + pub const GLOB_DOOFFS : c_int = 1 << 3; + pub const GLOB_NOCHECK : c_int = 1 << 4; + pub const GLOB_APPEND : c_int = 1 << 5; + pub const GLOB_NOESCAPE : c_int = 1 << 6; + + pub const GLOB_NOSPACE : c_int = 1; + pub const GLOB_ABORTED : c_int = 2; + pub const GLOB_NOMATCH : c_int = 3; + + pub const POSIX_MADV_NORMAL : c_int = 0; + pub const POSIX_MADV_RANDOM : c_int = 1; + pub const POSIX_MADV_SEQUENTIAL : c_int = 2; + pub const POSIX_MADV_WILLNEED : c_int = 3; + pub const POSIX_MADV_DONTNEED : c_int = 4; + + pub const _SC_MQ_PRIO_MAX : c_int = 28; + pub const _SC_IOV_MAX : c_int = 60; + pub const _SC_GETGR_R_SIZE_MAX : c_int = 69; + pub const _SC_GETPW_R_SIZE_MAX : c_int = 70; + pub const _SC_LOGIN_NAME_MAX : c_int = 71; + pub const _SC_TTY_NAME_MAX : c_int = 72; + pub const _SC_THREADS : c_int = 67; + pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 68; + pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 73; + pub const _SC_THREAD_KEYS_MAX : c_int = 74; + pub const _SC_THREAD_STACK_MIN : c_int = 75; + pub const _SC_THREAD_THREADS_MAX : c_int = 76; + pub const _SC_THREAD_ATTR_STACKADDR : c_int = 77; + pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 78; + pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 79; + pub const _SC_THREAD_PRIO_INHERIT : c_int = 80; + pub const _SC_THREAD_PRIO_PROTECT : c_int = 81; + pub const _SC_THREAD_PROCESS_SHARED : c_int = 82; + pub const _SC_ATEXIT_MAX : c_int = 87; + pub const _SC_XOPEN_VERSION : c_int = 89; + pub const _SC_XOPEN_XCU_VERSION : c_int = 90; + pub const _SC_XOPEN_UNIX : c_int = 91; + pub const _SC_XOPEN_CRYPT : c_int = 92; + pub const _SC_XOPEN_ENH_I18N : c_int = 93; + pub const _SC_XOPEN_SHM : c_int = 94; + pub const _SC_XOPEN_LEGACY : c_int = 129; + pub const _SC_XOPEN_REALTIME : c_int = 130; + pub const _SC_XOPEN_REALTIME_THREADS : c_int = 131; + + pub const PTHREAD_CREATE_JOINABLE: c_int = 1; + pub const PTHREAD_CREATE_DETACHED: c_int = 0; + + pub const PTHREAD_STACK_MIN: size_t = 1024; + + pub const CLOCK_REALTIME: c_int = 0; + pub const CLOCK_MONOTONIC: c_int = 1; + } pub mod posix08 { } #[cfg(any(target_arch = "arm", target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64", + target_arch = "le32", target_arch = "powerpc"))] pub mod bsd44 { use types::os::arch::c95::c_int; @@ -3350,6 +3276,7 @@ pub mod consts { target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", + target_arch = "le32", target_arch = "powerpc"))] pub mod extra { use types::os::arch::c95::c_int; @@ -3465,6 +3392,14 @@ pub mod consts { pub const _SC_XBS5_ILP32_OFFBIG : c_int = 126; pub const _SC_XBS5_LPBIG_OFFBIG : c_int = 128; } + #[cfg(target_os = "nacl")] + pub mod sysconf { + use types::os::arch::c95::c_int; + + pub static _SC_SENDMSG_MAX_SIZE : c_int = 0; + pub static _SC_NPROCESSORS_ONLN : c_int = 1; + pub static _SC_PAGESIZE : c_int = 2; + } #[cfg(target_os = "android")] pub mod sysconf { use types::os::arch::c95::c_int; @@ -3706,7 +3641,6 @@ pub mod consts { pub const F_SETFL : c_int = 4; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_APPEND : c_int = 0x0001; @@ -4113,7 +4047,6 @@ pub mod consts { pub const F_DUPFD_CLOEXEC : c_int = 10; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_APPEND : c_int = 0x0001; @@ -4504,7 +4437,6 @@ pub mod consts { pub const F_SETFL : c_int = 4; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_APPEND : c_int = 0x0001; @@ -5009,7 +4941,8 @@ pub mod funcs { target_os = "freebsd", target_os = "dragonfly", target_os = "bitrig", - target_os = "openbsd"))] + target_os = "openbsd", + target_os = "nacl"))] pub mod posix88 { pub mod stat_ { use types::os::arch::c95::{c_char, c_int}; @@ -5026,7 +4959,8 @@ pub mod funcs { target_os = "bitrig", target_os = "openbsd", target_os = "android", - target_os = "ios"))] + target_os = "ios", + target_os = "nacl"))] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -5034,6 +4968,7 @@ pub mod funcs { pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int; + #[cfg(not(target_os = "nacl"))] pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int; #[cfg(any(target_os = "linux", @@ -5042,7 +4977,8 @@ pub mod funcs { target_os = "bitrig", target_os = "openbsd", target_os = "android", - target_os = "ios"))] + target_os = "ios", + target_os = "nacl"))] pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -5114,6 +5050,7 @@ pub mod funcs { pub const _PC_NAME_MAX: c_int = 4; + #[cfg(not(target_os = "nacl"))] extern { pub fn access(path: *const c_char, amode: c_int) -> c_int; pub fn alarm(seconds: c_uint) -> c_uint; @@ -5135,7 +5072,7 @@ pub mod funcs { pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; - pub fn getgid() -> gid_t ; + pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int; pub fn getlogin() -> *mut c_char; @@ -5176,6 +5113,57 @@ pub mod funcs { offset: off_t) -> ssize_t; pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; } + #[cfg(target_os = "nacl")] + extern { + pub fn access(path: *const c_char, amode: c_int) -> c_int; + pub fn chdir(dir: *const c_char) -> c_int; + pub fn chown(path: *const c_char, uid: uid_t, + gid: gid_t) -> c_int; + pub fn close(fd: c_int) -> c_int; + pub fn dup(fd: c_int) -> c_int; + pub fn dup2(src: c_int, dst: c_int) -> c_int; + pub fn execv(prog: *const c_char, + argv: *mut *const c_char) -> c_int; + pub fn execve(prog: *const c_char, argv: *mut *const c_char, + envp: *mut *const c_char) + -> c_int; + pub fn execvp(c: *const c_char, + argv: *mut *const c_char) -> c_int; + pub fn fork() -> pid_t; + pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; + pub fn getegid() -> gid_t; + pub fn geteuid() -> uid_t; + pub fn getgid() -> gid_t; + pub fn getlogin() -> *mut c_char; + pub fn getopt(argc: c_int, argv: *mut *const c_char, + optstr: *const c_char) -> c_int; + pub fn getuid() -> uid_t; + pub fn getsid(pid: pid_t) -> pid_t; + pub fn isatty(fd: c_int) -> c_int; + pub fn link(src: *const c_char, dst: *const c_char) -> c_int; + pub fn lseek(fd: c_int, offset: off_t, whence: c_int) + -> off_t; + pub fn pipe(fds: *mut c_int) -> c_int; + pub fn read(fd: c_int, buf: *mut c_void, count: size_t) + -> ssize_t; + pub fn rmdir(path: *const c_char) -> c_int; + pub fn setgid(gid: gid_t) -> c_int; + pub fn setuid(uid: uid_t) -> c_int; + pub fn sleep(secs: c_uint) -> c_uint; + pub fn usleep(secs: c_uint) -> c_int; + pub fn nanosleep(rqtp: *const timespec, + rmtp: *mut timespec) -> c_int; + pub fn sysconf(name: c_int) -> c_long; + pub fn ttyname(fd: c_int) -> *mut c_char; + pub fn unlink(c: *const c_char) -> c_int; + pub fn write(fd: c_int, buf: *const c_void, count: size_t) + -> ssize_t; + pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, + offset: off_t) -> ssize_t; + pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t, + offset: off_t) -> ssize_t; + pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; + } } pub mod signal { @@ -5192,12 +5180,24 @@ pub mod funcs { use types::os::arch::c95::{size_t, c_int, c_char}; use types::os::arch::posix88::{mode_t, off_t}; + #[cfg(not(target_os = "nacl"))] extern { pub fn mlock(addr: *const c_void, len: size_t) -> c_int; pub fn munlock(addr: *const c_void, len: size_t) -> c_int; pub fn mlockall(flags: c_int) -> c_int; pub fn munlockall() -> c_int; + pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) + -> c_int; + + pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) + -> c_int; + pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) + -> c_int; + pub fn shm_unlink(name: *const c_char) -> c_int; + } + + extern { pub fn mmap(addr: *mut c_void, len: size_t, prot: c_int, @@ -5207,14 +5207,6 @@ pub mod funcs { -> *mut c_void; pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; - pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) - -> c_int; - - pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) - -> c_int; - pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) - -> c_int; - pub fn shm_unlink(name: *const c_char) -> c_int; } } @@ -5235,7 +5227,8 @@ pub mod funcs { target_os = "freebsd", target_os = "dragonfly", target_os = "bitrig", - target_os = "openbsd"))] + target_os = "openbsd", + target_os = "nacl"))] pub mod posix01 { pub mod stat_ { use types::os::arch::c95::{c_char, c_int}; @@ -5248,7 +5241,8 @@ pub mod funcs { target_os = "bitrig", target_os = "openbsd", target_os = "android", - target_os = "ios"))] + target_os = "ios", + target_os = "nacl"))] pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -5320,6 +5314,7 @@ pub mod funcs { use types::common::c95::{c_void}; use types::os::arch::c95::{c_int, size_t}; + #[cfg(not(target_os = "nacl"))] extern { pub fn posix_madvise(addr: *mut c_void, len: size_t, @@ -5356,7 +5351,8 @@ pub mod funcs { target_os = "freebsd", target_os = "dragonfly", target_os = "bitrig", - target_os = "openbsd"))] + target_os = "openbsd", + target_os = "nacl"))] pub mod posix08 { pub mod unistd { } @@ -5494,6 +5490,13 @@ pub mod funcs { } } + #[cfg(target_os = "nacl")] + pub mod bsd44 { + use types::os::arch::c95::c_int; + extern { + pub fn getdtablesize() -> c_int; + } + } #[cfg(target_os = "windows")] pub mod bsd44 { @@ -5516,7 +5519,7 @@ pub mod funcs { pub mod extra { } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] pub mod extra { } From 27747ac1a76f054275c75a5b3f867d09cd27c888 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 24 Feb 2015 07:45:34 +0200 Subject: [PATCH 02/25] Revert bogus rename from DefTrait to DefaultImpl. --- src/librustc/metadata/decoder.rs | 2 +- src/librustc/middle/astencode.rs | 2 +- src/librustc/middle/def.rs | 4 ++-- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 4 ++-- src/librustc_resolve/lib.rs | 8 ++++---- src/librustc_trans/save/mod.rs | 2 +- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_typeck/astconv.rs | 8 ++++---- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 6 +++--- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- 16 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index aeae101a1235c..7c0ffe8f3d81a 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -357,7 +357,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) let enum_did = item_reqd_and_translated_parent_item(cnum, item); DlDef(def::DefVariant(enum_did, did, false)) } - Trait => DlDef(def::DefaultImpl(did)), + Trait => DlDef(def::DefTrait(did)), Enum => DlDef(def::DefTy(did, true)), Impl | DefaultImpl => DlImpl(did), PublicField | InheritedField => DlField, diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index e63901c21b270..eb723830d383c 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -440,7 +440,7 @@ impl tr for def::Def { def::DefVariant(e_did, v_did, is_s) => { def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s) }, - def::DefaultImpl(did) => def::DefaultImpl(did.tr(dcx)), + def::DefTrait(did) => def::DefTrait(did.tr(dcx)), def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum), def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)), def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) => diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 009bfaf8728f8..7857bcad8135d 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -38,7 +38,7 @@ pub enum Def { // type `U` (indicated by the Ident). // FIXME(#20301) -- should use Name DefAssociatedPath(TyParamProvenance, ast::Ident), - DefaultImpl(ast::DefId), + DefTrait(ast::DefId), DefPrimTy(ast::PrimTy), DefTyParam(ParamSpace, u32, ast::DefId, ast::Name), DefUse(ast::DefId), @@ -135,7 +135,7 @@ impl Def { DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) | - DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefaultImpl(id) | + DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _, _) | DefConst(id) | DefAssociatedPath(TyParamProvenance::FromSelf(id), _) | DefAssociatedPath(TyParamProvenance::FromParam(id), _) => { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 5aa6be43002b5..d1fba421bbe58 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -579,7 +579,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Ok(self.cat_rvalue_node(id, span, expr_ty)) } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | - def::DefaultImpl(_) | def::DefTy(..) | def::DefPrimTy(_) | + def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index bef98f5bd02be..9012de0850fa2 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -169,7 +169,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. match self.def_map.borrow().get(&id) { - Some(&def::DefaultImpl(..)) => { + Some(&def::DefTrait(..)) => { self.with(LateScope(&Vec::new(), self.scope), |_, this| { this.visit_path(path, id); }); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f0a640aa2e0e2..3d92b387cdb32 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -802,7 +802,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { def::DefVariant(..) => ck("variant"), def::DefTy(_, false) => ck("type"), def::DefTy(_, true) => ck("enum"), - def::DefaultImpl(..) => ck("trait"), + def::DefTrait(..) => ck("trait"), def::DefStruct(..) => ck("struct"), def::DefMethod(_, Some(..), _) => ck("trait method"), def::DefMethod(..) => ck("method"), diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 31f21a84f842b..a181497010faf 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -736,7 +736,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.trait_item_map.insert((name, def_id), kind); } - name_bindings.define_type(DefaultImpl(def_id), sp, modifiers); + name_bindings.define_type(DefTrait(def_id), sp, modifiers); parent.clone() } ItemMac(..) => parent.clone() @@ -918,7 +918,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } child_name_bindings.define_value(def, DUMMY_SP, modifiers); } - DefaultImpl(def_id) => { + DefTrait(def_id) => { debug!("(building reduced graph for external \ crate) building type {}", final_ident); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c38b8fc750281..2da8bd5b538b6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2989,7 +2989,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // check for imports shadowing primitive types if let ast::ViewPathSimple(ident, _) = view_path.node { match self.def_map.borrow().get(&item.id) { - Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefaultImpl(..)) | None => { + Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefTrait(..)) | None => { self.check_if_primitive_type_name(ident.name, item.span); } _ => {} @@ -3199,7 +3199,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Some(def) => { match def { - (DefaultImpl(_), _) => { + (DefTrait(_), _) => { debug!("(resolving trait) found trait def: {:?}", def); self.record_def(trait_reference.ref_id, def); } @@ -4675,7 +4675,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => continue }; let trait_def_id = match def { - DefaultImpl(trait_def_id) => trait_def_id, + DefTrait(trait_def_id) => trait_def_id, _ => continue, }; if self.trait_item_map.contains_key(&(name, trait_def_id)) { @@ -4691,7 +4691,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(target) => target, }; let did = match target.bindings.def_for_namespace(TypeNS) { - Some(DefaultImpl(trait_def_id)) => trait_def_id, + Some(DefTrait(trait_def_id)) => trait_def_id, Some(..) | None => continue, }; if self.trait_item_map.contains_key(&(name, did)) { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 591450a259564..59fca4b031886 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -239,7 +239,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | - def::DefaultImpl(_) => Some(recorder::TypeRef), + def::DefTrait(_) => Some(recorder::TypeRef), def::DefStatic(_, _) | def::DefConst(_) | def::DefLocal(_) | diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index a358a3d89e90c..25568db814824 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -207,7 +207,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) def::DefUpvar(..) => { datum_callee(bcx, ref_expr) } - def::DefMod(..) | def::DefForeignMod(..) | def::DefaultImpl(..) | + def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) | def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) | def::DefUse(..) | def::DefTyParamBinder(..) | def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) | diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 581279c2c9ca8..46a7041fff672 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -600,7 +600,7 @@ pub fn instantiate_trait_ref<'tcx>( -> Rc> { match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) { - def::DefaultImpl(trait_def_id) => { + def::DefTrait(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, trait_def_id, @@ -914,7 +914,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, match ty.node { ast::TyPath(ref path, id) => { match this.tcx().def_map.borrow().get(&id) { - Some(&def::DefaultImpl(trait_def_id)) => { + Some(&def::DefTrait(trait_def_id)) => { let mut projection_bounds = Vec::new(); let trait_ref = object_path_to_poly_trait_ref(this, rscope, @@ -1194,7 +1194,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, Some(&d) => d }; match a_def { - def::DefaultImpl(trait_def_id) => { + def::DefTrait(trait_def_id) => { // N.B. this case overlaps somewhat with // TyObjectSum, see that fn for details let mut projection_bounds = Vec::new(); @@ -1804,7 +1804,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, match *ast_bound { ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => { match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { - def::DefaultImpl(trait_did) => { + def::DefTrait(trait_did) => { match trait_def_ids.get(&trait_did) { // Already seen this trait. We forbid // duplicates in the list (for some diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 26ba0fe8ed148..34c52981b794d 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -435,7 +435,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, let def = tcx.def_map.borrow()[pat.id].clone(); let (enum_def_id, variant_def_id) = match def { - def::DefaultImpl(_) => { + def::DefTrait(_) => { let name = pprust::path_to_string(path); span_err!(tcx.sess, pat.span, E0168, "use of trait `{}` in a struct pattern", name); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9b1693cba1e99..f5a03f0721a65 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -330,7 +330,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { cstore: &cstore::CStore, dl: decoder::DefLike) { match dl { - decoder::DlDef(def::DefaultImpl(did)) => { + decoder::DlDef(def::DefTrait(did)) => { traits.push(TraitInfo::new(did)); } decoder::DlDef(def::DefMod(did)) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 81e72ef6326c7..0430954ad7e2f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3862,7 +3862,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, variant_id, &fields[..]); enum_id } - Some(def::DefaultImpl(def_id)) => { + Some(def::DefTrait(def_id)) => { span_err!(tcx.sess, path.span, E0159, "use of trait `{}` as a struct constructor", pprust::path_to_string(path)); @@ -4634,7 +4634,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefStruct(id) | def::DefConst(id) => { (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id)) } - def::DefaultImpl(_) | + def::DefTrait(_) | def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | @@ -4738,7 +4738,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | - def::DefaultImpl(..) | + def::DefTrait(..) | def::DefPrimTy(..) | def::DefTyParam(..) => { // Everything but the final segment should have no diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 4cd6f6551d088..d1283d6f46bd8 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -69,7 +69,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt, let mut ret = Vec::new(); let did = def.def_id(); let inner = match def { - def::DefaultImpl(did) => { + def::DefTrait(did) => { record_extern_fqn(cx, did, clean::TypeTrait); clean::TraitItem(build_external_trait(cx, tcx, did)) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a3e0cecdd4826..058d55bd7ba95 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2430,7 +2430,7 @@ fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId { def::DefFn(i, _) => (i, TypeFunction), def::DefTy(i, false) => (i, TypeTypedef), def::DefTy(i, true) => (i, TypeEnum), - def::DefaultImpl(i) => (i, TypeTrait), + def::DefTrait(i) => (i, TypeTrait), def::DefStruct(i) => (i, TypeStruct), def::DefMod(i) => (i, TypeModule), def::DefStatic(i, _) => (i, TypeStatic), From a817c69297dc2bfac4029410cc055d32022cea95 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 29 Jan 2015 21:18:17 +0200 Subject: [PATCH 03/25] syntax: don't store a secondary NodeId for TyPath. --- src/librustc/lint/builtin.rs | 11 ++-- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/astconv_util.rs | 4 +- src/librustc/middle/infer/error_reporting.rs | 6 +- src/librustc/middle/resolve_lifetime.rs | 12 ++-- src/librustc_privacy/lib.rs | 69 ++++++++------------ src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_resolve/lib.rs | 12 ++-- src/librustc_trans/save/mod.rs | 8 +-- src/librustc_typeck/astconv.rs | 12 ++-- src/librustdoc/clean/mod.rs | 4 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/ast_util.rs | 3 - src/libsyntax/ext/build.rs | 2 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/fold.rs | 5 +- src/libsyntax/parse/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 7 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 4 +- 21 files changed, 74 insertions(+), 101 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 8a00622486ddc..8c6984972718f 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -405,8 +405,8 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { - fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) { - match self.cx.tcx.def_map.borrow()[path_id].clone() { + fn check_def(&mut self, sp: Span, id: ast::NodeId) { + match self.cx.tcx.def_map.borrow()[id].clone() { def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => { self.cx.span_lint(IMPROPER_CTYPES, sp, "found rust type `isize` in foreign module, while \ @@ -418,7 +418,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { libc::c_uint or libc::c_ulong should be used"); } def::DefTy(..) => { - let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty_id) { + let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&id) { Some(&ty::atttce_resolved(t)) => t, _ => panic!("ast_ty_to_ty_cache was incomplete after typeck!") }; @@ -437,9 +437,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - match ty.node { - ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id), - _ => (), + if let ast::TyPath(_) = ty.node { + self.check_def(ty.span, ty.id); } visit::walk_ty(self, ty); } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index e0832bb683a1c..e6f5c36a2f812 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1221,7 +1221,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_unsafety(rbml_w, unsafety); encode_polarity(rbml_w, polarity); match ty.node { - ast::TyPath(ref path, _) if path.segments.len() == 1 => { + ast::TyPath(ref path) if path.segments.len() == 1 => { let ident = path.segments.last().unwrap().identifier; encode_impl_type_basename(rbml_w, ident); } diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index d699ba40e8220..d468084483898 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -43,8 +43,8 @@ pub fn check_path_args(tcx: &ty::ctxt, pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { match ast_ty.node { - ast::TyPath(ref path, id) => { - let a_def = match tcx.def_map.borrow().get(&id) { + ast::TyPath(ref path) => { + let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { None => { tcx.sess.span_bug(ast_ty.span, &format!("unbound path {}", diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 110c7bf41e559..4439472ab5671 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1233,8 +1233,8 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } ty_queue.push(&*mut_ty.ty); } - ast::TyPath(ref path, id) => { - let a_def = match self.tcx.def_map.borrow().get(&id) { + ast::TyPath(ref path) => { + let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) { None => { self.tcx .sess @@ -1279,7 +1279,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { let new_path = self.rebuild_path(rebuild_info, lifetime); let to = ast::Ty { id: cur_ty.id, - node: ast::TyPath(new_path, id), + node: ast::TyPath(new_path), span: cur_ty.span }; new_ty = self.rebuild_ty(new_ty, P(to)); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 9012de0850fa2..7b957d6ce8498 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -165,13 +165,13 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { visit::walk_ty(this, ty); }); } - ast::TyPath(ref path, id) => { + ast::TyPath(ref path) => { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. - match self.def_map.borrow().get(&id) { + match self.def_map.borrow().get(&ty.id) { Some(&def::DefTrait(..)) => { self.with(LateScope(&Vec::new(), self.scope), |_, this| { - this.visit_path(path, id); + this.visit_path(path, ty.id); }); } _ => { @@ -270,16 +270,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { for lifetime in &trait_ref.bound_lifetimes { this.visit_lifetime_def(lifetime); } - this.visit_trait_ref(&trait_ref.trait_ref) + visit::walk_path(this, &trait_ref.trait_ref.path) }) } else { self.visit_trait_ref(&trait_ref.trait_ref) } } - - fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) { - self.visit_path(&trait_ref.path, trait_ref.ref_id); - } } impl<'a> LifetimeContext<'a> { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 3d92b387cdb32..838ba9c658cf1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -259,8 +259,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // * Private trait impls for private types can be completely ignored ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => { let public_ty = match ty.node { - ast::TyPath(_, id) => { - match self.tcx.def_map.borrow()[id].clone() { + ast::TyPath(_) => { + match self.tcx.def_map.borrow()[ty.id].clone() { def::DefPrimTy(..) => true, def => { let did = def.def_id(); @@ -326,8 +326,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { } ast::ItemTy(ref ty, _) if public_first => { - if let ast::TyPath(_, id) = ty.node { - match self.tcx.def_map.borrow()[id].clone() { + if let ast::TyPath(_) = ty.node { + match self.tcx.def_map.borrow()[ty.id].clone() { def::DefPrimTy(..) | def::DefTyParam(..) => {}, def => { let did = def.def_id(); @@ -628,11 +628,11 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // back up the chains to find the relevant struct/enum that // was private. ast::ItemImpl(_, _, _, _, ref ty, _) => { - let id = match ty.node { - ast::TyPath(_, id) => id, + match ty.node { + ast::TyPath(_) => {} _ => return Some((err_span, err_msg, None)), }; - let def = self.tcx.def_map.borrow()[id].clone(); + let def = self.tcx.def_map.borrow()[ty.id].clone(); let did = def.def_id(); assert!(is_local(did)); match self.tcx.map.get(did.node) { @@ -716,13 +716,13 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { } // Checks that a path is in scope. - fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) { + fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) { debug!("privacy - path {}", self.nodestr(path_id)); let orig_def = self.tcx.def_map.borrow()[path_id].clone(); let ck = |tyname: &str| { let ck_public = |def: ast::DefId| { debug!("privacy - ck_public {:?}", def); - let name = token::get_ident(path.segments.last().unwrap().identifier); + let name = token::get_ident(last); let origdid = orig_def.def_id(); self.ensure_public(span, def, @@ -832,37 +832,22 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &ast::Item) { - match item.node { - ast::ItemUse(ref vpath) => { - match vpath.node { - ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {} - ast::ViewPathList(ref prefix, ref list) => { - for pid in list { - match pid.node { - ast::PathListIdent { id, name } => { - debug!("privacy - ident item {}", id); - let seg = ast::PathSegment { - identifier: name, - parameters: ast::PathParameters::none(), - }; - let segs = vec![seg]; - let path = ast::Path { - global: false, - span: pid.span, - segments: segs, - }; - self.check_path(pid.span, id, &path); - } - ast::PathListMod { id } => { - debug!("privacy - mod item {}", id); - self.check_path(pid.span, id, prefix); - } - } + if let ast::ItemUse(ref vpath) = item.node { + if let ast::ViewPathList(ref prefix, ref list) = vpath.node { + for pid in list { + match pid.node { + ast::PathListIdent { id, name } => { + debug!("privacy - ident item {}", id); + self.check_path(pid.span, id, name); + } + ast::PathListMod { id } => { + debug!("privacy - mod item {}", id); + let name = prefix.segments.last().unwrap().identifier; + self.check_path(pid.span, id, name); } } } } - _ => {} } let orig_curitem = replace(&mut self.curitem, item.id); visit::walk_item(self, item); @@ -1033,7 +1018,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) { - self.check_path(path.span, id, path); + self.check_path(path.span, id, path.segments.last().unwrap().identifier); visit::walk_path(self, path); } } @@ -1273,8 +1258,8 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - if let ast::TyPath(_, path_id) = ty.node { - if self.inner.path_is_private_type(path_id) { + if let ast::TyPath(_) = ty.node { + if self.inner.path_is_private_type(ty.id) { self.contains_private = true; // found what we're looking for so let's stop // working. @@ -1398,7 +1383,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // // Those in 2. are warned via walk_generics and this // call here. - self.visit_trait_ref(tr) + visit::walk_path(self, &tr.path); } } } else if trait_ref.is_none() && self_is_public_path { @@ -1479,9 +1464,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_ty(&mut self, t: &ast::Ty) { - if let ast::TyPath(ref p, path_id) = t.node { + if let ast::TyPath(ref p) = t.node { if !self.tcx.sess.features.borrow().visible_private_types && - self.path_is_private_type(path_id) { + self.path_is_private_type(t.id) { self.tcx.sess.span_err(p.span, "private type in exported type signature"); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a181497010faf..ad5fa600bd81b 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -523,14 +523,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // within this module. let mod_name = match ty.node { - TyPath(ref path, _) if path.segments.len() == 1 => { + TyPath(ref path) if path.segments.len() == 1 => { // FIXME(18446) we should distinguish between the name of // a trait and the name of an impl of that trait. Some(path.segments.last().unwrap().identifier.name) } TyObjectSum(ref lhs_ty, _) => { match lhs_ty.node { - TyPath(ref path, _) if path.segments.len() == 1 => { + TyPath(ref path) if path.segments.len() == 1 => { Some(path.segments.last().unwrap().identifier.name) } _ => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2da8bd5b538b6..55ad52762e0c6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3387,8 +3387,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // type, the result will be that the type name resolves to a module but not // a type (shadowing any imported modules or types with this name), leading // to weird user-visible bugs. So we ward this off here. See #15060. - TyPath(ref path, path_id) => { - match self.def_map.borrow().get(&path_id) { + TyPath(ref path) => { + match self.def_map.borrow().get(&self_type.id) { // FIXME: should we catch other options and give more precise errors? Some(&DefMod(_)) => { self.resolve_error(path.span, "inherent implementations are not \ @@ -3576,7 +3576,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. - TyPath(ref path, path_id) => { + TyPath(ref path) => { // This is a path in the type namespace. Walk through scopes // looking for it. let mut result_def = None; @@ -3617,8 +3617,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving type) writing resolution for `{}` \ (id {}) = {:?}", self.path_names_to_string(path), - path_id, def); - self.record_def(path_id, def); + ty.id, def); + self.record_def(ty.id, def); } None => { let msg = format!("use of undeclared type name `{}`", @@ -4281,7 +4281,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) -> Option<(Path, NodeId, FallbackChecks)> { match t.node { - TyPath(ref path, node_id) => Some((path.clone(), node_id, allow)), + TyPath(ref path) => Some((path.clone(), t.id, allow)), TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics), TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow), // This doesn't handle the remaining `Ty` variants as they are not diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 59fca4b031886..af891001ea00e 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -662,9 +662,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id)); match typ.node { // Common case impl for a struct or something basic. - ast::TyPath(ref path, id) => { + ast::TyPath(ref path) => { let sub_span = self.span.sub_span_for_type_name(path.span); - let self_id = self.lookup_type_ref(id).map(|id| { + let self_id = self.lookup_type_ref(typ.id).map(|id| { self.fmt.ref_str(recorder::TypeRef, path.span, sub_span, @@ -1303,8 +1303,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } match t.node { - ast::TyPath(ref path, id) => { - match self.lookup_type_ref(id) { + ast::TyPath(ref path) => { + match self.lookup_type_ref(t.id) { Some(id) => { let sub_span = self.span.sub_span_for_type_name(t.span); self.fmt.ref_str(recorder::TypeRef, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 46a7041fff672..16a2dbf26870a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -852,8 +852,8 @@ pub fn ast_ty_to_builtin_ty<'tcx>( } match ast_ty.node { - ast::TyPath(ref path, id) => { - let a_def = match this.tcx().def_map.borrow().get(&id) { + ast::TyPath(ref path) => { + let a_def = match this.tcx().def_map.borrow().get(&ast_ty.id) { None => { this.tcx() .sess @@ -912,8 +912,8 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, */ match ty.node { - ast::TyPath(ref path, id) => { - match this.tcx().def_map.borrow().get(&id) { + ast::TyPath(ref path) => { + match this.tcx().def_map.borrow().get(&ty.id) { Some(&def::DefTrait(trait_def_id)) => { let mut projection_bounds = Vec::new(); let trait_ref = object_path_to_poly_trait_ref(this, @@ -1183,8 +1183,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..]) } - ast::TyPath(ref path, id) => { - let a_def = match tcx.def_map.borrow().get(&id) { + ast::TyPath(ref path) => { + let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { None => { tcx.sess .span_bug(ast_ty.span, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 058d55bd7ba95..d05aa4d20066b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1496,8 +1496,8 @@ impl Clean for ast::Ty { TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx), e.span.to_src(cx)), TyTup(ref tys) => Tuple(tys.clean(cx)), - TyPath(ref p, id) => { - resolve_type(cx, p.clean(cx), id) + TyPath(ref p) => { + resolve_type(cx, p.clean(cx), self.id) } TyObjectSum(ref lhs, ref bounds) => { let lhs_ty = lhs.clean(cx); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index effaac5271634..7c83286f656b1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1257,7 +1257,7 @@ pub enum Ty_ { /// A path (`module::module::...::Type`) or primitive /// /// Type parameters are stored in the Path itself - TyPath(Path, NodeId), + TyPath(Path), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f1228c1d36308..6ea37aaf72ce2 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -488,9 +488,6 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { fn visit_ty(&mut self, typ: &Ty) { self.operation.visit_id(typ.id); - if let TyPath(_, id) = typ.node { - self.operation.visit_id(id); - } visit::walk_ty(self, typ) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 656d507ed69b8..baa2fab044f3f 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -398,7 +398,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn ty_path(&self, path: ast::Path) -> P { - self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID)) + self.ty(path.span, ast::TyPath(path)) } fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice) -> P { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index bc239d0c7c269..f7014d6cc3c00 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -41,7 +41,7 @@ pub fn expand_type(t: P, debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty); let t = match (t.node.clone(), impl_ty) { // Expand uses of `Self` in impls to the concrete type. - (ast::Ty_::TyPath(ref path, _), Some(ref impl_ty)) => { + (ast::Ty_::TyPath(ref path), Some(ref impl_ty)) => { let path_as_ident = path_to_ident(path); // Note unhygenic comparison here. I think this is correct, since // even though `Self` is almost just a type parameter, the treatment diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 071158fcebb5c..4efae84fea5ae 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -549,7 +549,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, t: &ast::Ty) { match t.node { - ast::TyPath(ref p, _) => { + ast::TyPath(ref p) => { match &*p.segments { [ast::PathSegment { identifier, .. }] => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index dae830583c44b..ae4d2a8004598 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -428,10 +428,7 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { } TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), - TyPath(path, id) => { - let id = fld.new_id(id); - TyPath(fld.fold_path(path), id) - } + TyPath(path) => TyPath(fld.fold_path(path)), TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds)) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 43dfcbae57e49..d4c66529e77df 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1051,7 +1051,7 @@ mod test { parameters: ast::PathParameters::none(), } ), - }, ast::DUMMY_NODE_ID), + }), span:sp(10,13) }), pat: P(ast::Pat { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fec33eddb91c1..bcef7238d7f21 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1076,8 +1076,7 @@ impl<'a> Parser<'a> { } pub fn parse_ty_path(&mut self) -> Ty_ { - let path = self.parse_path(LifetimeAndTypesWithoutColons); - TyPath(path, ast::DUMMY_NODE_ID) + TyPath(self.parse_path(LifetimeAndTypesWithoutColons)) } /// parse a TyBareFn type: @@ -4815,10 +4814,10 @@ impl<'a> Parser<'a> { let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. match ty.node { - TyPath(ref path, node_id) => { + TyPath(ref path) => { Some(TraitRef { path: (*path).clone(), - ref_id: node_id, + ref_id: ty.id, }) } _ => { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 869dad867ebc4..752d34a19c6e1 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -729,7 +729,7 @@ impl<'a> State<'a> { &generics, None)); } - ast::TyPath(ref path, _) => { + ast::TyPath(ref path) => { try!(self.print_path(path, false)); } ast::TyObjectSum(ref ty, ref bounds) => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 412bf0fa22a00..4586495227d02 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -399,8 +399,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_fn_ret_ty(visitor, &function_declaration.decl.output); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyPath(ref path, id) => { - visitor.visit_path(path, id); + TyPath(ref path) => { + visitor.visit_path(path, typ.id); } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); From 004df413aa35b3d610faf231682cfbae5d4eeb46 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 30 Jan 2015 10:09:44 +0200 Subject: [PATCH 04/25] syntax: don't use TraitRef in QPath. --- src/librustc/lint/context.rs | 5 ++ src/librustc/lint/mod.rs | 1 + src/librustc/metadata/encoder.rs | 5 +- src/librustc/middle/dead.rs | 5 ++ src/librustc/middle/ty.rs | 34 ++++----- src/librustc_back/svh.rs | 5 ++ src/librustc_privacy/lib.rs | 5 ++ src/librustc_resolve/lib.rs | 74 ++++++++----------- src/librustc_trans/save/mod.rs | 4 +- src/librustc_typeck/astconv.rs | 28 ++++--- src/librustc_typeck/check/mod.rs | 14 ++-- src/librustc_typeck/check/wf.rs | 4 +- src/librustc_typeck/coherence/impls.rs | 4 +- src/librustc_typeck/coherence/mod.rs | 38 +++------- src/librustc_typeck/collect.rs | 4 +- src/librustdoc/clean/mod.rs | 2 +- src/libsyntax/ast.rs | 8 +- src/libsyntax/ast_util.rs | 9 ++- src/libsyntax/fold.rs | 8 +- src/libsyntax/parse/parser.rs | 8 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 20 +++-- .../compile-fail/ufcs-qpath-missing-params.rs | 2 +- 23 files changed, 143 insertions(+), 146 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index d344ee8c881c5..81fb1c8e913f6 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -717,6 +717,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { visit::walk_path(self, p); } + fn visit_qpath(&mut self, p: &ast::QPath, id: ast::NodeId) { + run_lints!(self, check_qpath, p, id); + visit::walk_qpath(self, p); + } + fn visit_attribute(&mut self, attr: &ast::Attribute) { run_lints!(self, check_attribute, attr); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 021827b0101c8..1e2ddb7db0bfa 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -157,6 +157,7 @@ pub trait LintPass { fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { } fn check_mac(&mut self, _: &Context, _: &ast::Mac) { } fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { } + fn check_qpath(&mut self, _: &Context, _: &ast::QPath, _: ast::NodeId) { } fn check_attribute(&mut self, _: &Context, _: &ast::Attribute) { } /// Called when entering a syntax node that can have lint attributes such diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index e6f5c36a2f812..1a695baf7216b 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1241,9 +1241,8 @@ fn encode_info_for_item(ecx: &EncodeContext, } rbml_w.end_tag(); } - if let Some(ref ast_trait_ref) = *opt_trait { - let trait_ref = ty::node_id_to_trait_ref( - tcx, ast_trait_ref.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id); encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref); } encode_path(rbml_w, path.clone()); diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index ff78deb8d12ea..4f9b900a5f876 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -306,6 +306,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { visit::walk_path(self, path); } + fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { + self.lookup_and_handle_definition(&id); + visit::walk_qpath(self, qpath); + } + fn visit_item(&mut self, _: &ast::Item) { // Do not recurse into items. These items will be added to the // worklist and recursed into manually if necessary. diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3d059e27c5207..c4fe3f4df0218 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -709,7 +709,7 @@ pub struct ctxt<'tcx> { pub impl_trait_cache: RefCell>>>>, - pub trait_refs: RefCell>>>, + pub impl_trait_refs: RefCell>>>, pub trait_defs: RefCell>>>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its @@ -2449,7 +2449,7 @@ pub fn mk_ctxt<'tcx>(s: Session, region_maps: region_maps, node_types: RefCell::new(FnvHashMap()), item_substs: RefCell::new(NodeMap()), - trait_refs: RefCell::new(NodeMap()), + impl_trait_refs: RefCell::new(NodeMap()), trait_defs: RefCell::new(DefIdMap()), predicates: RefCell::new(DefIdMap()), object_cast_map: RefCell::new(NodeMap()), @@ -4174,12 +4174,12 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>, } } -pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) +pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Rc> { - match cx.trait_refs.borrow().get(&id) { + match cx.impl_trait_refs.borrow().get(&id) { Some(ty) => ty.clone(), None => cx.sess.bug( - &format!("node_id_to_trait_ref: no trait ref for node `{}`", + &format!("impl_id_to_trait_ref: no trait ref for impl `{}`", cx.map.node_to_string(id))) } } @@ -5116,25 +5116,19 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) memoized(&cx.impl_trait_cache, id, |id: ast::DefId| { if id.krate == ast::LOCAL_CRATE { debug!("(impl_trait_ref) searching for trait impl {:?}", id); - match cx.map.find(id.node) { - Some(ast_map::NodeItem(item)) => { - match item.node { - ast::ItemImpl(_, _, _, ref opt_trait, _, _) => { - match opt_trait { - &Some(ref t) => { - let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id); - Some(trait_ref) - } - &None => None - } - } + if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) { + if let ast::ItemImpl(_, _, _, ref opt_trait, _, _) = item.node { + opt_trait.as_ref().map(|_| { + ty::impl_id_to_trait_ref(cx, id.node) + }) + } else { + None ast::ItemDefaultImpl(_, ref ast_trait_ref) => { Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id)) } - _ => None - } } - _ => None + } else { + None } } else { csearch::get_impl_trait(cx, id) diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 2fc43ab26b58e..af886ed25ab20 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -194,6 +194,7 @@ mod svh_visitor { SawVariant, SawExplicitSelf, SawPath, + SawQPath, SawOptLifetimeRef, SawBlock, SawPat, @@ -485,6 +486,10 @@ mod svh_visitor { SawPath.hash(self.st); visit::walk_path(self, path) } + fn visit_qpath(&mut self, qpath: &QPath, _: ast::NodeId) { + SawQPath.hash(self.st); visit::walk_qpath(self, qpath) + } + fn visit_block(&mut self, b: &Block) { SawBlock.hash(self.st); visit::walk_block(self, b) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 838ba9c658cf1..1f8ae3fbbcbb4 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1021,6 +1021,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { self.check_path(path.span, id, path.segments.last().unwrap().identifier); visit::walk_path(self, path); } + + fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { + self.check_path(qpath.trait_path.span, id, qpath.item_path.identifier); + visit::walk_qpath(self, qpath); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 55ad52762e0c6..1380e2367256d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2875,8 +2875,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.resolve_type_parameters(&generics.ty_params); this.resolve_where_clause(&generics.where_clause); - this.resolve_type_parameter_bounds(item.id, bounds, - TraitDerivation); + this.resolve_type_parameter_bounds(bounds, TraitDerivation); for trait_item in &(*trait_items) { // Create a new rib for the trait_item-specific type @@ -3141,8 +3140,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { type_parameter: &TyParam) { self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); for bound in &*type_parameter.bounds { - self.resolve_type_parameter_bound(type_parameter.id, bound, - TraitBoundingTypeParameter); + self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); } match type_parameter.default { Some(ref ty) => self.resolve_type(&**ty), @@ -3151,41 +3149,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn resolve_type_parameter_bounds(&mut self, - id: NodeId, type_parameter_bounds: &OwnedSlice, reference_type: TraitReferenceType) { for type_parameter_bound in &**type_parameter_bounds { - self.resolve_type_parameter_bound(id, type_parameter_bound, - reference_type); + self.resolve_type_parameter_bound(type_parameter_bound, reference_type); } } fn resolve_type_parameter_bound(&mut self, - id: NodeId, type_parameter_bound: &TyParamBound, reference_type: TraitReferenceType) { match *type_parameter_bound { TraitTyParamBound(ref tref, _) => { - self.resolve_poly_trait_reference(id, tref, reference_type) + self.resolve_trait_reference(tref.trait_ref.ref_id, + &tref.trait_ref.path, + reference_type) } RegionTyParamBound(..) => {} } } - fn resolve_poly_trait_reference(&mut self, - id: NodeId, - poly_trait_reference: &PolyTraitRef, - reference_type: TraitReferenceType) { - self.resolve_trait_reference(id, &poly_trait_reference.trait_ref, reference_type) - } - fn resolve_trait_reference(&mut self, id: NodeId, - trait_reference: &TraitRef, + trait_path: &Path, reference_type: TraitReferenceType) { - match self.resolve_path(id, &trait_reference.path, TypeNS, true) { + match self.resolve_path(id, trait_path, TypeNS, true) { None => { - let path_str = self.path_names_to_string(&trait_reference.path); + let path_str = self.path_names_to_string(trait_path); let usage_str = match reference_type { TraitBoundingTypeParameter => "bound type parameter with", TraitImplementation => "implement", @@ -3195,26 +3185,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str); - self.resolve_error(trait_reference.path.span, &msg[..]); + self.resolve_error(trait_path.span, &msg[..]); } Some(def) => { match def { (DefTrait(_), _) => { debug!("(resolving trait) found trait def: {:?}", def); - self.record_def(trait_reference.ref_id, def); + self.record_def(id, def); } (def, _) => { - self.resolve_error(trait_reference.path.span, - &format!("`{}` is not a trait", - self.path_names_to_string( - &trait_reference.path))); + self.resolve_error(trait_path.span, + &format!("`{}` is not a trait", + self.path_names_to_string(trait_path))); // If it's a typedef, give a note if let DefTy(..) = def { - self.session.span_note( - trait_reference.path.span, - &format!("`type` aliases cannot be used for traits") - ); + self.session.span_note(trait_path.span, + &format!("`type` aliases cannot be used for traits")); } } } @@ -3229,8 +3216,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_type(&*bound_pred.bounded_ty); for bound in &*bound_pred.bounds { - self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound, - TraitBoundingTypeParameter); + self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); } } &ast::WherePredicate::RegionPredicate(_) => {} @@ -3303,14 +3289,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result } - fn with_optional_trait_ref(&mut self, id: NodeId, + fn with_optional_trait_ref(&mut self, opt_trait_ref: &Option, f: F) -> T where F: FnOnce(&mut Resolver) -> T, { let new_val = match *opt_trait_ref { Some(ref trait_ref) => { - self.resolve_trait_reference(id, trait_ref, TraitImplementation); + self.resolve_trait_reference(trait_ref.ref_id, + &trait_ref.path, + TraitImplementation); match self.def_map.borrow().get(&trait_ref.ref_id) { Some(def) => { @@ -3345,7 +3333,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.resolve_where_clause(&generics.where_clause); // Resolve the trait reference, if necessary. - this.with_optional_trait_ref(id, opt_trait_reference, |this| { + this.with_optional_trait_ref(opt_trait_reference, |this| { // Resolve the self type. this.resolve_type(self_type); @@ -3630,13 +3618,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { TyObjectSum(ref ty, ref bound_vec) => { self.resolve_type(&**ty); - self.resolve_type_parameter_bounds(ty.id, bound_vec, - TraitBoundingTypeParameter); + self.resolve_type_parameter_bounds(bound_vec, TraitBoundingTypeParameter); } TyQPath(ref qpath) => { self.resolve_type(&*qpath.self_type); - self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath); + self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath); for ty in qpath.item_path.parameters.types() { self.resolve_type(&**ty); } @@ -3646,10 +3633,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } TyPolyTraitRef(ref bounds) => { - self.resolve_type_parameter_bounds( - ty.id, - bounds, - TraitObject); + self.resolve_type_parameter_bounds(bounds, TraitObject); visit::walk_ty(self, ty); } _ => { @@ -4439,8 +4423,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ExprPath(ref path) => path, ExprQPath(ref qpath) => { self.resolve_type(&*qpath.self_type); - self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath); - path_from_qpath = qpath.trait_ref.path.clone(); + + // Just make sure the trait is valid, don't record a def. + self.resolve_trait_reference(expr.id, &qpath.trait_path, TraitQPath); + self.def_map.borrow_mut().remove(&expr.id); + + path_from_qpath = qpath.trait_path.clone(); path_from_qpath.segments.push(qpath.item_path.clone()); &path_from_qpath } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index af891001ea00e..c928866512892 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1340,10 +1340,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { visit::walk_path(self, path); } ast::ExprQPath(ref qpath) => { - let mut path = qpath.trait_ref.path.clone(); + let mut path = qpath.trait_path.clone(); path.segments.push(qpath.item_path.clone()); self.process_path(ex.id, ex.span, &path, None); - visit::walk_qpath(self, ex.span, &**qpath); + visit::walk_qpath(self, &**qpath); } ast::ExprStruct(ref path, ref fields, ref base) => self.process_struct_lit(ex, path, fields, base), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 16a2dbf26870a..3c4af12c1f994 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -574,9 +574,10 @@ pub fn instantiate_poly_trait_ref<'tcx>( // lifetimes. Oh well, not there yet. let shifted_rscope = ShiftedRscope::new(rscope); - let trait_ref = - instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref, - self_ty, Some(&mut projections)); + let trait_ref = instantiate_trait_ref(this, &shifted_rscope, + &ast_trait_ref.trait_ref.path, + ast_trait_ref.trait_ref.ref_id, + None, self_ty, Some(&mut projections)); for projection in projections { poly_projections.push(ty::Binder(projection)); @@ -594,26 +595,29 @@ pub fn instantiate_poly_trait_ref<'tcx>( pub fn instantiate_trait_ref<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, - ast_trait_ref: &ast::TraitRef, + path: &ast::Path, + path_id: ast::NodeId, + impl_id: Option, self_ty: Option>, projections: Option<&mut Vec>>) -> Rc> { - match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) { + match ::lookup_def_tcx(this.tcx(), path.span, path_id) { def::DefTrait(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty, - &ast_trait_ref.path, + path, projections); - this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone()); + if let Some(id) = impl_id { + this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone()); + } trait_ref } _ => { - span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245, - "`{}` is not a trait", - ast_trait_ref.path.user_string(this.tcx())); + span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait", + path.user_string(this.tcx())); } } } @@ -1056,7 +1060,9 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, let trait_ref = instantiate_trait_ref(this, rscope, - &*qpath.trait_ref, + &qpath.trait_path, + ast_ty.id, + None, Some(self_type), None); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 0430954ad7e2f..b6003071f8c72 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3611,13 +3611,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, constrain_path_type_parameters(fcx, expr); } ast::ExprQPath(ref qpath) => { - // Require explicit type params for the trait. let self_ty = fcx.to_ty(&*qpath.self_type); - astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None); - let defn = lookup_def(fcx, expr.span, id); let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - let mut path = qpath.trait_ref.path.clone(); + let mut path = qpath.trait_path.clone(); path.segments.push(qpath.item_path.clone()); instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty), defn, expr.span, expr.id); @@ -4829,7 +4826,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // to add defaults. If the user provided *too many* types, that's // a problem. for &space in &ParamSpace::all() { - adjust_type_parameters(fcx, span, space, type_defs, &mut substs); + adjust_type_parameters(fcx, span, space, type_defs, + opt_self_ty.is_some(), &mut substs); assert_eq!(substs.types.len(space), type_defs.len(space)); adjust_region_parameters(fcx, span, space, region_defs, &mut substs); @@ -5007,6 +5005,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, space: ParamSpace, defs: &VecPerParamSpace>, + require_type_space: bool, substs: &mut Substs<'tcx>) { let provided_len = substs.types.len(space); @@ -5029,9 +5028,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Nothing specified at all: supply inference variables for // everything. - if provided_len == 0 { - substs.types.replace(space, - fcx.infcx().next_ty_vars(desired.len())); + if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) { + substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len())); return; } diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 399795c66567e..e024526d0016f 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -81,8 +81,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => { self.check_impl(item); } - ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => { - let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id); + ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => { + let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id); ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id); match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { Some(ty::BoundSend) | Some(ty::BoundSync) => {} diff --git a/src/librustc_typeck/coherence/impls.rs b/src/librustc_typeck/coherence/impls.rs index e535b86a7bfd1..e89c96b36e1a2 100644 --- a/src/librustc_typeck/coherence/impls.rs +++ b/src/librustc_typeck/coherence/impls.rs @@ -28,8 +28,8 @@ struct ImplsChecker<'cx, 'tcx:'cx> { impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v ast::Item) { match item.node { - ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => { - let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id); + ast::ItemImpl(_, _, _, Some(_), _, _) => { + let trait_ref = ty::impl_id_to_trait_ref(self.tcx, item.id); if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { match trait_ref.self_ty().sty { ty::ty_struct(..) | ty::ty_enum(..) => {} diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 7dac1eeb6f117..1913b55f1d8e6 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -106,19 +106,9 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> { //debug!("(checking coherence) item '{}'", token::get_ident(item.ident)); - match item.node { - ItemImpl(_, _, _, ref opt_trait, _, _) => { - match opt_trait.clone() { - Some(opt_trait) => { - self.cc.check_implementation(item, &[opt_trait]); - } - None => self.cc.check_implementation(item, &[]) - } - } - _ => { - // Nothing to do. - } - }; + if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node { + self.cc.check_implementation(item, opt_trait.as_ref()) + } visit::walk_item(self, item); } @@ -155,9 +145,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { self.check_implementations_of_copy(); } - fn check_implementation(&self, - item: &Item, - associated_traits: &[TraitRef]) { + fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) { let tcx = self.crate_context.tcx; let impl_did = local_def(item.id); let self_type = ty::lookup_item_type(tcx, impl_did); @@ -167,9 +155,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { let impl_items = self.create_impl_from_item(item); - for associated_trait in associated_traits { - let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx, - associated_trait.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id); debug!("(checking implementation) adding impl for trait '{}', item '{}'", trait_ref.repr(self.crate_context.tcx), token::get_ident(item.ident)); @@ -191,7 +178,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } Some(base_type_def_id) => { // FIXME: Gather up default methods? - if associated_traits.len() == 0 { + if opt_trait.is_none() { self.add_inherent_impl(base_type_def_id, impl_did); } } @@ -289,7 +276,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // Converts an implementation in the AST to a vector of items. fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { - ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => { + ItemImpl(_, _, _, ref opt_trait, _, ref ast_items) => { let mut items: Vec = ast_items.iter() .map(|ast_item| { @@ -304,13 +291,12 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } }).collect(); - if let Some(ref trait_ref) = *trait_refs { - let ty_trait_ref = ty::node_id_to_trait_ref( - self.crate_context.tcx, - trait_ref.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, + item.id); self.instantiate_default_methods(local_def(item.id), - &*ty_trait_ref, + &*trait_ref, &mut items); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 353e8e097a897..65c1d7adf4876 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -740,7 +740,9 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { if let Some(ref trait_ref) = *opt_trait_ref { astconv::instantiate_trait_ref(ccx, &ExplicitRscope, - trait_ref, + &trait_ref.path, + trait_ref.ref_id, + Some(it.id), Some(selfty), None); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d05aa4d20066b..8e08c5278d004 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1629,7 +1629,7 @@ impl Clean for ast::QPath { Type::QPath { name: self.item_path.identifier.clean(cx), self_type: box self.self_type.clean(cx), - trait_: box self.trait_ref.clean(cx) + trait_: box resolve_type(cx, self.trait_path.clean(cx), 0) } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7c83286f656b1..5f9776425c3ff 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -782,11 +782,11 @@ pub enum Expr_ { /// /// as SomeTrait>::SomeAssociatedItem /// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~ -/// self_type trait_name item_path +/// self_type trait_path item_path #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct QPath { pub self_type: P, - pub trait_ref: P, + pub trait_path: Path, pub item_path: PathSegment, } @@ -1258,12 +1258,12 @@ pub enum Ty_ { /// /// Type parameters are stored in the Path itself TyPath(Path), + /// A "qualified path", e.g. ` as SomeTrait>::SomeType` + TyQPath(P), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` TyPolyTraitRef(TyParamBounds), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - TyQPath(P), /// No-op; kept solely so that we can pretty-print faithfully TyParen(P), /// Unused for now diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 6ea37aaf72ce2..f207efc5b6c34 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -561,13 +561,18 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { visit::walk_trait_item(self, tm); } - fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { + fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) { self.operation.visit_id(lifetime.id); } - fn visit_lifetime_def(&mut self, def: &'v LifetimeDef) { + fn visit_lifetime_def(&mut self, def: &LifetimeDef) { self.visit_lifetime_ref(&def.lifetime); } + + fn visit_trait_ref(&mut self, trait_ref: &TraitRef) { + self.operation.visit_id(trait_ref.ref_id); + visit::walk_trait_ref(self, trait_ref); + } } pub fn visit_ids_for_inlined_item(item: &InlinedItem, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index ae4d2a8004598..c0421fb6f1cf2 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -429,13 +429,13 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), TyPath(path) => TyPath(fld.fold_path(path)), + TyQPath(qpath) => { + TyQPath(fld.fold_qpath(qpath)) + } TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds)) } - TyQPath(qpath) => { - TyQPath(fld.fold_qpath(qpath)) - } TyFixedLengthVec(ty, e) => { TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e)) } @@ -454,7 +454,7 @@ pub fn noop_fold_qpath(qpath: P, fld: &mut T) -> P { qpath.map(|qpath| { QPath { self_type: fld.fold_ty(qpath.self_type), - trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)), + trait_path: fld.fold_path(qpath.trait_path), item_path: PathSegment { identifier: fld.fold_ident(qpath.item_path.identifier), parameters: fld.fold_path_parameters(qpath.item_path.parameters), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bcef7238d7f21..b2f597258558d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1525,13 +1525,13 @@ impl<'a> Parser<'a> { // QUALIFIED PATH `::item` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); let item_name = self.parse_ident(); TyQPath(P(QPath { self_type: self_type, - trait_ref: P(trait_ref), + trait_path: trait_path, item_path: ast::PathSegment { identifier: item_name, parameters: ast::PathParameters::none() @@ -2220,7 +2220,7 @@ impl<'a> Parser<'a> { // QUALIFIED PATH `::item::<'a, T>` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); let item_name = self.parse_ident(); @@ -2240,7 +2240,7 @@ impl<'a> Parser<'a> { let hi = self.span.hi; return self.mk_expr(lo, hi, ExprQPath(P(QPath { self_type: self_type, - trait_ref: P(trait_ref), + trait_path: trait_path, item_path: ast::PathSegment { identifier: item_name, parameters: parameters diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 752d34a19c6e1..3cfb90a3e6818 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2047,7 +2047,7 @@ impl<'a> State<'a> { try!(self.print_type(&*qpath.self_type)); try!(space(&mut self.s)); try!(self.word_space("as")); - try!(self.print_trait_ref(&*qpath.trait_ref)); + try!(self.print_path(&qpath.trait_path, false)); try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); try!(self.print_ident(qpath.item_path.identifier)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4586495227d02..4e90adea90c62 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -125,8 +125,8 @@ pub trait Visitor<'v> : Sized { fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) } - fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) { - walk_qpath(self, qpath_span, qpath) + fn visit_qpath(&mut self, qpath: &'v QPath, _id: ast::NodeId) { + walk_qpath(self, qpath) } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) @@ -402,13 +402,13 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyPath(ref path) => { visitor.visit_path(path, typ.id); } + TyQPath(ref qpath) => { + visitor.visit_qpath(&**qpath, typ.id); + } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); walk_ty_param_bounds_helper(visitor, bounds); } - TyQPath(ref qpath) => { - visitor.visit_qpath(typ.span, &**qpath); - } TyFixedLengthVec(ref ty, ref expression) => { visitor.visit_ty(&**ty); visitor.visit_expr(&**expression) @@ -436,12 +436,10 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } } -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, - qpath_span: Span, - qpath: &'v QPath) { +pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath) { visitor.visit_ty(&*qpath.self_type); - visitor.visit_trait_ref(&*qpath.trait_ref); - visitor.visit_path_segment(qpath_span, &qpath.item_path); + walk_path(visitor, &qpath.trait_path); + visitor.visit_path_segment(qpath.trait_path.span, &qpath.item_path); } pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, @@ -873,7 +871,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_path(path, expression.id) } ExprQPath(ref qpath) => { - visitor.visit_qpath(expression.span, &**qpath) + visitor.visit_qpath(&**qpath, expression.id) } ExprBreak(_) | ExprAgain(_) => {} ExprRet(ref optional_expression) => { diff --git a/src/test/compile-fail/ufcs-qpath-missing-params.rs b/src/test/compile-fail/ufcs-qpath-missing-params.rs index f4e18265fd990..b3fe178dc455e 100644 --- a/src/test/compile-fail/ufcs-qpath-missing-params.rs +++ b/src/test/compile-fail/ufcs-qpath-missing-params.rs @@ -12,5 +12,5 @@ use std::borrow::IntoCow; fn main() { ::into_cow("foo".to_string()); - //~^ ERROR wrong number of type arguments: expected 1, found 0 + //~^ ERROR too few type parameters provided: expected 1 parameter(s) } From 9739ae4d09a637b914171c873953bb8c13daa0c0 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 30 Jan 2015 11:26:49 +0200 Subject: [PATCH 05/25] rustc: remove unused ForeignType item family. --- src/librustc/metadata/decoder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 7c0ffe8f3d81a..e390620bcabe4 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -119,7 +119,6 @@ enum Family { StaticMethod, // F Method, // h Type, // y - ForeignType, // T Mod, // m ForeignMod, // n Enum, // t @@ -145,7 +144,6 @@ fn item_family(item: rbml::Doc) -> Family { 'F' => StaticMethod, 'h' => Method, 'y' => Type, - 'T' => ForeignType, 'm' => Mod, 'n' => ForeignMod, 't' => Enum, @@ -346,7 +344,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) _ => panic!() } } - Type | ForeignType => DlDef(def::DefTy(did, false)), + Type => DlDef(def::DefTy(did, false)), Mod => DlDef(def::DefMod(did)), ForeignMod => DlDef(def::DefForeignMod(did)), StructVariant => { From 9a69378e8b61473fbfa55f347286718ca4c5d399 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 30 Jan 2015 12:16:59 +0200 Subject: [PATCH 06/25] rustc: load DefAssociatedTy from cross-crate metadata. Fixes #20542. --- src/librustc/metadata/decoder.rs | 42 +++++++++++-------- src/librustc/middle/astencode.rs | 3 +- src/librustc/middle/def.rs | 4 +- src/librustc_resolve/build_reduced_graph.rs | 8 ++-- src/librustc_typeck/astconv.rs | 5 +-- .../associated-types-in-ambiguous-context.rs | 3 ++ 6 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index e390620bcabe4..6d2269b74a218 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -172,16 +172,13 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility { } } -fn item_sort(item: rbml::Doc) -> char { +fn item_sort(item: rbml::Doc) -> Option { let mut ret = None; reader::tagged_docs(item, tag_item_trait_item_sort, |doc| { ret = Some(doc.as_str_slice().as_bytes()[0] as char); false }); - match ret { - Some(r) => r, - None => panic!("No item_sort found") - } + ret } fn item_symbol(item: rbml::Doc) -> String { @@ -344,7 +341,14 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) _ => panic!() } } - Type => DlDef(def::DefTy(did, false)), + Type => { + if item_sort(item) == Some('t') { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + DlDef(def::DefAssociatedTy(trait_did, did)) + } else { + DlDef(def::DefTy(did, false)) + } + } Mod => DlDef(def::DefMod(did)), ForeignMod => DlDef(def::DefForeignMod(did)), StructVariant => { @@ -829,8 +833,10 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId) tag_item_impl_item, |doc| { let def_id = item_def_id(doc, cdata); match item_sort(doc) { - 'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)), - 't' => impl_items.push(ty::TypeTraitItemId(def_id)), + Some('r') | Some('p') => { + impl_items.push(ty::MethodTraitItemId(def_id)) + } + Some('t') => impl_items.push(ty::TypeTraitItemId(def_id)), _ => panic!("unknown impl item sort"), } true @@ -854,14 +860,14 @@ pub fn get_trait_item_name_and_kind(intr: Rc, let doc = lookup_item(id, cdata.data()); let name = item_name(&*intr, doc); match item_sort(doc) { - 'r' | 'p' => { + Some('r') | Some('p') => { let explicit_self = get_explicit_self(doc); (name, def::TraitItemKind::from_explicit_self_category(explicit_self)) } - 't' => (name, def::TypeTraitItemKind), + Some('t') => (name, def::TypeTraitItemKind), c => { panic!("get_trait_item_name_and_kind(): unknown trait item kind \ - in metadata: `{}`", c) + in metadata: `{:?}`", c) } } } @@ -887,7 +893,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, let vis = item_visibility(method_doc); match item_sort(method_doc) { - 'r' | 'p' => { + Some('r') | Some('p') => { let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics); let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics); let fty = doc_method_fty(method_doc, tcx, cdata); @@ -904,7 +910,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, container, provided_source))) } - 't' => { + Some('t') => { ty::TypeTraitItem(Rc::new(ty::AssociatedType { name: name, vis: vis, @@ -924,8 +930,10 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId) reader::tagged_docs(item, tag_item_trait_item, |mth| { let def_id = item_def_id(mth, cdata); match item_sort(mth) { - 'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)), - 't' => result.push(ty::TypeTraitItemId(def_id)), + Some('r') | Some('p') => { + result.push(ty::MethodTraitItemId(def_id)); + } + Some('t') => result.push(ty::TypeTraitItemId(def_id)), _ => panic!("unknown trait item sort"), } true @@ -954,7 +962,7 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc, let did = item_def_id(mth_id, cdata); let mth = lookup_item(did.node, data); - if item_sort(mth) == 'p' { + if item_sort(mth) == Some('p') { let trait_item = get_impl_or_trait_item(intr.clone(), cdata, did.node, @@ -1558,7 +1566,7 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool { let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items); match maybe_find_item(id, items) { None => false, - Some(item) => item_sort(item) == 't', + Some(item) => item_sort(item) == Some('t'), } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index eb723830d383c..c4b874f793019 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -442,7 +442,8 @@ impl tr for def::Def { }, def::DefTrait(did) => def::DefTrait(did.tr(dcx)), def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum), - def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)), + def::DefAssociatedTy(trait_did, did) => + def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)), def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) => def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident), def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) => diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 7857bcad8135d..a341b55333f41 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -32,7 +32,7 @@ pub enum Def { DefLocal(ast::NodeId), DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */), DefTy(ast::DefId, bool /* is_enum */), - DefAssociatedTy(ast::DefId), + DefAssociatedTy(ast::DefId /* trait */, ast::DefId), // A partially resolved path to an associated type `T::U` where `T` is a concrete // type (indicated by the DefId) which implements a trait which has an associated // type `U` (indicated by the Ident). @@ -134,7 +134,7 @@ impl Def { match *self { DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | - DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) | + DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) | DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _, _) | DefConst(id) | DefAssociatedPath(TyParamProvenance::FromSelf(id), _) | diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index ad5fa600bd81b..7c6e537f0be23 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -638,8 +638,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { &new_parent, ForbidDuplicateTypesAndModules, typedef.span); - let def = DefAssociatedTy(local_def( - typedef.id)); + let def = DefAssociatedTy(local_def(item.id), + local_def(typedef.id)); // NB: not IMPORTABLE let modifiers = if typedef.vis == ast::Public { PUBLIC @@ -716,8 +716,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { (name, static_flag) } ast::TypeTraitItem(ref associated_type) => { - let def = DefAssociatedTy(local_def( - associated_type.ty_param.id)); + let def = DefAssociatedTy(local_def(item.id), + local_def(associated_type.ty_param.id)); let name_bindings = self.add_child(associated_type.ty_param.ident.name, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3c4af12c1f994..8b5cb1f974666 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1236,9 +1236,8 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, def::DefPrimTy(_) => { panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); } - def::DefAssociatedTy(trait_type_id) => { - let path_str = tcx.map.path_to_string( - tcx.map.get_parent(trait_type_id.node)); + def::DefAssociatedTy(trait_id, _) => { + let path_str = ty::item_path_str(tcx, trait_id); span_err!(tcx.sess, ast_ty.span, E0223, "ambiguous associated \ type; specify the type \ diff --git a/src/test/compile-fail/associated-types-in-ambiguous-context.rs b/src/test/compile-fail/associated-types-in-ambiguous-context.rs index 3999e9cbe753d..becbc27138b77 100644 --- a/src/test/compile-fail/associated-types-in-ambiguous-context.rs +++ b/src/test/compile-fail/associated-types-in-ambiguous-context.rs @@ -22,5 +22,8 @@ trait Grab { //~^ ERROR ambiguous associated type } +type X = std::ops::Deref::Target; +//~^ ERROR ambiguous associated type + fn main() { } From 326711e9bdee2e8f467ad716109b5a270b61478d Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 31 Jan 2015 05:51:21 +0200 Subject: [PATCH 07/25] rustc_resolve: use DefAssociatedTy for TyQPath. --- src/librustc_resolve/lib.rs | 35 ++++++--- src/librustc_typeck/astconv.rs | 113 +++++++++++++++------------ src/librustdoc/clean/mod.rs | 18 ++--- src/test/compile-fail/issue-19883.rs | 13 +-- 4 files changed, 95 insertions(+), 84 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1380e2367256d..914663e75814e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3563,8 +3563,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match ty.node { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. + TyPath(_) | TyQPath(_) => { + let mut path_from_qpath; + let path = match ty.node { + TyPath(ref path) => path, + TyQPath(ref qpath) => { + self.resolve_type(&*qpath.self_type); + + // Just make sure the trait is valid, don't record a def. + self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath); + self.def_map.borrow_mut().remove(&ty.id); + + path_from_qpath = qpath.trait_path.clone(); + path_from_qpath.segments.push(qpath.item_path.clone()); + &path_from_qpath + } + _ => unreachable!() + }; - TyPath(ref path) => { // This is a path in the type namespace. Walk through scopes // looking for it. let mut result_def = None; @@ -3609,7 +3625,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(ty.id, def); } None => { - let msg = format!("use of undeclared type name `{}`", + let kind = match ty.node { + TyQPath(_) => "associated type", + _ => "type name" + }; + let msg = format!("use of undeclared {} `{}`", kind, self.path_names_to_string(path)); self.resolve_error(ty.span, &msg[..]); } @@ -3621,17 +3641,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_type_parameter_bounds(bound_vec, TraitBoundingTypeParameter); } - TyQPath(ref qpath) => { - self.resolve_type(&*qpath.self_type); - self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath); - for ty in qpath.item_path.parameters.types() { - self.resolve_type(&**ty); - } - for binding in qpath.item_path.parameters.bindings() { - self.resolve_type(&*binding.ty); - } - } - TyPolyTraitRef(ref bounds) => { self.resolve_type_parameter_bounds(bounds, TraitObject); visit::walk_ty(self, ty); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8b5cb1f974666..cf567f709f52a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -606,9 +606,10 @@ pub fn instantiate_trait_ref<'tcx>( def::DefTrait(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, + path.span, trait_def_id, self_ty, - path, + path.segments.last().unwrap(), projections); if let Some(id) = impl_id { this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone()); @@ -637,9 +638,10 @@ fn object_path_to_poly_trait_ref<'a,'tcx>( let mut tmp = Vec::new(); let trait_ref = ty::Binder(ast_path_to_trait_ref(this, &shifted_rscope, + path.span, trait_def_id, None, - path, + path.segments.last().unwrap(), Some(&mut tmp))); projections.extend(tmp.into_iter().map(ty::Binder)); trait_ref @@ -648,24 +650,25 @@ fn object_path_to_poly_trait_ref<'a,'tcx>( fn ast_path_to_trait_ref<'a,'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, trait_def_id: ast::DefId, self_ty: Option>, - path: &ast::Path, + trait_segment: &ast::PathSegment, mut projections: Option<&mut Vec>>) -> Rc> { - debug!("ast_path_to_trait_ref {:?}", path); + debug!("ast_path_to_trait_ref {:?}", trait_segment); let trait_def = this.get_trait_def(trait_def_id); - let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters { + let (regions, types, assoc_bindings) = match trait_segment.parameters { ast::AngleBracketedParameters(ref data) => { // For now, require that parenthetical notation be used // only with `Fn()` etc. if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar { - span_err!(this.tcx().sess, path.span, E0215, + span_err!(this.tcx().sess, span, E0215, "angle-bracket notation is not stable when \ used with the `Fn` family of traits, use parentheses"); - span_help!(this.tcx().sess, path.span, + span_help!(this.tcx().sess, span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to enable"); } @@ -676,10 +679,10 @@ fn ast_path_to_trait_ref<'a,'tcx>( // For now, require that parenthetical notation be used // only with `Fn()` etc. if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar { - span_err!(this.tcx().sess, path.span, E0216, + span_err!(this.tcx().sess, span, E0216, "parenthetical notation is only stable when \ used with the `Fn` family of traits"); - span_help!(this.tcx().sess, path.span, + span_help!(this.tcx().sess, span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to enable"); } @@ -689,7 +692,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( }; let substs = create_substs_for_ast_path(this, - path.span, + span, &trait_def.generics, self_ty, types, @@ -1047,33 +1050,42 @@ fn trait_defines_associated_type_named(this: &AstConv, fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, rscope: &RegionScope, - ast_ty: &ast::Ty, // the TyQPath - qpath: &ast::QPath) + span: Span, + opt_self_ty: Option<&ast::Ty>, + trait_def_id: ast::DefId, + trait_segment: &ast::PathSegment, + item_segment: &ast::PathSegment) -> Ty<'tcx> { - debug!("qpath_to_ty(ast_ty={})", - ast_ty.repr(this.tcx())); + let tcx = this.tcx(); - let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type); + let self_ty = if let Some(ty) = opt_self_ty { + ast_ty_to_ty(this, rscope, ty) + } else { + let path_str = ty::item_path_str(tcx, trait_def_id); + span_err!(tcx.sess, span, E0223, + "ambiguous associated type; specify the type using the syntax \ + `::{}`", + path_str, &token::get_ident(item_segment.identifier)); + return tcx.types.err; + }; - debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx())); + debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx)); - let trait_ref = instantiate_trait_ref(this, + let trait_ref = ast_path_to_trait_ref(this, rscope, - &qpath.trait_path, - ast_ty.id, - None, - Some(self_type), + span, + trait_def_id, + Some(self_ty), + trait_segment, None); - debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx())); + debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx)); // `::U` shouldn't parse right now. - assert!(qpath.item_path.parameters.is_empty()); + assert!(item_segment.parameters.is_empty()); - return this.projected_ty(ast_ty.span, - trait_ref, - qpath.item_path.identifier.name); + this.projected_ty(span, trait_ref, item_segment.identifier.name) } /// Convert a type supplied as value for a type argument from AST into our @@ -1189,13 +1201,17 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..]) } - ast::TyPath(ref path) => { + ast::TyPath(_) | ast::TyQPath(_) => { + let simple_path = |&:| match ast_ty.node { + ast::TyPath(ref path) => path, + _ => tcx.sess.span_bug(ast_ty.span, "expected non-qualified path") + }; let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { None => { tcx.sess .span_bug(ast_ty.span, &format!("unbound path {}", - path.repr(tcx))) + ast_ty.repr(tcx))) } Some(&d) => d }; @@ -1208,24 +1224,24 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, let trait_ref = object_path_to_poly_trait_ref(this, rscope, trait_def_id, - path, + simple_path(), &mut projection_bounds); - trait_ref_to_object_type(this, rscope, path.span, + trait_ref_to_object_type(this, rscope, ast_ty.span, trait_ref, projection_bounds, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { - ast_path_to_ty(this, rscope, did, path).ty + ast_path_to_ty(this, rscope, did, simple_path()).ty } def::DefTyParam(space, index, _, name) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); + check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS); ty::mk_param(tcx, space, index, name) } def::DefSelfTy(_) => { // n.b.: resolve guarantees that the this type only appears in a // trait, which we rely upon in various places when creating // substs - check_path_args(tcx, path, NO_TPS | NO_REGIONS); + check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS); ty::mk_self_type(tcx) } def::DefMod(id) => { @@ -1236,20 +1252,20 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, def::DefPrimTy(_) => { panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); } - def::DefAssociatedTy(trait_id, _) => { - let path_str = ty::item_path_str(tcx, trait_id); - span_err!(tcx.sess, ast_ty.span, E0223, - "ambiguous associated \ - type; specify the type \ - using the syntax `::{}`", - path_str, - &token::get_ident( - path.segments - .last() - .unwrap() - .identifier)); - this.tcx().types.err + def::DefAssociatedTy(trait_did, _) => { + let (opt_self_ty, trait_segment, item_segment) = match ast_ty.node { + ast::TyQPath(ref qpath) => { + (Some(&*qpath.self_type), qpath.trait_path.segments.last().unwrap(), + &qpath.item_path) + } + ast::TyPath(ref path) => { + (None, &path.segments[path.segments.len()-2], + path.segments.last().unwrap()) + } + _ => unreachable!() + }; + qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, + trait_did, trait_segment, item_segment) } def::DefAssociatedPath(provenance, assoc_ident) => { associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) @@ -1262,9 +1278,6 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, } } } - ast::TyQPath(ref qpath) => { - qpath_to_ty(this, rscope, ast_ty, &**qpath) - } ast::TyFixedLengthVec(ref ty, ref e) => { match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) { Ok(ref r) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8e08c5278d004..aff15761ae775 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1499,6 +1499,13 @@ impl Clean for ast::Ty { TyPath(ref p) => { resolve_type(cx, p.clean(cx), self.id) } + TyQPath(ref qp) => { + Type::QPath { + name: qp.item_path.identifier.clean(cx), + self_type: box qp.self_type.clean(cx), + trait_: box resolve_type(cx, qp.trait_path.clean(cx), self.id) + } + } TyObjectSum(ref lhs, ref bounds) => { let lhs_ty = lhs.clean(cx); match lhs_ty { @@ -1512,7 +1519,6 @@ impl Clean for ast::Ty { } TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyParen(ref ty) => ty.clean(cx), - TyQPath(ref qp) => qp.clean(cx), TyPolyTraitRef(ref bounds) => { PolyTraitRef(bounds.clean(cx)) }, @@ -1624,16 +1630,6 @@ impl<'tcx> Clean for ty::Ty<'tcx> { } } -impl Clean for ast::QPath { - fn clean(&self, cx: &DocContext) -> Type { - Type::QPath { - name: self.item_path.identifier.clean(cx), - self_type: box self.self_type.clean(cx), - trait_: box resolve_type(cx, self.trait_path.clean(cx), 0) - } - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum StructField { HiddenStructField, // inserted later by strip passes diff --git a/src/test/compile-fail/issue-19883.rs b/src/test/compile-fail/issue-19883.rs index bbc5ee6c8f36e..c6ff82364b3e7 100644 --- a/src/test/compile-fail/issue-19883.rs +++ b/src/test/compile-fail/issue-19883.rs @@ -15,18 +15,11 @@ trait From { } trait To { - // This is a typo, the return type should be `>::Output` - fn to>( - self - //~^ error: the trait `core::marker::Sized` is not implemented - ) -> + fn to>(self) -> >::Dst - //~^ error: the trait `core::marker::Sized` is not implemented + //~^ ERROR use of undeclared associated type `From::Dst` { - From::from( - //~^ error: the trait `core::marker::Sized` is not implemented - self - ) + From::from(self) } } From ffb8092ccf8dd186a9a03e6808d04a7276206793 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 31 Jan 2015 21:20:24 +0200 Subject: [PATCH 08/25] syntax: use a single Path for Trait::Item in QPath. --- src/librustc/lint/context.rs | 5 - src/librustc/lint/mod.rs | 1 - src/librustc/middle/dead.rs | 5 - src/librustc_back/svh.rs | 5 - src/librustc_privacy/lib.rs | 5 - src/librustc_resolve/lib.rs | 158 +++++++++++++++---------------- src/librustc_trans/save/mod.rs | 12 +-- src/librustc_typeck/astconv.rs | 42 ++++---- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/collect.rs | 3 +- src/librustdoc/clean/mod.rs | 6 +- src/libsyntax/ast.rs | 11 +-- src/libsyntax/ext/build.rs | 44 ++++----- src/libsyntax/fold.rs | 27 ++---- src/libsyntax/parse/parser.rs | 32 +++---- src/libsyntax/print/pprust.rs | 53 +++++------ src/libsyntax/visit.rs | 15 +-- 17 files changed, 177 insertions(+), 251 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 81fb1c8e913f6..d344ee8c881c5 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -717,11 +717,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { visit::walk_path(self, p); } - fn visit_qpath(&mut self, p: &ast::QPath, id: ast::NodeId) { - run_lints!(self, check_qpath, p, id); - visit::walk_qpath(self, p); - } - fn visit_attribute(&mut self, attr: &ast::Attribute) { run_lints!(self, check_attribute, attr); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 1e2ddb7db0bfa..021827b0101c8 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -157,7 +157,6 @@ pub trait LintPass { fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { } fn check_mac(&mut self, _: &Context, _: &ast::Mac) { } fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { } - fn check_qpath(&mut self, _: &Context, _: &ast::QPath, _: ast::NodeId) { } fn check_attribute(&mut self, _: &Context, _: &ast::Attribute) { } /// Called when entering a syntax node that can have lint attributes such diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 4f9b900a5f876..ff78deb8d12ea 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -306,11 +306,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { visit::walk_path(self, path); } - fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { - self.lookup_and_handle_definition(&id); - visit::walk_qpath(self, qpath); - } - fn visit_item(&mut self, _: &ast::Item) { // Do not recurse into items. These items will be added to the // worklist and recursed into manually if necessary. diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index af886ed25ab20..2fc43ab26b58e 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -194,7 +194,6 @@ mod svh_visitor { SawVariant, SawExplicitSelf, SawPath, - SawQPath, SawOptLifetimeRef, SawBlock, SawPat, @@ -486,10 +485,6 @@ mod svh_visitor { SawPath.hash(self.st); visit::walk_path(self, path) } - fn visit_qpath(&mut self, qpath: &QPath, _: ast::NodeId) { - SawQPath.hash(self.st); visit::walk_qpath(self, qpath) - } - fn visit_block(&mut self, b: &Block) { SawBlock.hash(self.st); visit::walk_block(self, b) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 1f8ae3fbbcbb4..838ba9c658cf1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1021,11 +1021,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { self.check_path(path.span, id, path.segments.last().unwrap().identifier); visit::walk_path(self, path); } - - fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { - self.check_path(qpath.trait_path.span, id, qpath.item_path.identifier); - visit::walk_qpath(self, qpath); - } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 914663e75814e..6584e3cc19d4c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1096,8 +1096,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result } - fn path_names_to_string(&self, path: &Path) -> String { - let names: Vec = path.segments + fn path_names_to_string(&self, path: &Path, depth: usize) -> String { + let names: Vec = path.segments[..path.segments.len()-depth] .iter() .map(|seg| seg.identifier.name) .collect(); @@ -3162,7 +3162,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match *type_parameter_bound { TraitTyParamBound(ref tref, _) => { self.resolve_trait_reference(tref.trait_ref.ref_id, - &tref.trait_ref.path, + &tref.trait_ref.path, 0, reference_type) } RegionTyParamBound(..) => {} @@ -3172,10 +3172,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_trait_reference(&mut self, id: NodeId, trait_path: &Path, + path_depth: usize, reference_type: TraitReferenceType) { - match self.resolve_path(id, trait_path, TypeNS, true) { + match self.resolve_path(id, trait_path, path_depth, TypeNS, true) { None => { - let path_str = self.path_names_to_string(trait_path); + let path_str = self.path_names_to_string(trait_path, path_depth); let usage_str = match reference_type { TraitBoundingTypeParameter => "bound type parameter with", TraitImplementation => "implement", @@ -3196,7 +3197,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (def, _) => { self.resolve_error(trait_path.span, &format!("`{}` is not a trait", - self.path_names_to_string(trait_path))); + self.path_names_to_string(trait_path, path_depth))); // If it's a typedef, give a note if let DefTy(..) = def { @@ -3221,7 +3222,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { - match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) { + match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) { Some((def @ DefTyParam(..), last_private)) => { self.record_def(eq_pred.id, (def, last_private)); } @@ -3297,7 +3298,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let new_val = match *opt_trait_ref { Some(ref trait_ref) => { self.resolve_trait_reference(trait_ref.ref_id, - &trait_ref.path, + &trait_ref.path, 0, TraitImplementation); match self.def_map.borrow().get(&trait_ref.ref_id) { @@ -3395,7 +3396,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If there is a TraitRef in scope for an impl, then the method must be in the trait. if let Some((did, ref trait_ref)) = self.current_trait_ref { if self.trait_item_map.get(&(name, did)).is_none() { - let path_str = self.path_names_to_string(&trait_ref.path); + let path_str = self.path_names_to_string(&trait_ref.path, 0); self.resolve_error(span, &format!("method `{}` is not a member of trait `{}`", token::get_name(name), @@ -3563,23 +3564,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match ty.node { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. - TyPath(_) | TyQPath(_) => { - let mut path_from_qpath; - let path = match ty.node { - TyPath(ref path) => path, - TyQPath(ref qpath) => { - self.resolve_type(&*qpath.self_type); - - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath); - self.def_map.borrow_mut().remove(&ty.id); - - path_from_qpath = qpath.trait_path.clone(); - path_from_qpath.segments.push(qpath.item_path.clone()); - &path_from_qpath - } - _ => unreachable!() - }; + + TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => { + if let TyQPath(ref qpath) = ty.node { + self.resolve_type(&*qpath.self_type); + + // Just make sure the trait is valid, don't record a def. + self.resolve_trait_reference(ty.id, path, 1, TraitQPath); + self.def_map.borrow_mut().remove(&ty.id); + } // This is a path in the type namespace. Walk through scopes // looking for it. @@ -3612,7 +3605,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let None = result_def { - result_def = self.resolve_path(ty.id, path, TypeNS, true); + result_def = self.resolve_path(ty.id, path, 0, TypeNS, true); } match result_def { @@ -3620,7 +3613,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ (id {}) = {:?}", - self.path_names_to_string(path), + self.path_names_to_string(path, 0), ty.id, def); self.record_def(ty.id, def); } @@ -3630,7 +3623,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => "type name" }; let msg = format!("use of undeclared {} `{}`", kind, - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.resolve_error(ty.span, &msg[..]); } } @@ -3765,7 +3758,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatEnum(ref path, _) => { // This must be an enum variant, struct or const. - match self.resolve_path(pat_id, path, ValueNS, false) { + match self.resolve_path(pat_id, path, 0, ValueNS, false) { Some(def @ (DefVariant(..), _)) | Some(def @ (DefStruct(..), _)) | Some(def @ (DefConst(..), _)) => { @@ -3808,7 +3801,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } PatStruct(ref path, _, _) => { - match self.resolve_path(pat_id, path, TypeNS, false) { + match self.resolve_path(pat_id, path, 0, TypeNS, false) { Some(definition) => { self.record_def(pattern.id, definition); } @@ -3816,7 +3809,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } @@ -3896,34 +3889,38 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_path(&mut self, id: NodeId, path: &Path, + path_depth: usize, namespace: Namespace, check_ribs: bool) -> Option<(Def, LastPrivate)> { + let span = path.span; + let segments = &path.segments[..path.segments.len()-path_depth]; + // First, resolve the types and associated type bindings. - for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) { + for ty in segments.iter().flat_map(|s| s.parameters.types().into_iter()) { self.resolve_type(&**ty); } - for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { + for binding in segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { self.resolve_type(&*binding.ty); } // A special case for sugared associated type paths `T::A` where `T` is // a type parameter and `A` is an associated type on some bound of `T`. - if namespace == TypeNS && path.segments.len() == 2 { - match self.resolve_identifier(path.segments[0].identifier, + if namespace == TypeNS && segments.len() == 2 { + match self.resolve_identifier(segments[0].identifier, TypeNS, true, - path.span) { + span) { Some((def, last_private)) => { match def { DefTyParam(_, _, did, _) => { let def = DefAssociatedPath(TyParamProvenance::FromParam(did), - path.segments.last() + segments.last() .unwrap().identifier); return Some((def, last_private)); } DefSelfTy(nid) => { let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)), - path.segments.last() + segments.last() .unwrap().identifier); return Some((def, last_private)); } @@ -3935,24 +3932,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if path.global { - return self.resolve_crate_relative_path(path, namespace); + return self.resolve_crate_relative_path(span, segments, namespace); } // Try to find a path to an item in a module. let unqualified_def = - self.resolve_identifier(path.segments.last().unwrap().identifier, + self.resolve_identifier(segments.last().unwrap().identifier, namespace, check_ribs, - path.span); + span); - if path.segments.len() > 1 { - let def = self.resolve_module_relative_path(path, namespace); + if segments.len() > 1 { + let def = self.resolve_module_relative_path(span, segments, namespace); match (def, unqualified_def) { (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => { self.session .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, - id, - path.span, + id, span, "unnecessary qualification".to_string()); } _ => () @@ -4063,12 +4059,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // resolve a "module-relative" path, e.g. a::b::c fn resolve_module_relative_path(&mut self, - path: &Path, + span: Span, + segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = path.segments.init().iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = segments.init().iter() + .map(|ps| ps.identifier.name) + .collect::>(); let containing_module; let last_private; @@ -4076,7 +4073,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_module_path(module, &module_path[..], UseLexicalScope, - path.span, + span, PathSearch) { Failed(err) => { let (span, msg) = match err { @@ -4084,7 +4081,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { let msg = format!("Use of undeclared type or module `{}`", self.names_to_string(&module_path)); - (path.span, msg) + (span, msg) } }; @@ -4099,7 +4096,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let name = path.segments.last().unwrap().identifier.name; + let name = segments.last().unwrap().identifier.name; let def = match self.resolve_definition_of_name_in_module(containing_module.clone(), name, namespace) { @@ -4120,12 +4117,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Invariant: This must be called only during main resolution, not during /// import resolution. fn resolve_crate_relative_path(&mut self, - path: &Path, + span: Span, + segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = path.segments.init().iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = segments.init().iter() + .map(|ps| ps.identifier.name) + .collect::>(); let root_module = self.graph_root.get_module(); @@ -4134,7 +4132,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_module_path_from_root(root_module, &module_path[..], 0, - path.span, + span, PathSearch, LastMod(AllPublic)) { Failed(err) => { @@ -4143,7 +4141,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { let msg = format!("Use of undeclared module `::{}`", self.names_to_string(&module_path[..])); - (path.span, msg) + (span, msg) } }; @@ -4162,7 +4160,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let name = path.segments.last().unwrap().identifier.name; + let name = segments.last().unwrap().identifier.name; match self.resolve_definition_of_name_in_module(containing_module, name, namespace) { @@ -4342,7 +4340,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match get_module(self, path.span, &name_path[..]) { Some(module) => match module.children.borrow().get(&name) { Some(binding) => { - let p_str = self.path_names_to_string(&path); + let p_str = self.path_names_to_string(&path, 0); match binding.def_for_namespace(ValueNS) { Some(DefStaticMethod(_, provenance)) => { match provenance { @@ -4363,7 +4361,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Look for a method in the current trait. match self.current_trait_ref { Some((did, ref trait_ref)) => { - let path_str = self.path_names_to_string(&trait_ref.path); + let path_str = self.path_names_to_string(&trait_ref.path, 0); match self.trait_item_map.get(&(name, did)) { Some(&StaticMethodTraitItemKind) => { @@ -4426,29 +4424,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // The interpretation of paths depends on whether the path has // multiple elements in it or not. - ExprPath(_) | ExprQPath(_) => { - let mut path_from_qpath; - let path = match expr.node { - ExprPath(ref path) => path, - ExprQPath(ref qpath) => { - self.resolve_type(&*qpath.self_type); + ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { + if let ExprQPath(ref qpath) = expr.node { + self.resolve_type(&*qpath.self_type); - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(expr.id, &qpath.trait_path, TraitQPath); - self.def_map.borrow_mut().remove(&expr.id); + // Just make sure the trait is valid, don't record a def. + self.resolve_trait_reference(expr.id, path, 1, TraitQPath); + self.def_map.borrow_mut().remove(&expr.id); + } - path_from_qpath = qpath.trait_path.clone(); - path_from_qpath.segments.push(qpath.item_path.clone()); - &path_from_qpath - } - _ => unreachable!() - }; // This is a local path in the value namespace. Walk through // scopes looking for it. - match self.resolve_path(expr.id, path, ValueNS, true) { + match self.resolve_path(expr.id, path, 0, ValueNS, true) { // Check if struct variant Some((DefVariant(_, _, true), _)) => { - let path_name = self.path_names_to_string(path); + let path_name = self.path_names_to_string(path, 0); self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ this expression \ @@ -4463,7 +4453,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(def) => { // Write the result into the def map. debug!("(resolving expr) resolved `{}`", - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.record_def(expr.id, def); } @@ -4472,9 +4462,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // (The pattern matching def_tys where the id is in self.structs // matches on regular structs while excluding tuple- and enum-like // structs, which wouldn't result in this error.) - let path_name = self.path_names_to_string(path); + let path_name = self.path_names_to_string(path, 0); match self.with_no_errors(|this| - this.resolve_path(expr.id, path, TypeNS, false)) { + this.resolve_path(expr.id, path, 0, TypeNS, false)) { Some((DefTy(struct_id, _), _)) if self.structs.contains_key(&struct_id) => { self.resolve_error(expr.span, @@ -4557,13 +4547,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that // is checked later during typeck. - match self.resolve_path(expr.id, path, TypeNS, false) { + match self.resolve_path(expr.id, path, 0, TypeNS, false) { Some(definition) => self.record_def(expr.id, definition), result => { debug!("(resolving expression) didn't find struct \ def: {:?}", result); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path)); + self.path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index c928866512892..6a20938da2e47 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1334,16 +1334,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { // Don't need to do anything for function calls, // because just walking the callee path does what we want. visit::walk_expr(self, ex); - }, - ast::ExprPath(ref path) => { - self.process_path(ex.id, path.span, path, None); - visit::walk_path(self, path); } - ast::ExprQPath(ref qpath) => { - let mut path = qpath.trait_path.clone(); - path.segments.push(qpath.item_path.clone()); - self.process_path(ex.id, ex.span, &path, None); - visit::walk_qpath(self, &**qpath); + ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => { + self.process_path(ex.id, path.span, path, None); + visit::walk_expr(self, ex); } ast::ExprStruct(ref path, ref fields, ref base) => self.process_struct_lit(ex, path, fields, base), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index cf567f709f52a..8eb75ece4a145 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -575,8 +575,7 @@ pub fn instantiate_poly_trait_ref<'tcx>( let shifted_rscope = ShiftedRscope::new(rscope); let trait_ref = instantiate_trait_ref(this, &shifted_rscope, - &ast_trait_ref.trait_ref.path, - ast_trait_ref.trait_ref.ref_id, + &ast_trait_ref.trait_ref, None, self_ty, Some(&mut projections)); for projection in projections { @@ -595,14 +594,14 @@ pub fn instantiate_poly_trait_ref<'tcx>( pub fn instantiate_trait_ref<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, - path: &ast::Path, - path_id: ast::NodeId, + trait_ref: &ast::TraitRef, impl_id: Option, self_ty: Option>, projections: Option<&mut Vec>>) -> Rc> { - match ::lookup_def_tcx(this.tcx(), path.span, path_id) { + let path = &trait_ref.path; + match ::lookup_def_tcx(this.tcx(), path.span, trait_ref.ref_id) { def::DefTrait(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, @@ -1201,11 +1200,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..]) } - ast::TyPath(_) | ast::TyQPath(_) => { - let simple_path = |&:| match ast_ty.node { - ast::TyPath(ref path) => path, - _ => tcx.sess.span_bug(ast_ty.span, "expected non-qualified path") - }; + ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { None => { tcx.sess @@ -1224,24 +1219,24 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, let trait_ref = object_path_to_poly_trait_ref(this, rscope, trait_def_id, - simple_path(), + path, &mut projection_bounds); trait_ref_to_object_type(this, rscope, ast_ty.span, trait_ref, projection_bounds, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { - ast_path_to_ty(this, rscope, did, simple_path()).ty + ast_path_to_ty(this, rscope, did, path).ty } def::DefTyParam(space, index, _, name) => { - check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS); + check_path_args(tcx, path, NO_TPS | NO_REGIONS); ty::mk_param(tcx, space, index, name) } def::DefSelfTy(_) => { // n.b.: resolve guarantees that the this type only appears in a // trait, which we rely upon in various places when creating // substs - check_path_args(tcx, simple_path(), NO_TPS | NO_REGIONS); + check_path_args(tcx, path, NO_TPS | NO_REGIONS); ty::mk_self_type(tcx) } def::DefMod(id) => { @@ -1253,19 +1248,14 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); } def::DefAssociatedTy(trait_did, _) => { - let (opt_self_ty, trait_segment, item_segment) = match ast_ty.node { - ast::TyQPath(ref qpath) => { - (Some(&*qpath.self_type), qpath.trait_path.segments.last().unwrap(), - &qpath.item_path) - } - ast::TyPath(ref path) => { - (None, &path.segments[path.segments.len()-2], - path.segments.last().unwrap()) - } - _ => unreachable!() + let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { + Some(&*qpath.self_type) + } else { + None }; - qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, - trait_did, trait_segment, item_segment) + qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, trait_did, + &path.segments[path.segments.len()-2], + path.segments.last().unwrap()) } def::DefAssociatedPath(provenance, assoc_ident) => { associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b6003071f8c72..5b3090be59372 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3614,9 +3614,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let self_ty = fcx.to_ty(&*qpath.self_type); let defn = lookup_def(fcx, expr.span, id); let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - let mut path = qpath.trait_path.clone(); - path.segments.push(qpath.item_path.clone()); - instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty), + instantiate_path(fcx, &qpath.path, scheme, &predicates, Some(self_ty), defn, expr.span, expr.id); // We always require that the type provided as the value for diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 65c1d7adf4876..46e1f6f076a7b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -740,8 +740,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { if let Some(ref trait_ref) = *opt_trait_ref { astconv::instantiate_trait_ref(ccx, &ExplicitRscope, - &trait_ref.path, - trait_ref.ref_id, + trait_ref, Some(it.id), Some(selfty), None); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index aff15761ae775..2af8107622301 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1500,10 +1500,12 @@ impl Clean for ast::Ty { resolve_type(cx, p.clean(cx), self.id) } TyQPath(ref qp) => { + let mut trait_path = qp.path.clone(); + trait_path.segments.pop(); Type::QPath { - name: qp.item_path.identifier.clean(cx), + name: qp.path.segments.last().unwrap().identifier.clean(cx), self_type: box qp.self_type.clean(cx), - trait_: box resolve_type(cx, qp.trait_path.clean(cx), self.id) + trait_: box resolve_type(cx, trait_path.clean(cx), self.id) } } TyObjectSum(ref lhs, ref bounds) => { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5f9776425c3ff..80a5527cb948d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -757,7 +757,7 @@ pub enum Expr_ { /// type parameters, e.g. foo::bar:: ExprPath(Path), /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - ExprQPath(P), + ExprQPath(QPath), ExprAddrOf(Mutability, P), ExprBreak(Option), @@ -781,13 +781,12 @@ pub enum Expr_ { /// A "qualified path": /// /// as SomeTrait>::SomeAssociatedItem -/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~ -/// self_type trait_path item_path +/// ^~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// self_type path #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct QPath { pub self_type: P, - pub trait_path: Path, - pub item_path: PathSegment, + pub path: Path, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -1259,7 +1258,7 @@ pub enum Ty_ { /// Type parameters are stored in the Path itself TyPath(Path), /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - TyQPath(P), + TyQPath(QPath), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index baa2fab044f3f..90842bbab47d2 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -41,16 +41,16 @@ pub trait AstBuilder { -> ast::Path; fn qpath(&self, self_type: P, - trait_ref: P, - ident: ast::Ident ) - -> P; + trait_path: ast::Path, + ident: ast::Ident) + -> ast::QPath; fn qpath_all(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, - bindings: Vec> ) - -> P; + bindings: Vec>) + -> ast::QPath; // types fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; @@ -114,7 +114,7 @@ pub trait AstBuilder { // expressions fn expr(&self, span: Span, node: ast::Expr_) -> P; fn expr_path(&self, path: ast::Path) -> P; - fn expr_qpath(&self, span: Span, qpath: P) -> P; + fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P; fn expr_ident(&self, span: Span, id: ast::Ident) -> P; fn expr_self(&self, span: Span) -> P; @@ -346,40 +346,40 @@ impl<'a> AstBuilder for ExtCtxt<'a> { /// Constructs a qualified path. /// - /// Constructs a path like `::ident`. + /// Constructs a path like `::ident`. fn qpath(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident) - -> P { - self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new()) + -> ast::QPath { + self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) } /// Constructs a qualified path. /// - /// Constructs a path like `::ident`. + /// Constructs a path like `::ident<'a, T, A=Bar>`. fn qpath_all(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, - bindings: Vec> ) - -> P { - let segment = ast::PathSegment { + bindings: Vec>) + -> ast::QPath { + let mut path = trait_path; + path.segments.push(ast::PathSegment { identifier: ident, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), bindings: OwnedSlice::from_vec(bindings), }) - }; + }); - P(ast::QPath { + ast::QPath { self_type: self_type, - trait_ref: trait_ref, - item_path: segment, - }) + path: path + } } fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { @@ -607,7 +607,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } /// Constructs a QPath expression. - fn expr_qpath(&self, span: Span, qpath: P) -> P { + fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P { self.expr(span, ast::ExprQPath(qpath)) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c0421fb6f1cf2..c706ce9065dd5 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -146,10 +146,6 @@ pub trait Folder : Sized { noop_fold_ty(t, self) } - fn fold_qpath(&mut self, t: P) -> P { - noop_fold_qpath(t, self) - } - fn fold_ty_binding(&mut self, t: P) -> P { noop_fold_ty_binding(t, self) } @@ -430,7 +426,10 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyParen(ty) => TyParen(fld.fold_ty(ty)), TyPath(path) => TyPath(fld.fold_path(path)), TyQPath(qpath) => { - TyQPath(fld.fold_qpath(qpath)) + TyQPath(QPath { + self_type: fld.fold_ty(qpath.self_type), + path: fld.fold_path(qpath.path) + }) } TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), @@ -450,19 +449,6 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { }) } -pub fn noop_fold_qpath(qpath: P, fld: &mut T) -> P { - qpath.map(|qpath| { - QPath { - self_type: fld.fold_ty(qpath.self_type), - trait_path: fld.fold_path(qpath.trait_path), - item_path: PathSegment { - identifier: fld.fold_ident(qpath.item_path.identifier), - parameters: fld.fold_path_parameters(qpath.item_path.parameters), - } - } - }) -} - pub fn noop_fold_foreign_mod(ForeignMod {abi, items}: ForeignMod, fld: &mut T) -> ForeignMod { ForeignMod { @@ -1362,7 +1348,10 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> e2.map(|x| folder.fold_expr(x))) } ExprPath(pth) => ExprPath(folder.fold_path(pth)), - ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)), + ExprQPath(qpath) => ExprQPath(QPath { + self_type: folder.fold_ty(qpath.self_type), + path: folder.fold_path(qpath.path) + }), ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b2f597258558d..ad290da7d0a62 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1525,18 +1525,14 @@ impl<'a> Parser<'a> { // QUALIFIED PATH `::item` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); + let mut path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); - let item_name = self.parse_ident(); - TyQPath(P(QPath { - self_type: self_type, - trait_path: trait_path, - item_path: ast::PathSegment { - identifier: item_name, - parameters: ast::PathParameters::none() - } - })) + path.segments.push(ast::PathSegment { + identifier: self.parse_ident(), + parameters: ast::PathParameters::none() + }); + TyQPath(QPath { self_type: self_type, path: path }) } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -2220,7 +2216,7 @@ impl<'a> Parser<'a> { // QUALIFIED PATH `::item::<'a, T>` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); + let mut path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); let item_name = self.parse_ident(); @@ -2237,15 +2233,13 @@ impl<'a> Parser<'a> { } else { ast::PathParameters::none() }; + path.segments.push(ast::PathSegment { + identifier: item_name, + parameters: parameters + }); let hi = self.span.hi; - return self.mk_expr(lo, hi, ExprQPath(P(QPath { - self_type: self_type, - trait_path: trait_path, - item_path: ast::PathSegment { - identifier: item_name, - parameters: parameters - } - }))); + return self.mk_expr(lo, hi, + ExprQPath(QPath { self_type: self_type, path: path })); } if self.eat_keyword(keywords::Move) { return self.parse_lambda_expr(CaptureByValue); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3cfb90a3e6818..11502c29ebb15 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -373,7 +373,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String { } pub fn path_to_string(p: &ast::Path) -> String { - $to_string(|s| s.print_path(p, false)) + $to_string(|s| s.print_path(p, false, 0)) } pub fn ident_to_string(id: &ast::Ident) -> String { @@ -730,7 +730,10 @@ impl<'a> State<'a> { None)); } ast::TyPath(ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); + } + ast::TyQPath(ref qpath) => { + try!(self.print_qpath(qpath, false)) } ast::TyObjectSum(ref ty, ref bounds) => { try!(self.print_type(&**ty)); @@ -739,9 +742,6 @@ impl<'a> State<'a> { ast::TyPolyTraitRef(ref bounds) => { try!(self.print_bounds("", &bounds[..])); } - ast::TyQPath(ref qpath) => { - try!(self.print_qpath(&**qpath, false)) - } ast::TyFixedLengthVec(ref ty, ref v) => { try!(word(&mut self.s, "[")); try!(self.print_type(&**ty)); @@ -1018,7 +1018,7 @@ impl<'a> State<'a> { ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { try!(self.print_visibility(item.vis)); - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "! ")); try!(self.print_ident(item.ident)); try!(self.cbox(indent_unit)); @@ -1033,7 +1033,7 @@ impl<'a> State<'a> { } fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> { - self.print_path(&t.path, false) + self.print_path(&t.path, false, 0) } fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> IoResult<()> { @@ -1297,7 +1297,7 @@ impl<'a> State<'a> { ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { // code copied from ItemMac: - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "! ")); try!(self.cbox(indent_unit)); try!(self.popen()); @@ -1514,7 +1514,7 @@ impl<'a> State<'a> { match m.node { // I think it's reasonable to hide the ctxt here: ast::MacInvocTT(ref pth, ref tts, _) => { - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "!")); match delim { token::Paren => try!(self.popen()), @@ -1584,7 +1584,7 @@ impl<'a> State<'a> { path: &ast::Path, fields: &[ast::Field], wth: &Option>) -> IoResult<()> { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); if !(fields.is_empty() && wth.is_none()) { try!(word(&mut self.s, "{")); try!(self.commasep_cmnt( @@ -1852,8 +1852,8 @@ impl<'a> State<'a> { try!(self.print_expr(&**e)); } } - ast::ExprPath(ref path) => try!(self.print_path(path, true)), - ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)), + ast::ExprPath(ref path) => try!(self.print_path(path, true, 0)), + ast::ExprQPath(ref qpath) => try!(self.print_qpath(qpath, true)), ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); try!(space(&mut self.s)); @@ -2014,16 +2014,14 @@ impl<'a> State<'a> { fn print_path(&mut self, path: &ast::Path, - colons_before_params: bool) + colons_before_params: bool, + depth: usize) -> IoResult<()> { try!(self.maybe_print_comment(path.span.lo)); - if path.global { - try!(word(&mut self.s, "::")); - } - let mut first = true; - for segment in &path.segments { + let mut first = !path.global; + for segment in &path.segments[..path.segments.len()-depth] { if first { first = false } else { @@ -2047,11 +2045,12 @@ impl<'a> State<'a> { try!(self.print_type(&*qpath.self_type)); try!(space(&mut self.s)); try!(self.word_space("as")); - try!(self.print_path(&qpath.trait_path, false)); + try!(self.print_path(&qpath.path, false, 1)); try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); - try!(self.print_ident(qpath.item_path.identifier)); - self.print_path_parameters(&qpath.item_path.parameters, colons_before_params) + let item_segment = qpath.path.segments.last().unwrap(); + try!(self.print_ident(item_segment.identifier)); + self.print_path_parameters(&item_segment.parameters, colons_before_params) } fn print_path_parameters(&mut self, @@ -2156,7 +2155,7 @@ impl<'a> State<'a> { } } ast::PatEnum(ref path, ref args_) => { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); match *args_ { None => try!(word(&mut self.s, "(..)")), Some(ref args) => { @@ -2170,7 +2169,7 @@ impl<'a> State<'a> { } } ast::PatStruct(ref path, ref fields, etc) => { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); try!(self.nbsp()); try!(self.word_space("{")); try!(self.commasep_cmnt( @@ -2555,7 +2554,7 @@ impl<'a> State<'a> { } } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); try!(space(&mut self.s)); try!(self.word_space("=")); try!(self.print_type(&**ty)); @@ -2592,7 +2591,7 @@ impl<'a> State<'a> { pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> { match vp.node { ast::ViewPathSimple(ident, ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); // FIXME(#6993) can't compare identifiers directly here if path.segments.last().unwrap().identifier.name != @@ -2606,7 +2605,7 @@ impl<'a> State<'a> { } ast::ViewPathGlob(ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); word(&mut self.s, "::*") } @@ -2614,7 +2613,7 @@ impl<'a> State<'a> { if path.segments.is_empty() { try!(word(&mut self.s, "{")); } else { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); try!(word(&mut self.s, "::{")); } try!(self.commasep(Inconsistent, &idents[..], |s, w| { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4e90adea90c62..55372585062d8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -125,9 +125,6 @@ pub trait Visitor<'v> : Sized { fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) } - fn visit_qpath(&mut self, qpath: &'v QPath, _id: ast::NodeId) { - walk_qpath(self, qpath) - } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) } @@ -403,7 +400,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_path(path, typ.id); } TyQPath(ref qpath) => { - visitor.visit_qpath(&**qpath, typ.id); + visitor.visit_ty(&*qpath.self_type); + visitor.visit_path(&qpath.path, typ.id); } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); @@ -436,12 +434,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } } -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath) { - visitor.visit_ty(&*qpath.self_type); - walk_path(visitor, &qpath.trait_path); - visitor.visit_path_segment(qpath.trait_path.span, &qpath.item_path); -} - pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { @@ -871,7 +863,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_path(path, expression.id) } ExprQPath(ref qpath) => { - visitor.visit_qpath(&**qpath, expression.id) + visitor.visit_ty(&*qpath.self_type); + visitor.visit_path(&qpath.path, expression.id); } ExprBreak(_) | ExprAgain(_) => {} ExprRet(ref optional_expression) => { From 5809f8ae746dbde96e0924b8e422b9e0d092375b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 5 Feb 2015 09:19:07 +0200 Subject: [PATCH 09/25] rustc_resolve: use the visitor model more, remove redundant repeated lookups. --- src/librustc/middle/astconv_util.rs | 63 +- src/librustc/middle/astencode.rs | 3 - src/librustc/middle/def.rs | 2 - src/librustc/middle/mem_categorization.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 47 +- src/librustc_resolve/lib.rs | 844 ++++++------------ src/librustc_trans/save/mod.rs | 1 - src/librustc_trans/trans/callee.rs | 5 +- src/librustc_typeck/check/mod.rs | 1 - src/librustdoc/clean/mod.rs | 3 - src/librustdoc/html/format.rs | 3 - src/libsyntax/ext/deriving/cmp/eq.rs | 2 +- src/libsyntax/ext/deriving/cmp/ord.rs | 2 +- src/libsyntax/ext/deriving/mod.rs | 6 + src/libsyntax/ext/deriving/primitive.rs | 4 +- .../compile-fail/extern-with-type-bounds.rs | 2 +- src/test/compile-fail/glob-resolve1.rs | 3 - .../inner-static-type-parameter.rs | 3 +- src/test/compile-fail/issue-3521-2.rs | 4 +- src/test/compile-fail/issue-3521.rs | 4 +- src/test/compile-fail/issue-3668-2.rs | 4 +- src/test/compile-fail/issue-3668.rs | 1 + .../no-implicit-prelude-nested.rs | 30 +- src/test/compile-fail/no-implicit-prelude.rs | 10 +- .../compile-fail/resolve-unknown-trait.rs | 6 +- ...unboxed-closure-sugar-nonexistent-trait.rs | 2 +- 26 files changed, 335 insertions(+), 722 deletions(-) diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index d468084483898..d45c18efee7b4 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -35,55 +35,36 @@ pub fn check_path_args(tcx: &ty::ctxt, if (flags & NO_REGIONS) != 0 { if path.segments.iter().any(|s| s.parameters.has_lifetimes()) { span_err!(tcx.sess, path.span, E0110, - "region parameters are not allowed on this type"); + "lifetime parameters are not allowed on this type"); } } } pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { - match ast_ty.node { - ast::TyPath(ref path) => { - let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { - None => { - tcx.sess.span_bug(ast_ty.span, - &format!("unbound path {}", - path.repr(tcx))) - } - Some(&d) => d - }; - match a_def { - def::DefPrimTy(nty) => { - match nty { - ast::TyBool => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(tcx.types.bool) - } - ast::TyChar => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(tcx.types.char) - } - ast::TyInt(it) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_int(tcx, it)) - } - ast::TyUint(uit) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_uint(tcx, uit)) - } - ast::TyFloat(ft) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_float(tcx, ft)) - } - ast::TyStr => { - Some(ty::mk_str(tcx)) - } - } - } - _ => None + if let ast::TyPath(ref path) = ast_ty.node { + let def = match tcx.def_map.borrow().get(&ast_ty.id) { + None => { + tcx.sess.span_bug(ast_ty.span, + &format!("unbound path {}", path.repr(tcx))) } + Some(&d) => d + }; + if let def::DefPrimTy(nty) = def { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + Some(match nty { + ast::TyBool => tcx.types.bool, + ast::TyChar => tcx.types.char, + ast::TyInt(it) => ty::mk_mach_int(tcx, it), + ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit), + ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft), + ast::TyStr => ty::mk_str(tcx) + }) + } else { + None } - _ => None + } else { + None } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index c4b874f793019..37586b08b3654 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -456,9 +456,6 @@ impl tr for def::Def { } def::DefStruct(did) => def::DefStruct(did.tr(dcx)), def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)), - def::DefTyParamBinder(nid) => { - def::DefTyParamBinder(dcx.tr_id(nid)) - } def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid)) } } diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index a341b55333f41..191672775f253 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -54,7 +54,6 @@ pub enum Def { /// - If it's an ExprPath referring to some tuple struct, then DefMap maps /// it to a def whose id is the StructDef.ctor_id. DefStruct(ast::DefId), - DefTyParamBinder(ast::NodeId), /* struct, impl or trait with ty params */ DefRegion(ast::NodeId), DefLabel(ast::NodeId), DefMethod(ast::DefId /* method */, Option /* trait */, MethodProvenance), @@ -145,7 +144,6 @@ impl Def { DefSelfTy(id) | DefUpvar(id, _) | DefRegion(id) | - DefTyParamBinder(id) | DefLabel(id) => { local_def(id) } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index d1fba421bbe58..59e090a603703 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -580,7 +580,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) | - def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) | + def::DefTyParam(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> { Ok(Rc::new(cmt_ { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 7c6e537f0be23..cc47090198ba2 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -23,10 +23,8 @@ use Namespace::{TypeNS, ValueNS}; use NameBindings; use ParentLink::{self, ModuleParentLink, BlockParentLink}; use Resolver; -use RibKind::*; use Shadowable; use TypeNsDef; -use TypeParameters::HasTypeParameters; use self::DuplicateCheckingMode::*; use self::NamespaceError::*; @@ -34,7 +32,6 @@ use self::NamespaceError::*; use rustc::metadata::csearch; use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; use rustc::middle::def::*; -use rustc::middle::subst::FnSpace; use syntax::ast::{Block, Crate}; use syntax::ast::{DeclItem, DefId}; @@ -773,12 +770,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(&mut self, - foreign_item: &ForeignItem, - parent: &Rc, - f: F) where - F: FnOnce(&mut Resolver), - { + fn build_reduced_graph_for_foreign_item(&mut self, + foreign_item: &ForeignItem, + parent: &Rc) { let name = foreign_item.ident.name; let is_public = foreign_item.vis == ast::Public; let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; @@ -786,25 +780,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.add_child(name, parent, ForbidDuplicateValues, foreign_item.span); - match foreign_item.node { - ForeignItemFn(_, ref generics) => { - let def = DefFn(local_def(foreign_item.id), false); - name_bindings.define_value(def, foreign_item.span, modifiers); - - self.with_type_parameter_rib( - HasTypeParameters(generics, - FnSpace, - foreign_item.id, - NormalRibKind), - f); + let def = match foreign_item.node { + ForeignItemFn(..) => { + DefFn(local_def(foreign_item.id), false) } ForeignItemStatic(_, m) => { - let def = DefStatic(local_def(foreign_item.id), m); - name_bindings.define_value(def, foreign_item.span, modifiers); - - f(self.resolver) + DefStatic(local_def(foreign_item.id), m) } - } + }; + name_bindings.define_value(def, foreign_item.span, modifiers); } fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc) -> Rc { @@ -980,7 +964,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } DefLocal(..) | DefPrimTy(..) | DefTyParam(..) | DefUse(..) | DefUpvar(..) | DefRegion(..) | - DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => { + DefLabel(..) | DefSelfTy(..) => { panic!("didn't expect `{:?}`", def); } } @@ -1241,16 +1225,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { - let parent = &self.parent; - self.builder.build_reduced_graph_for_foreign_item(foreign_item, - parent, - |r| { - let mut v = BuildReducedGraphVisitor { - builder: GraphBuilder { resolver: r }, - parent: parent.clone() - }; - visit::walk_foreign_item(&mut v, foreign_item); - }) + self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent); } fn visit_block(&mut self, block: &Block) { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6584e3cc19d4c..b211681992ba9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -41,14 +41,12 @@ use self::ResolveResult::*; use self::FallbackSuggestion::*; use self::TypeParameters::*; use self::RibKind::*; -use self::MethodSort::*; use self::UseLexicalScopeFlag::*; use self::ModulePrefixResult::*; use self::NameSearchType::*; use self::BareIdentifierPatternResolution::*; use self::ParentLink::*; use self::ModuleKind::*; -use self::TraitReferenceType::*; use self::FallbackChecks::*; use rustc::session::Session; @@ -66,21 +64,18 @@ use rustc::util::lev_distance::lev_distance; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; -use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall}; +use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; -use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId}; +use syntax::ast::{Local, MethodImplItem, Name, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; -use syntax::ast::{PatRange, PatStruct, Path}; -use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit}; -use syntax::ast::{RegionTyParamBound, StructField}; -use syntax::ast::{TraitRef, TraitTyParamBound}; -use syntax::ast::{Ty, TyBool, TyChar, TyF32}; -use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum}; -use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath}; +use syntax::ast::{PatRange, PatStruct, Path, PrimTy}; +use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32}; +use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt}; +use syntax::ast::{TyPath, TyPtr, TyQPath}; use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint}; use syntax::ast::{TypeImplItem}; use syntax::ast; @@ -89,8 +84,7 @@ use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat}; use syntax::attr::AttrMetaMethods; use syntax::ext::mtwt; use syntax::parse::token::{self, special_names, special_idents}; -use syntax::codemap::{Span, Pos}; -use syntax::owned_slice::OwnedSlice; +use syntax::codemap::{self, Span, Pos}; use syntax::visit::{self, Visitor}; use std::collections::{HashMap, HashSet}; @@ -188,6 +182,72 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_ty(&mut self, ty: &Ty) { self.resolve_type(ty); } + fn visit_generics(&mut self, generics: &Generics) { + self.resolve_generics(generics); + } + fn visit_poly_trait_ref(&mut self, + tref: &ast::PolyTraitRef, + m: &ast::TraitBoundModifier) { + match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) { + Ok(def) => self.record_def(tref.trait_ref.ref_id, def), + Err(_) => { /* error already reported */ } + } + visit::walk_poly_trait_ref(self, tref, m); + } + fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) { + if let Some(ref dis_expr) = variant.node.disr_expr { + // resolve the discriminator expr as a constant + self.with_constant_rib(|this| { + this.visit_expr(&**dis_expr); + }); + } + + // `visit::walk_variant` without the discriminant expression. + match variant.node.kind { + ast::TupleVariantKind(ref variant_arguments) => { + for variant_argument in variant_arguments.iter() { + self.visit_ty(&*variant_argument.ty); + } + } + ast::StructVariantKind(ref struct_definition) => { + self.visit_struct_def(&**struct_definition, + variant.node.name, + generics, + variant.node.id); + } + } + } + fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) { + let type_parameters = match foreign_item.node { + ForeignItemFn(_, ref generics) => { + HasTypeParameters(generics, FnSpace, ItemRibKind) + } + ForeignItemStatic(..) => NoTypeParameters + }; + self.with_type_parameter_rib(type_parameters, |this| { + visit::walk_foreign_item(this, foreign_item); + }); + } + fn visit_fn(&mut self, + function_kind: visit::FnKind<'v>, + declaration: &'v FnDecl, + block: &'v Block, + _: Span, + node_id: NodeId) { + let rib_kind = match function_kind { + visit::FkItemFn(_, generics, _, _) => { + self.visit_generics(generics); + ItemRibKind + } + visit::FkMethod(_, generics, method) => { + self.visit_generics(generics); + self.visit_explicit_self(method.pe_explicit_self()); + MethodRibKind + } + visit::FkFnBlock(..) => ClosureRibKind(node_id) + }; + self.resolve_function(rib_kind, declaration, block); + } } /// Contains data for specific types of import directives. @@ -231,9 +291,6 @@ enum TypeParameters<'a> { // were declared on (type, fn, etc) ParamSpace, - // ID of the enclosing item. - NodeId, - // The kind of the rib used for type parameters. RibKind) } @@ -253,8 +310,7 @@ enum RibKind { // methods. Allow references to ty params that impl or trait // binds. Disallow any other upvars (including other ty params that are // upvars). - // parent; method itself - MethodRibKind(NodeId, MethodSort), + MethodRibKind, // We passed through an item scope. Disallow upvars. ItemRibKind, @@ -263,13 +319,6 @@ enum RibKind { ConstantItemRibKind } -// Methods can be required or provided. RequiredMethod methods only occur in traits. -#[derive(Copy, Debug)] -enum MethodSort { - RequiredMethod, - ProvidedMethod(NodeId) -} - #[derive(Copy)] enum UseLexicalScopeFlag { DontUseLexicalScope, @@ -586,16 +635,6 @@ struct NameBindings { value_def: RefCell>, //< Meaning in value namespace. } -/// Ways in which a trait can be referenced -#[derive(Copy)] -enum TraitReferenceType { - TraitImplementation, // impl SomeTrait for T { ... } - TraitDerivation, // trait T : SomeTrait { ... } - TraitBoundingTypeParameter, // fn f() { ... } - TraitObject, // Box SomeTrait> - TraitQPath, // :: -} - impl NameBindings { fn new() -> NameBindings { NameBindings { @@ -2600,14 +2639,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { def_like: DefLike, span: Span) -> Option { - match def_like { - DlDef(d @ DefUpvar(..)) => { + let mut def = match def_like { + DlDef(def) => def, + _ => return Some(def_like) + }; + match def { + DefUpvar(..) => { self.session.span_bug(span, - &format!("unexpected {:?} in bindings", d)) + &format!("unexpected {:?} in bindings", def)) } - DlDef(d @ DefLocal(_)) => { - let node_id = d.def_id().node; - let mut def = d; + DefLocal(node_id) => { for rib in ribs { match rib.kind { NormalRibKind => { @@ -2631,39 +2672,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }.push(Freevar { def: prev_def, span: span }); seen.insert(node_id); } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - DefTyParam(_, _, did, _) if { - self.def_map.borrow().get(&did.node).cloned() - == Some(DefTyParamBinder(item_id)) - } => {} // ok - DefSelfTy(did) if did == item_id => {} // ok - _ => { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. - - self.resolve_error( - span, - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - - return None; - } - } - } - ItemRibKind => { + ItemRibKind | MethodRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. - self.resolve_error( - span, + self.resolve_error(span, "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - + use the || { ... } closure form instead"); return None; } ConstantItemRibKind => { @@ -2671,42 +2687,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(span, "attempt to use a non-constant \ value in a constant"); - + return None; } } } - Some(DlDef(def)) } - DlDef(def @ DefTyParam(..)) | - DlDef(def @ DefSelfTy(..)) => { + DefTyParam(..) | DefSelfTy(_) => { for rib in ribs { match rib.kind { - NormalRibKind | ClosureRibKind(..) => { + NormalRibKind | MethodRibKind | ClosureRibKind(..) => { // Nothing to do. Continue. } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - DefTyParam(_, _, did, _) if { - self.def_map.borrow().get(&did.node).cloned() - == Some(DefTyParamBinder(item_id)) - } => {} // ok - DefSelfTy(did) if did == item_id => {} // ok - - _ => { - // This was an attempt to use a type parameter outside - // its scope. - - self.resolve_error(span, - "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); - - return None; - } - } - } ItemRibKind => { // This was an attempt to use a type parameter outside // its scope. @@ -2715,7 +2706,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "can't use type parameters from \ outer function; try using a local \ type parameter instead"); - return None; } ConstantItemRibKind => { @@ -2723,14 +2713,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(span, "cannot use an outer type \ parameter in this context"); - + return None; } } } - Some(DlDef(def)) } - _ => Some(def_like) + _ => {} } + Some(DlDef(def)) } /// Searches the current set of local scopes and @@ -2743,13 +2733,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME #4950: Try caching? for (i, rib) in ribs.iter().enumerate().rev() { - match rib.bindings.get(&name).cloned() { - Some(def_like) => { - return self.upvarify(&ribs[i + 1..], def_like, span); - } - None => { - // Continue. - } + if let Some(def_like) = rib.bindings.get(&name).cloned() { + return self.upvarify(&ribs[i + 1..], def_like, span); } } @@ -2797,47 +2782,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { token::get_name(name)); match item.node { - - // enum item: resolve all the variants' discrs, - // then resolve the ty params - ItemEnum(ref enum_def, ref generics) => { + ItemEnum(_, ref generics) | + ItemTy(_, ref generics) | + ItemStruct(_, ref generics) => { self.check_if_primitive_type_name(name, item.span); - for variant in &(*enum_def).variants { - if let Some(ref dis_expr) = variant.node.disr_expr { - // resolve the discriminator expr - // as a constant - self.with_constant_rib(|this| { - this.resolve_expr(&**dis_expr); - }); - } - } - - // n.b. the discr expr gets visited twice. - // but maybe it's okay since the first time will signal an - // error if there is one? -- tjc self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - item.id, ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - visit::walk_item(this, item); - }); + |this| visit::walk_item(this, item)); } - - ItemTy(_, ref generics) => { - self.check_if_primitive_type_name(name, item.span); - + ItemFn(_, _, _, ref generics, _) => { self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - item.id, + FnSpace, ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - visit::walk_item(this, item); - }); + |this| visit::walk_item(this, item)); } ItemDefaultImpl(_, ref trait_ref) => { @@ -2848,8 +2807,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ref implemented_traits, ref self_type, ref impl_items) => { - self.resolve_implementation(item.id, - generics, + self.resolve_implementation(generics, implemented_traits, &**self_type, &impl_items[..]); @@ -2869,13 +2827,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - item.id, NormalRibKind), |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - - this.resolve_type_parameter_bounds(bounds, TraitDerivation); + this.visit_generics(generics); + visit::walk_ty_param_bounds_helper(this, bounds); for trait_item in &(*trait_items) { // Create a new rib for the trait_item-specific type @@ -2883,101 +2838,34 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // // FIXME #4951: Do we need a node ID here? - match *trait_item { - ast::RequiredMethod(ref ty_m) => { - this.with_type_parameter_rib - (HasTypeParameters(&ty_m.generics, - FnSpace, - item.id, - MethodRibKind(item.id, RequiredMethod)), - |this| { - - // Resolve the method-specific type - // parameters. - this.resolve_type_parameters( - &ty_m.generics.ty_params); - this.resolve_where_clause(&ty_m.generics - .where_clause); - - for argument in &ty_m.decl.inputs { - this.resolve_type(&*argument.ty); - } - - if let SelfExplicit(ref typ, _) = ty_m.explicit_self.node { - this.resolve_type(&**typ) - } - - if let ast::Return(ref ret_ty) = ty_m.decl.output { - this.resolve_type(&**ret_ty); - } - }); - } - ast::ProvidedMethod(ref m) => { - this.resolve_method(MethodRibKind(item.id, - ProvidedMethod(m.id)), - &**m) - } - ast::TypeTraitItem(ref data) => { - this.resolve_type_parameter(&data.ty_param); - visit::walk_trait_item(this, trait_item); - } - } + let type_parameters = match *trait_item { + ast::RequiredMethod(ref ty_m) => { + HasTypeParameters(&ty_m.generics, + FnSpace, + MethodRibKind) + } + ast::ProvidedMethod(ref m) => { + HasTypeParameters(m.pe_generics(), + FnSpace, + MethodRibKind) + } + ast::TypeTraitItem(_) => NoTypeParameters, + }; + this.with_type_parameter_rib(type_parameters, |this| { + visit::walk_trait_item(this, trait_item) + }); } }); self.type_ribs.pop(); } - ItemStruct(ref struct_def, ref generics) => { - self.check_if_primitive_type_name(name, item.span); - - self.resolve_struct(item.id, - generics, - &struct_def.fields); - } - - ItemMod(ref module_) => { + ItemMod(_) | ItemForeignMod(_) => { self.with_scope(Some(name), |this| { - this.resolve_module(module_, item.span, name, - item.id); - }); - } - - ItemForeignMod(ref foreign_module) => { - self.with_scope(Some(name), |this| { - for foreign_item in &foreign_module.items { - match foreign_item.node { - ForeignItemFn(_, ref generics) => { - this.with_type_parameter_rib( - HasTypeParameters( - generics, FnSpace, foreign_item.id, - ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - visit::walk_foreign_item(this, &**foreign_item) - }); - } - ForeignItemStatic(..) => { - visit::walk_foreign_item(this, - &**foreign_item); - } - } - } + visit::walk_item(this, item); }); } - ItemFn(ref fn_decl, _, _, ref generics, ref block) => { - self.resolve_function(ItemRibKind, - Some(&**fn_decl), - HasTypeParameters - (generics, - FnSpace, - item.id, - ItemRibKind), - &**block); - } - ItemConst(..) | ItemStatic(..) => { self.with_constant_rib(|this| { visit::walk_item(this, item); @@ -3006,35 +2894,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { F: FnOnce(&mut Resolver), { match type_parameters { - HasTypeParameters(generics, space, node_id, rib_kind) => { + HasTypeParameters(generics, space, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = HashSet::new(); for (index, type_parameter) in generics.ty_params.iter().enumerate() { let name = type_parameter.ident.name; - debug!("with_type_parameter_rib: {} {}", node_id, - type_parameter.id); + debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { self.resolve_error(type_parameter.span, &format!("the name `{}` is already \ - used for a type \ - parameter in this type \ - parameter list", - token::get_name( - name))) + used for a type \ + parameter in this type \ + parameter list", + token::get_name(name))) } seen_bindings.insert(name); - let def_like = DlDef(DefTyParam(space, - index as u32, - local_def(type_parameter.id), - name)); - // Associate this type parameter with - // the item that bound it - self.record_def(type_parameter.id, - (DefTyParamBinder(node_id), LastMod(AllPublic))); // plain insert (no renaming) - function_type_rib.bindings.insert(name, def_like); + function_type_rib.bindings.insert(name, + DlDef(DefTyParam(space, + index as u32, + local_def(type_parameter.id), + name))); } self.type_ribs.push(function_type_rib); } @@ -3072,154 +2954,74 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_function(&mut self, rib_kind: RibKind, - optional_declaration: Option<&FnDecl>, - type_parameters: TypeParameters, + declaration: &FnDecl, block: &Block) { // Create a value rib for the function. - let function_value_rib = Rib::new(rib_kind); - self.value_ribs.push(function_value_rib); + self.value_ribs.push(Rib::new(rib_kind)); // Create a label rib for the function. - let function_label_rib = Rib::new(rib_kind); - self.label_ribs.push(function_label_rib); - - // If this function has type parameters, add them now. - self.with_type_parameter_rib(type_parameters, |this| { - // Resolve the type parameters. - match type_parameters { - NoTypeParameters => { - // Continue. - } - HasTypeParameters(ref generics, _, _, _) => { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - } - } + self.label_ribs.push(Rib::new(rib_kind)); - // Add each argument to the rib. - match optional_declaration { - None => { - // Nothing to do. - } - Some(declaration) => { - let mut bindings_list = HashMap::new(); - for argument in &declaration.inputs { - this.resolve_pattern(&*argument.pat, - ArgumentIrrefutableMode, - &mut bindings_list); - - this.resolve_type(&*argument.ty); + // Add each argument to the rib. + let mut bindings_list = HashMap::new(); + for argument in &declaration.inputs { + self.resolve_pattern(&*argument.pat, + ArgumentIrrefutableMode, + &mut bindings_list); - debug!("(resolving function) recorded argument"); - } + self.visit_ty(&*argument.ty); - if let ast::Return(ref ret_ty) = declaration.output { - this.resolve_type(&**ret_ty); - } - } - } + debug!("(resolving function) recorded argument"); + } + visit::walk_fn_ret_ty(self, &declaration.output); - // Resolve the function body. - this.resolve_block(&*block); + // Resolve the function body. + self.visit_block(&*block); - debug!("(resolving function) leaving function"); - }); + debug!("(resolving function) leaving function"); self.label_ribs.pop(); self.value_ribs.pop(); } - fn resolve_type_parameters(&mut self, - type_parameters: &OwnedSlice) { - for type_parameter in &**type_parameters { - self.resolve_type_parameter(type_parameter); - } - } - - fn resolve_type_parameter(&mut self, - type_parameter: &TyParam) { - self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); - for bound in &*type_parameter.bounds { - self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); - } - match type_parameter.default { - Some(ref ty) => self.resolve_type(&**ty), - None => {} - } - } - - fn resolve_type_parameter_bounds(&mut self, - type_parameter_bounds: &OwnedSlice, - reference_type: TraitReferenceType) { - for type_parameter_bound in &**type_parameter_bounds { - self.resolve_type_parameter_bound(type_parameter_bound, reference_type); - } - } - - fn resolve_type_parameter_bound(&mut self, - type_parameter_bound: &TyParamBound, - reference_type: TraitReferenceType) { - match *type_parameter_bound { - TraitTyParamBound(ref tref, _) => { - self.resolve_trait_reference(tref.trait_ref.ref_id, - &tref.trait_ref.path, 0, - reference_type) - } - RegionTyParamBound(..) => {} - } - } - fn resolve_trait_reference(&mut self, id: NodeId, trait_path: &Path, - path_depth: usize, - reference_type: TraitReferenceType) { + path_depth: usize) + -> Result<(Def, LastPrivate), ()> { match self.resolve_path(id, trait_path, path_depth, TypeNS, true) { - None => { - let path_str = self.path_names_to_string(trait_path, path_depth); - let usage_str = match reference_type { - TraitBoundingTypeParameter => "bound type parameter with", - TraitImplementation => "implement", - TraitDerivation => "derive", - TraitObject => "reference", - TraitQPath => "extract an associated item from", - }; - - let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str); - self.resolve_error(trait_path.span, &msg[..]); - } - Some(def) => { - match def { - (DefTrait(_), _) => { - debug!("(resolving trait) found trait def: {:?}", def); - self.record_def(id, def); - } - (def, _) => { - self.resolve_error(trait_path.span, - &format!("`{}` is not a trait", - self.path_names_to_string(trait_path, path_depth))); - - // If it's a typedef, give a note - if let DefTy(..) = def { - self.session.span_note(trait_path.span, - &format!("`type` aliases cannot be used for traits")); - } - } + Some(def @ (DefTrait(_), _)) => { + debug!("(resolving trait) found trait def: {:?}", def); + Ok(def) + } + Some((def, _)) => { + self.resolve_error(trait_path.span, + &format!("`{}` is not a trait", + self.path_names_to_string(trait_path, path_depth))); + + // If it's a typedef, give a note + if let DefTy(..) = def { + self.session.span_note(trait_path.span, + "`type` aliases cannot be used for traits"); } + Err(()) + } + None => { + let msg = format!("use of undeclared trait name `{}`", + self.path_names_to_string(trait_path, path_depth)); + self.resolve_error(trait_path.span, &msg[]); + Err(()) } } } - fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) { - for predicate in &where_clause.predicates { + fn resolve_generics(&mut self, generics: &Generics) { + for type_parameter in &generics.ty_params { + self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); + } + for predicate in &generics.where_clause.predicates { match predicate { - &ast::WherePredicate::BoundPredicate(ref bound_pred) => { - self.resolve_type(&*bound_pred.bounded_ty); - - for bound in &*bound_pred.bounds { - self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); - } - } + &ast::WherePredicate::BoundPredicate(_) | &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) { @@ -3231,53 +3033,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "undeclared associated type"); } } - - self.resolve_type(&*eq_pred.ty); } } } - } - - fn resolve_struct(&mut self, - id: NodeId, - generics: &Generics, - fields: &[StructField]) { - // If applicable, create a rib for the type parameters. - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - id, - ItemRibKind), - |this| { - // Resolve the type parameters. - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - - // Resolve fields. - for field in fields { - this.resolve_type(&*field.node.ty); - } - }); - } - - // Does this really need to take a RibKind or is it always going - // to be NormalRibKind? - fn resolve_method(&mut self, - rib_kind: RibKind, - method: &ast::Method) { - let method_generics = method.pe_generics(); - let type_parameters = HasTypeParameters(method_generics, - FnSpace, - method.id, - rib_kind); - - if let SelfExplicit(ref typ, _) = method.pe_explicit_self().node { - self.resolve_type(&**typ); - } - - self.resolve_function(rib_kind, - Some(method.pe_fn_decl()), - type_parameters, - method.pe_body()); + visit::walk_generics(self, generics); } fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T where @@ -3295,22 +3054,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { f: F) -> T where F: FnOnce(&mut Resolver) -> T, { - let new_val = match *opt_trait_ref { - Some(ref trait_ref) => { - self.resolve_trait_reference(trait_ref.ref_id, - &trait_ref.path, 0, - TraitImplementation); - - match self.def_map.borrow().get(&trait_ref.ref_id) { - Some(def) => { - let did = def.def_id(); - Some((did, trait_ref.clone())) - } - None => None + let mut new_val = None; + if let Some(ref trait_ref) = *opt_trait_ref { + match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) { + Ok(def) => { + self.record_def(trait_ref.ref_id, def); + new_val = Some((def.0.def_id(), trait_ref.clone())); } + Err(_) => { /* error was already reported */ } } - None => None - }; + visit::walk_trait_ref(self, trait_ref); + } let original_trait_ref = replace(&mut self.current_trait_ref, new_val); let result = f(self); self.current_trait_ref = original_trait_ref; @@ -3318,7 +3072,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn resolve_implementation(&mut self, - id: NodeId, generics: &Generics, opt_trait_reference: &Option, self_type: &Ty, @@ -3326,17 +3079,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If applicable, create a rib for the type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - id, - NormalRibKind), + ItemRibKind), |this| { // Resolve the type parameters. - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); + this.visit_generics(generics); // Resolve the trait reference, if necessary. this.with_optional_trait_ref(opt_trait_reference, |this| { // Resolve the self type. - this.resolve_type(self_type); + this.visit_ty(self_type); this.with_current_self_type(self_type, |this| { for impl_item in impl_items { @@ -3349,9 +3100,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // We also need a new scope for the method- // specific type parameters. - this.resolve_method( - MethodRibKind(id, ProvidedMethod(method.id)), - &**method); + let type_parameters = + HasTypeParameters(method.pe_generics(), + FnSpace, + MethodRibKind); + this.with_type_parameter_rib(type_parameters, |this| { + visit::walk_method_helper(this, &**method); + }); } TypeImplItem(ref typedef) => { // If this is a trait impl, ensure the method @@ -3359,7 +3114,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.check_trait_item(typedef.ident.name, typedef.span); - this.resolve_type(&*typedef.typ); + this.visit_ty(&*typedef.typ); } } } @@ -3405,34 +3160,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_module(&mut self, module: &Mod, _span: Span, - _name: Name, id: NodeId) { - // Write the implementations in scope into the module metadata. - debug!("(resolving module) resolving module ID {}", id); - visit::walk_mod(self, module); - } - fn resolve_local(&mut self, local: &Local) { // Resolve the type. - if let Some(ref ty) = local.ty { - self.resolve_type(&**ty); - } + visit::walk_ty_opt(self, &local.ty); - // Resolve the initializer, if necessary. - match local.init { - None => { - // Nothing to do. - } - Some(ref initializer) => { - self.resolve_expr(&**initializer); - } - } + // Resolve the initializer. + visit::walk_expr_opt(self, &local.init); // Resolve the pattern. - let mut bindings_list = HashMap::new(); self.resolve_pattern(&*local.pat, LocalIrrefutableMode, - &mut bindings_list); + &mut HashMap::new()); } // build a map from pattern identifiers to binding-info's. @@ -3510,7 +3248,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.check_consistent_bindings(arm); visit::walk_expr_opt(self, &arm.guard); - self.resolve_expr(&*arm.body); + self.visit_expr(&*arm.body); self.value_ribs.pop(); } @@ -3566,49 +3304,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // on whether the path has multiple elements in it or not. TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => { - if let TyQPath(ref qpath) = ty.node { - self.resolve_type(&*qpath.self_type); - - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(ty.id, path, 1, TraitQPath); - self.def_map.borrow_mut().remove(&ty.id); + if let TyQPath(_) = ty.node { + // Make sure the trait is valid. + self.resolve_trait_reference(ty.id, path, 1); } // This is a path in the type namespace. Walk through scopes // looking for it. - let mut result_def = None; - - // First, check to see whether the name is a primitive type. - if path.segments.len() == 1 { - let id = path.segments.last().unwrap().identifier; - - match self.primitive_type_table - .primitive_types - .get(&id.name) { - - Some(&primitive_type) => { - result_def = - Some((DefPrimTy(primitive_type), LastMod(AllPublic))); - - if path.segments[0].parameters.has_lifetimes() { - span_err!(self.session, path.span, E0157, - "lifetime parameters are not allowed on this type"); - } else if !path.segments[0].parameters.is_empty() { - span_err!(self.session, path.span, E0153, - "type parameters are not allowed on this type"); - } - } - None => { - // Continue. - } - } - } - - if let None = result_def { - result_def = self.resolve_path(ty.id, path, 0, TypeNS, true); - } - - match result_def { + match self.resolve_path(ty.id, path, 0, TypeNS, true) { Some(def) => { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ @@ -3628,21 +3331,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } - - TyObjectSum(ref ty, ref bound_vec) => { - self.resolve_type(&**ty); - self.resolve_type_parameter_bounds(bound_vec, TraitBoundingTypeParameter); - } - - TyPolyTraitRef(ref bounds) => { - self.resolve_type_parameter_bounds(bounds, TraitObject); - visit::walk_ty(self, ty); - } - _ => { - // Just resolve embedded types. - visit::walk_ty(self, ty); - } + _ => {} } + // Resolve embedded types. + visit::walk_ty(self, ty); } fn resolve_pattern(&mut self, @@ -3669,7 +3361,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let renamed = mtwt::resolve(ident); match self.resolve_bare_identifier_pattern(ident.name, pattern.span) { - FoundStructOrEnumVariant(ref def, lp) + FoundStructOrEnumVariant(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ struct or enum variant", @@ -3679,7 +3371,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "an enum variant"); - self.record_def(pattern.id, (def.clone(), lp)); + self.record_def(pattern.id, (def, lp)); } FoundStructOrEnumVariant(..) => { self.resolve_error( @@ -3689,7 +3381,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { scope", token::get_name(renamed))); } - FoundConst(ref def, lp) if mode == RefutableMode => { + FoundConst(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ constant", token::get_name(renamed)); @@ -3698,7 +3390,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "a constant"); - self.record_def(pattern.id, (def.clone(), lp)); + self.record_def(pattern.id, (def, lp)); } FoundConst(..) => { self.resolve_error(pattern.span, @@ -3782,22 +3474,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { token::get_ident(path.segments.last().unwrap().identifier))); } } - - // Check the types in the path pattern. - for ty in path.segments - .iter() - .flat_map(|s| s.parameters.types().into_iter()) { - self.resolve_type(&**ty); - } - } - - PatLit(ref expr) => { - self.resolve_expr(&**expr); - } - - PatRange(ref first_expr, ref last_expr) => { - self.resolve_expr(&**first_expr); - self.resolve_expr(&**last_expr); + visit::walk_path(self, path); } PatStruct(ref path, _, _) => { @@ -3813,6 +3490,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(path.span, &msg[..]); } } + visit::walk_path(self, path); + } + + PatLit(_) | PatRange(..) => { + visit::walk_pat(self, pattern); } _ => { @@ -3895,14 +3577,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let span = path.span; let segments = &path.segments[..path.segments.len()-path_depth]; - // First, resolve the types and associated type bindings. - for ty in segments.iter().flat_map(|s| s.parameters.types().into_iter()) { - self.resolve_type(&**ty); - } - for binding in segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { - self.resolve_type(&*binding.ty); - } - // A special case for sugared associated type paths `T::A` where `T` is // a type parameter and `A` is an associated type on some bound of `T`. if namespace == TypeNS && segments.len() == 2 { @@ -3957,7 +3631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return def; } - return unqualified_def; + unqualified_def } // resolve a single identifier (used as a varref) @@ -3967,20 +3641,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { check_ribs: bool, span: Span) -> Option<(Def, LastPrivate)> { + // First, check to see whether the name is a primitive type. + if namespace == TypeNS { + if let Some(&prim_ty) = self.primitive_type_table + .primitive_types + .get(&identifier.name) { + return Some((DefPrimTy(prim_ty), LastMod(AllPublic))); + } + } + if check_ribs { - match self.resolve_identifier_in_local_ribs(identifier, - namespace, - span) { - Some(def) => { - return Some((def, LastMod(AllPublic))); - } - None => { - // Continue. - } + if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, + namespace, + span) { + return Some((def, LastMod(AllPublic))); } } - return self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace); + self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace) } // FIXME #4952: Merge me with resolve_name_in_module? @@ -4197,10 +3875,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { local: {:?}", token::get_ident(ident), def); - return Some(def); + Some(def) } Some(DlField) | Some(DlImpl(_)) | None => { - return None; + None } } } @@ -4425,12 +4103,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // multiple elements in it or not. ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { - if let ExprQPath(ref qpath) = expr.node { - self.resolve_type(&*qpath.self_type); - - // Just make sure the trait is valid, don't record a def. - self.resolve_trait_reference(expr.id, path, 1, TraitQPath); - self.def_map.borrow_mut().remove(&expr.id); + if let ExprQPath(_) = expr.node { + // Make sure the trait is valid. + self.resolve_trait_reference(expr.id, path, 1); } // This is a local path in the value namespace. Walk through @@ -4482,13 +4157,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => { let mut method_scope = false; self.value_ribs.iter().rev().all(|rib| { - let res = match *rib { - Rib { bindings: _, kind: MethodRibKind(_, _) } => true, - Rib { bindings: _, kind: ItemRibKind } => false, + method_scope = match rib.kind { + MethodRibKind => true, + ItemRibKind | ConstantItemRibKind => false, _ => return true, // Keep advancing }; - - method_scope = res; false // Stop advancing }); @@ -4537,21 +4210,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { visit::walk_expr(self, expr); } - ExprClosure(_, ref fn_decl, ref block) => { - self.resolve_function(ClosureRibKind(expr.id), - Some(&**fn_decl), NoTypeParameters, - &**block); - } - ExprStruct(ref path, _, _) => { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that // is checked later during typeck. match self.resolve_path(expr.id, path, 0, TypeNS, false) { Some(definition) => self.record_def(expr.id, definition), - result => { - debug!("(resolving expression) didn't find struct \ - def: {:?}", result); + None => { + debug!("(resolving expression) didn't find struct def",); let msg = format!("`{}` does not name a structure", self.path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); @@ -4704,26 +4370,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { found_traits } - fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) { + fn record_def(&mut self, + node_id: NodeId, + (def, lp): (Def, LastPrivate)) { debug!("(recording def) recording {:?} for {}, last private {:?}", def, node_id, lp); assert!(match lp {LastImport{..} => false, _ => true}, "Import should only be used for `use` directives"); self.last_private.insert(node_id, lp); - match self.def_map.borrow_mut().entry(node_id) { - // Resolve appears to "resolve" the same ID multiple - // times, so here is a sanity check it at least comes to - // the same conclusion! - nmatsakis - Occupied(entry) => if def != *entry.get() { - self.session - .bug(&format!("node_id {} resolved first to {:?} and \ - then {:?}", - node_id, - *entry.get(), - def)); - }, - Vacant(entry) => { entry.insert(def); }, + if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) { + let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); + self.session.span_bug(span, &format!("path resolved multiple times \ + ({:?} before, {:?} now)", + prev_def, def)); } } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 6a20938da2e47..531700b9563be 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -250,7 +250,6 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefSelfTy(_) | def::DefRegion(_) | - def::DefTyParamBinder(_) | def::DefLabel(_) | def::DefStaticMethod(..) | def::DefTyParam(..) | diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 25568db814824..9dbcbc8b1a28e 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -209,9 +209,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) | def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) | - def::DefUse(..) | def::DefTyParamBinder(..) | - def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) | - def::DefSelfTy(..) | def::DefAssociatedPath(..) => { + def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) | + def::DefTyParam(..) | def::DefSelfTy(..) | def::DefAssociatedPath(..) => { bcx.tcx().sess.span_bug( ref_expr.span, &format!("cannot translate def {:?} \ diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5b3090be59372..9d303f492eb34 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4729,7 +4729,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefSelfTy(..) | def::DefStruct(..) | def::DefVariant(..) | - def::DefTyParamBinder(..) | def::DefTy(..) | def::DefAssociatedTy(..) | def::DefAssociatedPath(..) | diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2af8107622301..7a27159bc47a2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1344,8 +1344,6 @@ pub enum Type { typarams: Option>, did: ast::DefId, }, - // I have no idea how to usefully use this. - TyParamBinder(ast::NodeId), /// For parameterized types, so the consumer of the JSON don't go /// looking for types which don't exist anywhere. Generic(String), @@ -2416,7 +2414,6 @@ fn resolve_type(cx: &DocContext, ast::TyFloat(ast::TyF64) => return Primitive(F64), }, def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()), - def::DefTyParamBinder(i) => return TyParamBinder(i), _ => {} }; let did = register_def(&*cx, def); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 11d9ecac14dd0..03a2d708ee43a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -454,9 +454,6 @@ fn tybounds(w: &mut fmt::Formatter, impl fmt::Display for clean::Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - clean::TyParamBinder(id) => { - f.write_str(&cache().typarams[ast_util::local_def(id)]) - } clean::Generic(ref name) => { f.write_str(name) } diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 91212a8695896..80ef882745f87 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -70,7 +70,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path!(bool)), + ret_ty: Literal(path_local!(bool)), attributes: attrs, combine_substructure: combine_substructure(box |a, b, c| { $f(a, b, c) diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index b109850a6bd23..be4a33002aa1c 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -36,7 +36,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path!(bool)), + ret_ty: Literal(path_local!(bool)), attributes: attrs, combine_substructure: combine_substructure(box |cx, span, substr| { cs_op($op, $equal, cx, span, substr) diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index eee780f457c9f..973c8f5fa1e0b 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -30,6 +30,12 @@ macro_rules! path { ) } +macro_rules! path_local { + ($x:ident) => ( + ::ext::deriving::generic::ty::Path::new_local(stringify!($x)) + ) +} + macro_rules! pathvec_std { ($cx:expr, $first:ident :: $($rest:ident)::+) => ( if $cx.use_std { diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 22c87d978c9e5..3b96292323a95 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -38,7 +38,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, name: "from_i64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!(Literal(path!(i64))), + args: vec!(Literal(path_local!(i64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self_), @@ -53,7 +53,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, name: "from_u64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!(Literal(path!(u64))), + args: vec!(Literal(path_local!(u64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self_), diff --git a/src/test/compile-fail/extern-with-type-bounds.rs b/src/test/compile-fail/extern-with-type-bounds.rs index ade8b397e0003..21334e1d51375 100644 --- a/src/test/compile-fail/extern-with-type-bounds.rs +++ b/src/test/compile-fail/extern-with-type-bounds.rs @@ -24,7 +24,7 @@ extern "rust-intrinsic" { // Unresolved bounds should still error. fn align_of() -> usize; - //~^ ERROR attempt to bound type parameter with a nonexistent trait `NoSuchTrait` + //~^ ERROR use of undeclared trait name `NoSuchTrait` } fn main() {} diff --git a/src/test/compile-fail/glob-resolve1.rs b/src/test/compile-fail/glob-resolve1.rs index fce8a07d7270d..181503db81846 100644 --- a/src/test/compile-fail/glob-resolve1.rs +++ b/src/test/compile-fail/glob-resolve1.rs @@ -36,9 +36,6 @@ fn main() { import(); //~ ERROR: unresolved foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared } diff --git a/src/test/compile-fail/inner-static-type-parameter.rs b/src/test/compile-fail/inner-static-type-parameter.rs index abd7efe0e8ed1..cf2a70deee513 100644 --- a/src/test/compile-fail/inner-static-type-parameter.rs +++ b/src/test/compile-fail/inner-static-type-parameter.rs @@ -14,7 +14,8 @@ enum Bar { What } fn foo() { static a: Bar = Bar::What; - //~^ ERROR: cannot use an outer type parameter in this context + //~^ ERROR cannot use an outer type parameter in this context + //~| ERROR use of undeclared type name `T` } fn main() { diff --git a/src/test/compile-fail/issue-3521-2.rs b/src/test/compile-fail/issue-3521-2.rs index 678618d721692..ad5bc4e445c98 100644 --- a/src/test/compile-fail/issue-3521-2.rs +++ b/src/test/compile-fail/issue-3521-2.rs @@ -11,7 +11,9 @@ fn main() { let foo = 100; - static y: isize = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant + static y: isize = foo + 1; + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `foo` println!("{}", y); } diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs index c49959c16a621..f06aa45ac38fd 100644 --- a/src/test/compile-fail/issue-3521.rs +++ b/src/test/compile-fail/issue-3521.rs @@ -13,7 +13,9 @@ fn main() { #[derive(Debug)] enum Stuff { - Bar = foo //~ ERROR attempt to use a non-constant value in a constant + Bar = foo + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `foo` } println!("{}", Stuff::Bar); diff --git a/src/test/compile-fail/issue-3668-2.rs b/src/test/compile-fail/issue-3668-2.rs index 0577b1527234d..a09c8090de06d 100644 --- a/src/test/compile-fail/issue-3668-2.rs +++ b/src/test/compile-fail/issue-3668-2.rs @@ -9,7 +9,9 @@ // except according to those terms. fn f(x:isize) { - static child: isize = x + 1; //~ ERROR attempt to use a non-constant value in a constant + static child: isize = x + 1; + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `x` } fn main() {} diff --git a/src/test/compile-fail/issue-3668.rs b/src/test/compile-fail/issue-3668.rs index 9c31dc1e38ef8..9b7476244f0d2 100644 --- a/src/test/compile-fail/issue-3668.rs +++ b/src/test/compile-fail/issue-3668.rs @@ -17,6 +17,7 @@ impl PTrait for P { fn getChildOption(&self) -> Option> { static childVal: Box

= self.child.get(); //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `self` panic!(); } } diff --git a/src/test/compile-fail/no-implicit-prelude-nested.rs b/src/test/compile-fail/no-implicit-prelude-nested.rs index 2fb097f111db4..526750257d278 100644 --- a/src/test/compile-fail/no-implicit-prelude-nested.rs +++ b/src/test/compile-fail/no-implicit-prelude-nested.rs @@ -18,11 +18,11 @@ mod foo { mod baz { struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name @@ -30,11 +30,11 @@ mod foo { } struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name @@ -45,11 +45,11 @@ fn qux() { #[no_implicit_prelude] mod qux_inner { struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name diff --git a/src/test/compile-fail/no-implicit-prelude.rs b/src/test/compile-fail/no-implicit-prelude.rs index c0f7bea25b57a..c4bcd33b93bd0 100644 --- a/src/test/compile-fail/no-implicit-prelude.rs +++ b/src/test/compile-fail/no-implicit-prelude.rs @@ -17,11 +17,11 @@ // fail with the same error message). struct Test; -impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait +impl Add for Test {} //~ ERROR: use of undeclared trait +impl Clone for Test {} //~ ERROR: use of undeclared trait +impl Iterator for Test {} //~ ERROR: use of undeclared trait +impl ToString for Test {} //~ ERROR: use of undeclared trait +impl Writer for Test {} //~ ERROR: use of undeclared trait fn main() { drop(2) //~ ERROR: unresolved name diff --git a/src/test/compile-fail/resolve-unknown-trait.rs b/src/test/compile-fail/resolve-unknown-trait.rs index 0d0dc0a05d12a..3983a84f6ad17 100644 --- a/src/test/compile-fail/resolve-unknown-trait.rs +++ b/src/test/compile-fail/resolve-unknown-trait.rs @@ -10,11 +10,11 @@ trait NewTrait : SomeNonExistentTrait {} -//~^ ERROR attempt to derive a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` impl SomeNonExistentTrait for isize {} -//~^ ERROR attempt to implement a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` fn f() {} -//~^ ERROR attempt to bound type parameter with a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` diff --git a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs index 12f62d805e15a..f28bf7acadd37 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs @@ -10,7 +10,7 @@ #![feature(unboxed_closures)] -fn f isize>(x: F) {} //~ ERROR nonexistent trait `Nonexist` +fn f isize>(x: F) {} //~ ERROR undeclared trait name `Nonexist` type Typedef = isize; From 0f49254b31353a80710af50e4f387740d154e60b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 5 Feb 2015 13:20:48 +0200 Subject: [PATCH 10/25] rustc: use partially resolved definitions to replace the `T::A` hack. --- src/librustc/middle/astconv_util.rs | 38 +- src/librustc/middle/astencode.rs | 4 - src/librustc/middle/def.rs | 40 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/ty.rs | 9 +- src/librustc_driver/driver.rs | 2 + src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 150 +++--- src/librustc_trans/save/mod.rs | 1 - src/librustc_trans/trans/callee.rs | 2 +- src/librustc_typeck/astconv.rs | 481 +++++++++--------- src/librustc_typeck/check/mod.rs | 7 +- src/test/compile-fail/issue-7607-1.rs | 4 +- src/test/compile-fail/issue-8767.rs | 2 +- .../compile-fail/trait-impl-for-module.rs | 2 +- .../compile-fail/trait-or-new-type-instead.rs | 5 +- 16 files changed, 376 insertions(+), 375 deletions(-) diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index d45c18efee7b4..621a231ed7d18 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -17,29 +17,47 @@ use middle::def; use middle::ty::{self, Ty}; use syntax::ast; +use syntax::codemap::Span; use util::ppaux::Repr; pub const NO_REGIONS: uint = 1; pub const NO_TPS: uint = 2; pub fn check_path_args(tcx: &ty::ctxt, - path: &ast::Path, + span: Span, + segments: &[ast::PathSegment], flags: uint) { if (flags & NO_TPS) != 0 { - if path.segments.iter().any(|s| s.parameters.has_types()) { - span_err!(tcx.sess, path.span, E0109, + if segments.iter().any(|s| s.parameters.has_types()) { + span_err!(tcx.sess, span, E0109, "type parameters are not allowed on this type"); } } if (flags & NO_REGIONS) != 0 { - if path.segments.iter().any(|s| s.parameters.has_lifetimes()) { - span_err!(tcx.sess, path.span, E0110, + if segments.iter().any(|s| s.parameters.has_lifetimes()) { + span_err!(tcx.sess, span, E0110, "lifetime parameters are not allowed on this type"); } } } +pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>, + span: Span, + segments: &[ast::PathSegment], + nty: ast::PrimTy) + -> Ty<'tcx> { + check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS); + match nty { + ast::TyBool => tcx.types.bool, + ast::TyChar => tcx.types.char, + ast::TyInt(it) => ty::mk_mach_int(tcx, it), + ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit), + ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft), + ast::TyStr => ty::mk_str(tcx) + } +} + pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { if let ast::TyPath(ref path) = ast_ty.node { @@ -51,15 +69,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) Some(&d) => d }; if let def::DefPrimTy(nty) = def { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(match nty { - ast::TyBool => tcx.types.bool, - ast::TyChar => tcx.types.char, - ast::TyInt(it) => ty::mk_mach_int(tcx, it), - ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit), - ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft), - ast::TyStr => ty::mk_str(tcx) - }) + Some(prim_ty_to_ty(tcx, path.span, &path.segments[], nty)) } else { None } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 37586b08b3654..f7d34f0056b0c 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -444,10 +444,6 @@ impl tr for def::Def { def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum), def::DefAssociatedTy(trait_did, did) => def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)), - def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) => - def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident), - def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) => - def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident), def::DefPrimTy(p) => def::DefPrimTy(p), def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n), def::DefUse(did) => def::DefUse(did.tr(dcx)), diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 191672775f253..e1794cc0c8ae2 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -33,11 +33,6 @@ pub enum Def { DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */), DefTy(ast::DefId, bool /* is_enum */), DefAssociatedTy(ast::DefId /* trait */, ast::DefId), - // A partially resolved path to an associated type `T::U` where `T` is a concrete - // type (indicated by the DefId) which implements a trait which has an associated - // type `U` (indicated by the Ident). - // FIXME(#20301) -- should use Name - DefAssociatedPath(TyParamProvenance, ast::Ident), DefTrait(ast::DefId), DefPrimTy(ast::PrimTy), DefTyParam(ParamSpace, u32, ast::DefId, ast::Name), @@ -59,8 +54,24 @@ pub enum Def { DefMethod(ast::DefId /* method */, Option /* trait */, MethodProvenance), } +/// The result of resolving the prefix of a path to a type: +/// +/// module::Type::AssocA::AssocB::AssocC::MethodOrAssocType +/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~ +/// base_type extra_associated_types +/// +/// ::AssocA::AssocB::AssocC::MethodOrAssocType +/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~ +/// base_type extra_associated_types +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct PartialDef { + pub base_type: Def, + pub extra_associated_types: u32, +} + // Definition mapping pub type DefMap = RefCell>; +pub type PartialDefMap = RefCell>; // This is the replacement export map. It maps a module to all of the exports // within. pub type ExportMap = NodeMap>; @@ -77,12 +88,6 @@ pub enum MethodProvenance { FromImpl(ast::DefId), } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TyParamProvenance { - FromSelf(ast::DefId), - FromParam(ast::DefId), -} - impl MethodProvenance { pub fn map(self, f: F) -> MethodProvenance where F: FnOnce(ast::DefId) -> ast::DefId, @@ -94,15 +99,6 @@ impl MethodProvenance { } } -impl TyParamProvenance { - pub fn def_id(&self) -> ast::DefId { - match *self { - TyParamProvenance::FromSelf(ref did) => did.clone(), - TyParamProvenance::FromParam(ref did) => did.clone(), - } - } -} - #[derive(Clone, Copy, Eq, PartialEq)] pub enum TraitItemKind { NonstaticMethodTraitItemKind, @@ -135,9 +131,7 @@ impl Def { DefForeignMod(id) | DefStatic(id, _) | DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) | DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | - DefMethod(id, _, _) | DefConst(id) | - DefAssociatedPath(TyParamProvenance::FromSelf(id), _) | - DefAssociatedPath(TyParamProvenance::FromParam(id), _) => { + DefMethod(id, _, _) | DefConst(id) => { id } DefLocal(id) | diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 59e090a603703..57aac8f98b6c5 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -582,7 +582,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | - def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> { + def::DefAssociatedTy(..) => { Ok(Rc::new(cmt_ { id:id, span:span, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c4fe3f4df0218..2b0d032aa6df8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -46,7 +46,7 @@ use metadata::csearch; use middle; use middle::check_const; use middle::const_eval; -use middle::def::{self, DefMap, ExportMap}; +use middle::def::{self, DefMap, ExportMap, PartialDefMap}; use middle::dependency_format; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem}; use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem}; @@ -682,6 +682,7 @@ pub struct ctxt<'tcx> { pub sess: Session, pub def_map: DefMap, + pub partial_def_map: PartialDefMap, pub named_region_map: resolve_lifetime::NamedRegionMap, @@ -2423,7 +2424,8 @@ impl<'tcx> CommonTypes<'tcx> { pub fn mk_ctxt<'tcx>(s: Session, arenas: &'tcx CtxtArenas<'tcx>, - dm: DefMap, + def_map: DefMap, + partial_def_map: PartialDefMap, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, freevars: RefCell, @@ -2445,7 +2447,8 @@ pub fn mk_ctxt<'tcx>(s: Session, item_variance_map: RefCell::new(DefIdMap()), variance_computed: Cell::new(false), sess: s, - def_map: dm, + def_map: def_map, + partial_def_map: partial_def_map, region_maps: region_maps, node_types: RefCell::new(FnvHashMap()), item_substs: RefCell::new(NodeMap()), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b12f05d7c50f7..b5933ca11bafc 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -567,6 +567,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, let resolve::CrateMap { def_map, + partial_def_map, freevars, export_map, trait_map, @@ -607,6 +608,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, let ty_cx = ty::mk_ctxt(sess, arenas, def_map, + partial_def_map, named_region_map, ast_map, freevars, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index cc47090198ba2..fefb3c5fe7dc4 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -940,7 +940,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { is_public, DUMMY_SP) } - DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => { + DefTy(..) | DefAssociatedTy(..) => { debug!("(building reduced graph for external \ crate) building type {}", final_ident); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b211681992ba9..4a57dd0912e6a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -935,6 +935,7 @@ struct Resolver<'a, 'tcx:'a> { primitive_type_table: PrimitiveTypeTable, def_map: DefMap, + partial_def_map: PartialDefMap, freevars: RefCell, freevars_seen: RefCell>, export_map: ExportMap, @@ -1008,6 +1009,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { primitive_type_table: PrimitiveTypeTable::new(), def_map: RefCell::new(NodeMap()), + partial_def_map: RefCell::new(NodeMap()), freevars: RefCell::new(NodeMap()), freevars_seen: RefCell::new(NodeMap()), export_map: NodeMap(), @@ -2988,13 +2990,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { id: NodeId, trait_path: &Path, path_depth: usize) - -> Result<(Def, LastPrivate), ()> { + -> Result<(Def, LastPrivate, usize), ()> { match self.resolve_path(id, trait_path, path_depth, TypeNS, true) { - Some(def @ (DefTrait(_), _)) => { + Some(def @ (DefTrait(_), _, _)) => { debug!("(resolving trait) found trait def: {:?}", def); Ok(def) } - Some((def, _)) => { + Some((def, _, _)) => { self.resolve_error(trait_path.span, &format!("`{}` is not a trait", self.path_names_to_string(trait_path, path_depth))); @@ -3025,8 +3027,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) { - Some((def @ DefTyParam(..), last_private)) => { - self.record_def(eq_pred.id, (def, last_private)); + Some(def @ (DefTyParam(..), _, _)) => { + self.record_def(eq_pred.id, def); } _ => { self.resolve_error(eq_pred.path.span, @@ -3121,30 +3123,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); }); }); - - // Check that the current type is indeed a type, if we have an anonymous impl - if opt_trait_reference.is_none() { - match self_type.node { - // TyPath is the only thing that we handled in `build_reduced_graph_for_item`, - // where we created a module with the name of the type in order to implement - // an anonymous trait. In the case that the path does not resolve to an actual - // type, the result will be that the type name resolves to a module but not - // a type (shadowing any imported modules or types with this name), leading - // to weird user-visible bugs. So we ward this off here. See #15060. - TyPath(ref path) => { - match self.def_map.borrow().get(&self_type.id) { - // FIXME: should we catch other options and give more precise errors? - Some(&DefMod(_)) => { - self.resolve_error(path.span, "inherent implementations are not \ - allowed for types not defined in \ - the current module"); - } - _ => {} - } - } - _ => { } - } - } } fn check_trait_item(&self, name: Name, span: Span) { @@ -3304,14 +3282,31 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // on whether the path has multiple elements in it or not. TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => { - if let TyQPath(_) = ty.node { + let max_assoc_types = if let TyQPath(_) = ty.node { // Make sure the trait is valid. - self.resolve_trait_reference(ty.id, path, 1); + let _ = self.resolve_trait_reference(ty.id, path, 1); + 1 + } else { + path.segments.len() + }; + + let mut result = None; + for depth in 0..max_assoc_types { + self.with_no_errors(|this| { + result = this.resolve_path(ty.id, path, depth, TypeNS, true); + }); + if result.is_some() { + break; + } + } + if let Some((DefMod(_), _, _)) = result { + // A module is not a valid type. + result = None; } // This is a path in the type namespace. Walk through scopes // looking for it. - match self.resolve_path(ty.id, path, 0, TypeNS, true) { + match result { Some(def) => { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ @@ -3321,6 +3316,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(ty.id, def); } None => { + // Keep reporting some errors even if they're ignored above. + self.resolve_path(ty.id, path, 0, TypeNS, true); + let kind = match ty.node { TyQPath(_) => "associated type", _ => "type name" @@ -3371,7 +3369,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "an enum variant"); - self.record_def(pattern.id, (def, lp)); + self.record_def(pattern.id, (def, lp, 0)); } FoundStructOrEnumVariant(..) => { self.resolve_error( @@ -3390,7 +3388,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "a constant"); - self.record_def(pattern.id, (def, lp)); + self.record_def(pattern.id, (def, lp, 0)); } FoundConst(..) => { self.resolve_error(pattern.span, @@ -3407,7 +3405,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // will be able to distinguish variants from // locals in patterns. - self.record_def(pattern.id, (def, LastMod(AllPublic))); + self.record_def(pattern.id, (def, LastMod(AllPublic), 0)); // Add the binding to the local ribs, if it // doesn't already exist in the bindings list. (We @@ -3451,12 +3449,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatEnum(ref path, _) => { // This must be an enum variant, struct or const. match self.resolve_path(pat_id, path, 0, ValueNS, false) { - Some(def @ (DefVariant(..), _)) | - Some(def @ (DefStruct(..), _)) | - Some(def @ (DefConst(..), _)) => { + Some(def @ (DefVariant(..), _, _)) | + Some(def @ (DefStruct(..), _, _)) | + Some(def @ (DefConst(..), _, _)) => { self.record_def(pattern.id, def); } - Some((DefStatic(..), _)) => { + Some((DefStatic(..), _, _)) => { self.resolve_error(path.span, "static variables cannot be \ referenced in a pattern, \ @@ -3573,40 +3571,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path: &Path, path_depth: usize, namespace: Namespace, - check_ribs: bool) -> Option<(Def, LastPrivate)> { + check_ribs: bool) -> Option<(Def, LastPrivate, usize)> { let span = path.span; let segments = &path.segments[..path.segments.len()-path_depth]; - // A special case for sugared associated type paths `T::A` where `T` is - // a type parameter and `A` is an associated type on some bound of `T`. - if namespace == TypeNS && segments.len() == 2 { - match self.resolve_identifier(segments[0].identifier, - TypeNS, - true, - span) { - Some((def, last_private)) => { - match def { - DefTyParam(_, _, did, _) => { - let def = DefAssociatedPath(TyParamProvenance::FromParam(did), - segments.last() - .unwrap().identifier); - return Some((def, last_private)); - } - DefSelfTy(nid) => { - let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)), - segments.last() - .unwrap().identifier); - return Some((def, last_private)); - } - _ => {} - } - } - _ => {} - } - } - if path.global { - return self.resolve_crate_relative_path(span, segments, namespace); + let def = self.resolve_crate_relative_path(span, segments, namespace); + return def.map(|(def, lp)| (def, lp, path_depth)); } // Try to find a path to an item in a module. @@ -3628,10 +3599,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => () } - return def; + def.map(|(def, lp)| (def, lp, path_depth)) + } else { + unqualified_def.map(|(def, lp)| (def, lp, path_depth)) } - - unqualified_def } // resolve a single identifier (used as a varref) @@ -4105,14 +4076,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { if let ExprQPath(_) = expr.node { // Make sure the trait is valid. - self.resolve_trait_reference(expr.id, path, 1); + let _ = self.resolve_trait_reference(expr.id, path, 1); } // This is a local path in the value namespace. Walk through // scopes looking for it. match self.resolve_path(expr.id, path, 0, ValueNS, true) { // Check if struct variant - Some((DefVariant(_, _, true), _)) => { + Some((DefVariant(_, _, true), _, _)) => { let path_name = self.path_names_to_string(path, 0); self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ @@ -4140,7 +4111,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let path_name = self.path_names_to_string(path, 0); match self.with_no_errors(|this| this.resolve_path(expr.id, path, 0, TypeNS, false)) { - Some((DefTy(struct_id, _), _)) + Some((DefTy(struct_id, _), _, 0)) if self.structs.contains_key(&struct_id) => { self.resolve_error(expr.span, &format!("`{}` is a structure name, but \ @@ -4252,7 +4223,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. - self.record_def(expr.id, (def, LastMod(AllPublic))) + self.record_def(expr.id, (def, LastMod(AllPublic), 0)) } Some(_) => { self.session.span_bug(expr.span, @@ -4372,18 +4343,31 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn record_def(&mut self, node_id: NodeId, - (def, lp): (Def, LastPrivate)) { + (def, lp, depth): (Def, LastPrivate, usize)) { debug!("(recording def) recording {:?} for {}, last private {:?}", def, node_id, lp); assert!(match lp {LastImport{..} => false, _ => true}, "Import should only be used for `use` directives"); self.last_private.insert(node_id, lp); - if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) { - let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); - self.session.span_bug(span, &format!("path resolved multiple times \ - ({:?} before, {:?} now)", - prev_def, def)); + if depth == 0 { + if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) { + let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); + self.session.span_bug(span, &format!("path resolved multiple times \ + ({:?} before, {:?} now)", + prev_def, def)); + } + } else { + let def = PartialDef { + base_type: def, + extra_associated_types: (depth - 1) as u32 + }; + if let Some(prev_def) = self.partial_def_map.borrow_mut().insert(node_id, def) { + let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); + self.session.span_bug(span, &format!("path resolved multiple times \ + ({:?} before, {:?} now)", + prev_def, def)); + } } } @@ -4474,6 +4458,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub struct CrateMap { pub def_map: DefMap, + pub partial_def_map: PartialDefMap, pub freevars: RefCell, pub export_map: ExportMap, pub trait_map: TraitMap, @@ -4513,6 +4498,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, CrateMap { def_map: resolver.def_map, + partial_def_map: resolver.partial_def_map, freevars: resolver.freevars, export_map: resolver.export_map, trait_map: resolver.trait_map, diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 531700b9563be..0ba7bd84603cf 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -238,7 +238,6 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefStruct(_) => Some(recorder::StructRef), def::DefTy(..) | def::DefAssociatedTy(..) | - def::DefAssociatedPath(..) | def::DefTrait(_) => Some(recorder::TypeRef), def::DefStatic(_, _) | def::DefConst(_) | diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 9dbcbc8b1a28e..196686a70d1a1 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -210,7 +210,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) | def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) | def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) | - def::DefTyParam(..) | def::DefSelfTy(..) | def::DefAssociatedPath(..) => { + def::DefTyParam(..) | def::DefSelfTy(..) => { bcx.tcx().sess.span_bug( ref_expr.span, &format!("cannot translate def {:?} \ diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8eb75ece4a145..bc0986eff1f28 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -48,7 +48,7 @@ //! case but `&a` in the second. Basically, defaults that appear inside //! an rptr (`&r.T`) use the region `r` that appears in the rptr. -use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS}; +use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS}; use middle::const_eval; use middle::def; use middle::resolve_lifetime as rl; @@ -57,13 +57,13 @@ use middle::traits; use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope}; -use TypeAndSubsts; use util::common::{ErrorReported, FN_OUTPUT_NAME}; use util::nodemap::DefIdMap; use util::ppaux::{self, Repr, UserString}; -use std::rc::Rc; use std::iter::{repeat, AdditiveIterator}; +use std::rc::Rc; +use std::slice; use syntax::{abi, ast, ast_util}; use syntax::codemap::Span; use syntax::parse::token; @@ -245,8 +245,9 @@ pub fn opt_ast_region_to_region<'tcx>( pub fn ast_path_substs_for_ty<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, decl_generics: &ty::Generics<'tcx>, - path: &ast::Path) + item_segment: &ast::PathSegment) -> Substs<'tcx> { let tcx = this.tcx(); @@ -262,12 +263,12 @@ pub fn ast_path_substs_for_ty<'tcx>( assert!(decl_generics.regions.all(|d| d.space == TypeSpace)); assert!(decl_generics.types.all(|d| d.space != FnSpace)); - let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters { + let (regions, types, assoc_bindings) = match item_segment.parameters { ast::AngleBracketedParameters(ref data) => { convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data) } ast::ParenthesizedParameters(ref data) => { - span_err!(tcx.sess, path.span, E0214, + span_err!(tcx.sess, span, E0214, "parenthesized parameters may only be used with a trait"); convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data) } @@ -276,7 +277,7 @@ pub fn ast_path_substs_for_ty<'tcx>( prohibit_projections(this.tcx(), &assoc_bindings); create_substs_for_ast_path(this, - path.span, + span, decl_generics, None, types, @@ -625,8 +626,9 @@ pub fn instantiate_trait_ref<'tcx>( fn object_path_to_poly_trait_ref<'a,'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, trait_def_id: ast::DefId, - path: &ast::Path, + trait_segment: &ast::PathSegment, mut projections: &mut Vec>) -> ty::PolyTraitRef<'tcx> { @@ -637,10 +639,10 @@ fn object_path_to_poly_trait_ref<'a,'tcx>( let mut tmp = Vec::new(); let trait_ref = ty::Binder(ast_path_to_trait_ref(this, &shifted_rscope, - path.span, + span, trait_def_id, None, - path.segments.last().unwrap(), + trait_segment, Some(&mut tmp))); projections.extend(tmp.into_iter().map(ty::Binder)); trait_ref @@ -824,78 +826,28 @@ fn ast_type_binding_to_projection_predicate<'tcx>( }) } -pub fn ast_path_to_ty<'tcx>( +fn ast_path_to_ty<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, did: ast::DefId, - path: &ast::Path) - -> TypeAndSubsts<'tcx> + item_segment: &ast::PathSegment) + -> Ty<'tcx> { - let tcx = this.tcx(); let ty::TypeScheme { generics, ty: decl_ty } = this.get_item_type_scheme(did); - let substs = ast_path_substs_for_ty(this, - rscope, - &generics, - path); - let ty = decl_ty.subst(tcx, &substs); - TypeAndSubsts { substs: substs, ty: ty } -} + let substs = ast_path_substs_for_ty(this, rscope, span, &generics, item_segment); -/// Converts the given AST type to a built-in type. A "built-in type" is, at -/// present, either a core numeric type, a string, or `Box`. -pub fn ast_ty_to_builtin_ty<'tcx>( - this: &AstConv<'tcx>, - rscope: &RegionScope, - ast_ty: &ast::Ty) - -> Option> { - match ast_ty_to_prim_ty(this.tcx(), ast_ty) { - Some(typ) => return Some(typ), - None => {} + // FIXME(#12938): This is a hack until we have full support for DST. + if Some(did) == this.tcx().lang_items.owned_box() { + assert_eq!(substs.types.len(TypeSpace), 1); + return ty::mk_uniq(this.tcx(), *substs.types.get(TypeSpace, 0)); } - match ast_ty.node { - ast::TyPath(ref path) => { - let a_def = match this.tcx().def_map.borrow().get(&ast_ty.id) { - None => { - this.tcx() - .sess - .span_bug(ast_ty.span, - &format!("unbound path {}", - path.repr(this.tcx()))) - } - Some(&d) => d - }; - - // FIXME(#12938): This is a hack until we have full support for - // DST. - match a_def { - def::DefTy(did, _) | - def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => { - let ty = ast_path_to_ty(this, rscope, did, path).ty; - match ty.sty { - ty::ty_struct(struct_def_id, ref substs) => { - assert_eq!(struct_def_id, did); - assert_eq!(substs.types.len(TypeSpace), 1); - let referent_ty = *substs.types.get(TypeSpace, 0); - Some(ty::mk_uniq(this.tcx(), referent_ty)) - } - _ => { - this.tcx().sess.span_bug( - path.span, - &format!("converting `Box` to `{}`", - ty.repr(this.tcx()))); - } - } - } - _ => None - } - } - _ => None - } + decl_ty.subst(this.tcx(), &substs) } type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec>); @@ -919,13 +871,15 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, match ty.node { ast::TyPath(ref path) => { - match this.tcx().def_map.borrow().get(&ty.id) { - Some(&def::DefTrait(trait_def_id)) => { + let def = this.tcx().def_map.borrow().get(&ty.id).cloned(); + match def { + Some(def::DefTrait(trait_def_id)) => { let mut projection_bounds = Vec::new(); let trait_ref = object_path_to_poly_trait_ref(this, rscope, + path.span, trait_def_id, - path, + path.segments.last().unwrap(), &mut projection_bounds); Ok((trait_ref, projection_bounds)) } @@ -989,21 +943,35 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>, } fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, - ast_ty: &ast::Ty, - provenance: def::TyParamProvenance, - assoc_name: ast::Name) - -> Ty<'tcx> + span: Span, + ty: Ty<'tcx>, + ty_path_def: def::Def, + item_segment: &ast::PathSegment) + -> (Ty<'tcx>, def::Def) { let tcx = this.tcx(); - let ty_param_def_id = provenance.def_id(); + check_path_args(tcx, span, slice::ref_slice(item_segment), + NO_TPS | NO_REGIONS); + let assoc_name = item_segment.identifier.name; + + let ty_param_node_id = if let ty::ty_param(_) = ty.sty { + ty_path_def.local_node_id() + } else { + span_err!(tcx.sess, span, E0223, + "ambiguous associated type; specify the type using the syntax \ + `<{} as Trait>::{}`", + ty.user_string(tcx), token::get_name(assoc_name)); + return (tcx.types.err, ty_path_def); + }; let mut suitable_bounds: Vec<_>; let ty_param_name: ast::Name; { // contain scope of refcell: let ty_param_defs = tcx.ty_param_defs.borrow(); - let ty_param_def = &ty_param_defs[ty_param_def_id.node]; + let ty_param_def = &ty_param_defs[ty_param_node_id]; ty_param_name = ty_param_def.name; + // FIXME(#20300) -- search where clauses, not bounds suitable_bounds = traits::transitive_bounds(tcx, &ty_param_def.bounds.trait_bounds) @@ -1012,21 +980,21 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, } if suitable_bounds.len() == 0 { - span_err!(tcx.sess, ast_ty.span, E0220, + span_err!(tcx.sess, span, E0220, "associated type `{}` not found for type parameter `{}`", token::get_name(assoc_name), token::get_name(ty_param_name)); - return this.tcx().types.err; + return (this.tcx().types.err, ty_path_def); } if suitable_bounds.len() > 1 { - span_err!(tcx.sess, ast_ty.span, E0221, + span_err!(tcx.sess, span, E0221, "ambiguous associated type `{}` in bounds of `{}`", token::get_name(assoc_name), token::get_name(ty_param_name)); for suitable_bound in &suitable_bounds { - span_note!(this.tcx().sess, ast_ty.span, + span_note!(this.tcx().sess, span, "associated type `{}` could derive from `{}`", token::get_name(ty_param_name), suitable_bound.user_string(this.tcx())); @@ -1034,7 +1002,32 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, } let suitable_bound = suitable_bounds.pop().unwrap().clone(); - return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name); + let trait_did = suitable_bound.0.def_id; + + let ty = this.projected_ty_from_poly_trait_ref(span, suitable_bound, assoc_name); + + let item_did = if trait_did.krate == ast::LOCAL_CRATE { + // `ty::trait_items` used below requires information generated + // by type collection, which may be in progress at this point. + match this.tcx().map.expect_item(trait_did.node).node { + ast::ItemTrait(_, _, _, ref trait_items) => { + trait_items.iter().filter_map(|i| { + if let ast::TypeTraitItem(ref assoc) = *i { + if assoc.ty_param.ident.name == assoc_name { + return Some(ast_util::local_def(assoc.ty_param.id)); + } + } + None + }).next().expect("missing associated type") + } + _ => unreachable!() + } + } else { + let trait_items = ty::trait_items(this.tcx(), trait_did); + let item = trait_items.iter().find(|i| i.name() == assoc_name); + item.expect("missing associated type").def_id() + }; + (ty, def::DefAssociatedTy(trait_did, item_did)) } fn trait_defines_associated_type_named(this: &AstConv, @@ -1058,6 +1051,9 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, { let tcx = this.tcx(); + check_path_args(tcx, span, slice::ref_slice(item_segment), + NO_TPS | NO_REGIONS); + let self_ty = if let Some(ty) = opt_self_ty { ast_ty_to_ty(this, rscope, ty) } else { @@ -1081,9 +1077,6 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx)); - // `::U` shouldn't parse right now. - assert!(item_segment.parameters.is_empty()); - this.projected_ty(span, trait_ref, item_segment.identifier.name) } @@ -1146,164 +1139,184 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved); drop(ast_ty_to_ty_cache); - let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| { - match ast_ty.node { - ast::TyVec(ref ty) => { - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) - } - ast::TyObjectSum(ref ty, ref bounds) => { - match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[..]) { - Ok((trait_ref, projection_bounds)) => { - trait_ref_to_object_type(this, - rscope, - ast_ty.span, - trait_ref, - projection_bounds, - &bounds[..]) - } - Err(ErrorReported) => { - this.tcx().types.err - } + let typ = match ast_ty.node { + ast::TyVec(ref ty) => { + ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) + } + ast::TyObjectSum(ref ty, ref bounds) => { + match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) { + Ok((trait_ref, projection_bounds)) => { + trait_ref_to_object_type(this, + rscope, + ast_ty.span, + trait_ref, + projection_bounds, + bounds) } - } - ast::TyPtr(ref mt) => { - ty::mk_ptr(tcx, ty::mt { - ty: ast_ty_to_ty(this, rscope, &*mt.ty), - mutbl: mt.mutbl - }) - } - ast::TyRptr(ref region, ref mt) => { - let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region); - debug!("ty_rptr r={}", r.repr(this.tcx())); - let rscope1 = - &ObjectLifetimeDefaultRscope::new( - rscope, - Some(ty::ObjectLifetimeDefault::Specific(r))); - let t = ast_ty_to_ty(this, rscope1, &*mt.ty); - ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl}) - } - ast::TyTup(ref fields) => { - let flds = fields.iter() - .map(|t| ast_ty_to_ty(this, rscope, &**t)) - .collect(); - ty::mk_tup(tcx, flds) - } - ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ), - ast::TyBareFn(ref bf) => { - if bf.decl.variadic && bf.abi != abi::C { - span_err!(tcx.sess, ast_ty.span, E0222, - "variadic function must have C calling convention"); + Err(ErrorReported) => { + this.tcx().types.err } - let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl); - ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn)) } - ast::TyPolyTraitRef(ref bounds) => { - conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..]) + } + ast::TyPtr(ref mt) => { + ty::mk_ptr(tcx, ty::mt { + ty: ast_ty_to_ty(this, rscope, &*mt.ty), + mutbl: mt.mutbl + }) + } + ast::TyRptr(ref region, ref mt) => { + let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region); + debug!("ty_rptr r={}", r.repr(this.tcx())); + let rscope1 = + &ObjectLifetimeDefaultRscope::new( + rscope, + Some(ty::ObjectLifetimeDefault::Specific(r))); + let t = ast_ty_to_ty(this, rscope1, &*mt.ty); + ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl}) + } + ast::TyTup(ref fields) => { + let flds = fields.iter() + .map(|t| ast_ty_to_ty(this, rscope, &**t)) + .collect(); + ty::mk_tup(tcx, flds) + } + ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ), + ast::TyBareFn(ref bf) => { + if bf.decl.variadic && bf.abi != abi::C { + span_err!(tcx.sess, ast_ty.span, E0222, + "variadic function must have C calling convention"); } - ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { - let a_def = match tcx.def_map.borrow().get(&ast_ty.id) { - None => { - tcx.sess - .span_bug(ast_ty.span, - &format!("unbound path {}", - ast_ty.repr(tcx))) - } - Some(&d) => d - }; - match a_def { - def::DefTrait(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 = object_path_to_poly_trait_ref(this, - rscope, - trait_def_id, - path, - &mut projection_bounds); - - trait_ref_to_object_type(this, rscope, ast_ty.span, - trait_ref, projection_bounds, &[]) - } - def::DefTy(did, _) | def::DefStruct(did) => { - ast_path_to_ty(this, rscope, did, path).ty - } - def::DefTyParam(space, index, _, name) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_param(tcx, space, index, name) - } - def::DefSelfTy(_) => { - // n.b.: resolve guarantees that the this type only appears in a - // trait, which we rely upon in various places when creating - // substs - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_self_type(tcx) - } - def::DefMod(id) => { - span_fatal!(tcx.sess, ast_ty.span, E0247, - "found module name used as a type: {}", - tcx.map.node_to_string(id.node)); - } - def::DefPrimTy(_) => { - panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); - } - def::DefAssociatedTy(trait_did, _) => { - let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { - Some(&*qpath.self_type) - } else { - None - }; - qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, trait_did, - &path.segments[path.segments.len()-2], - path.segments.last().unwrap()) - } - def::DefAssociatedPath(provenance, assoc_ident) => { - associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) - } - _ => { - span_fatal!(tcx.sess, ast_ty.span, E0248, - "found value name used \ - as a type: {:?}", - a_def); - } + let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl); + ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn)) + } + ast::TyPolyTraitRef(ref bounds) => { + conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds) + } + ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { + let result = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { + (d, 0) + } else if let Some(d) = tcx.partial_def_map.borrow().get(&ast_ty.id) { + (d.base_type, (d.extra_associated_types + 1) as usize) + } else { + tcx.sess.span_bug(ast_ty.span, + &format!("unbound path {}", ast_ty.repr(tcx))) + }; + let (base_def, max_depth) = result; + let span = ast_ty.span; // Could be more granular. + let segments = &path.segments[..path.segments.len()-max_depth]; + let base_ty = match base_def { + def::DefTrait(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 = object_path_to_poly_trait_ref(this, + rscope, + span, + trait_def_id, + segments.last().unwrap(), + &mut projection_bounds); + + check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS); + trait_ref_to_object_type(this, rscope, span, trait_ref, + projection_bounds, &[]) + } + def::DefTy(did, _) | def::DefStruct(did) => { + check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS); + ast_path_to_ty(this, rscope, span, did, segments.last().unwrap()) } + def::DefTyParam(space, index, _, name) => { + check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS); + ty::mk_param(tcx, space, index, name) + } + def::DefSelfTy(_) => { + // n.b.: resolve guarantees that the this type only appears in a + // trait, which we rely upon in various places when creating + // substs + check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS); + ty::mk_self_type(tcx) + } + def::DefAssociatedTy(trait_did, _) => { + let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { + Some(&*qpath.self_type) + } else { + None + }; + check_path_args(tcx, span, &segments[..segments.len()-2], + NO_TPS | NO_REGIONS); + qpath_to_ty(this, rscope, span, opt_self_ty, trait_did, + &segments[segments.len()-2], + segments.last().unwrap()) + } + def::DefMod(id) => { + tcx.sess.span_bug(span, + &format!("found module name used as a type: {}", + tcx.map.node_to_string(id.node))); + } + def::DefPrimTy(prim_ty) => { + prim_ty_to_ty(tcx, span, segments, prim_ty) + } + _ => { + span_fatal!(tcx.sess, span, E0248, + "found value name used as a type: {:?}", base_def); + } + }; + + // If any associated type segments remain, attempt to resolve them. + let mut ty = base_ty; + let mut def = base_def; + for depth in (0..max_depth).rev() { + if ty.sty == ty::ty_err { + break; + } + // This is pretty bad (it will fail except for T::A and Self::A). + let segment = &path.segments[path.segments.len()-depth-1]; + let (a_ty, a_def) = associated_path_def_to_ty(this, span, + ty, def, segment); + ty = a_ty; + def = a_def; } - ast::TyFixedLengthVec(ref ty, ref e) => { - match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) { - Ok(ref r) => { - match *r { - const_eval::const_int(i) => - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), - Some(i as uint)), - const_eval::const_uint(i) => - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), - Some(i as uint)), - _ => { - span_fatal!(tcx.sess, ast_ty.span, E0249, - "expected constant expr for array length"); - } + + if max_depth != 0 && ty.sty != ty::ty_err { + // Write back the new resolution. + tcx.def_map.borrow_mut().insert(ast_ty.id, def); + } + + ty + } + ast::TyFixedLengthVec(ref ty, ref e) => { + match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) { + Ok(r) => { + match r { + const_eval::const_int(i) => + ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), + Some(i as uint)), + const_eval::const_uint(i) => + ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), + Some(i as uint)), + _ => { + span_fatal!(tcx.sess, ast_ty.span, E0249, + "expected constant expr for array length"); } } - Err(ref r) => { - span_fatal!(tcx.sess, ast_ty.span, E0250, - "expected constant expr for array \ - length: {}", - *r); - } } - } - ast::TyTypeof(ref _e) => { - tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented"); - } - ast::TyInfer => { - // TyInfer also appears as the type of arguments or return - // 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. - this.ty_infer(ast_ty.span) + Err(r) => { + span_fatal!(tcx.sess, ast_ty.span, E0250, + "expected constant expr for array length: {}", r); + } } } - }); + ast::TyTypeof(ref _e) => { + tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented"); + } + ast::TyInfer => { + // TyInfer also appears as the type of arguments or return + // 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. + this.ty_infer(ast_ty.span) + } + }; tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ)); return typ; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9d303f492eb34..f797d2b6fe7d7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1613,7 +1613,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { generics.regions.get_slice(TypeSpace)); Substs::new_type(tps, rps) } else { - astconv::ast_path_substs_for_ty(self, self, &generics, path) + astconv::ast_path_substs_for_ty(self, self, + path.span, + &generics, + path.segments.last().unwrap()) }; let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty); @@ -4632,7 +4635,6 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefTrait(_) | def::DefTy(..) | def::DefAssociatedTy(..) | - def::DefAssociatedPath(..) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefMod(..) | @@ -4731,7 +4733,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefVariant(..) | def::DefTy(..) | def::DefAssociatedTy(..) | - def::DefAssociatedPath(..) | def::DefTrait(..) | def::DefPrimTy(..) | def::DefTyParam(..) => { diff --git a/src/test/compile-fail/issue-7607-1.rs b/src/test/compile-fail/issue-7607-1.rs index 48fc393d0da8e..4ac901776099d 100644 --- a/src/test/compile-fail/issue-7607-1.rs +++ b/src/test/compile-fail/issue-7607-1.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - struct Foo { x: isize } -impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module +impl Fo { //~ ERROR use of undeclared type name `Fo` fn foo() {} } diff --git a/src/test/compile-fail/issue-8767.rs b/src/test/compile-fail/issue-8767.rs index 6c5bac5e0cb34..2ef0a75f77b5a 100644 --- a/src/test/compile-fail/issue-8767.rs +++ b/src/test/compile-fail/issue-8767.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength -impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module +impl B { //~ ERROR use of undeclared type name `B` } fn main() { diff --git a/src/test/compile-fail/trait-impl-for-module.rs b/src/test/compile-fail/trait-impl-for-module.rs index 28d20483c7e7b..969b6398fdb10 100644 --- a/src/test/compile-fail/trait-impl-for-module.rs +++ b/src/test/compile-fail/trait-impl-for-module.rs @@ -14,7 +14,7 @@ mod a { trait A { } -impl A for a { //~ERROR found module name used as a type +impl A for a { //~ ERROR use of undeclared type name `a` } fn main() { diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs index e621d77a65c8d..047e4e50c8223 100644 --- a/src/test/compile-fail/trait-or-new-type-instead.rs +++ b/src/test/compile-fail/trait-or-new-type-instead.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - -impl Option { //~ERROR inherent implementations are not allowed for types not defined in the current module +// FIXME(eddyb/UFCS) This should have a nicer error, but that's not possible just yet. +impl Option { //~ ERROR use of undeclared type name `Option` pub fn foo(&self) { } } From 7a3054f55c48682d1458176863e0ccb08d505aa8 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 11 Feb 2015 09:32:25 +0200 Subject: [PATCH 11/25] rustc_resolve: remove the distinction between DefStaticMethod and DefMethod. --- src/librustc/metadata/csearch.rs | 7 +-- src/librustc/metadata/decoder.rs | 22 ++----- src/librustc/middle/astencode.rs | 9 +-- src/librustc/middle/check_const.rs | 3 +- src/librustc/middle/def.rs | 29 +-------- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/librustc_privacy/lib.rs | 2 - src/librustc_resolve/build_reduced_graph.rs | 65 +++++-------------- src/librustc_resolve/lib.rs | 69 ++++++++++++--------- src/librustc_trans/save/mod.rs | 13 ++-- src/librustc_trans/trans/callee.rs | 6 +- src/librustc_trans/trans/consts.rs | 2 +- src/librustc_trans/trans/expr.rs | 8 +-- src/librustc_typeck/check/mod.rs | 5 +- src/test/compile-fail/issue-13641.rs | 4 +- 16 files changed, 89 insertions(+), 159 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 5ee2f89018946..f5c4cce065955 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -150,12 +150,9 @@ pub fn get_trait_name(cstore: &cstore::CStore, def: ast::DefId) -> ast::Name { def.node) } -pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId) - -> (ast::Name, def::TraitItemKind) { +pub fn is_static_method(cstore: &cstore::CStore, def: ast::DefId) -> bool { let cdata = cstore.get_crate_data(def.krate); - decoder::get_trait_item_name_and_kind(cstore.intr.clone(), - &*cdata, - def.node) + decoder::is_static_method(&*cdata, def.node) } pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 6d2269b74a218..0503045ac6e2d 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -334,12 +334,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) def::FromImpl(item_reqd_and_translated_parent_item(cnum, item)) }; - match fam { - // We don't bother to get encode/decode the trait id, we don't need it. - Method => DlDef(def::DefMethod(did, None, provenance)), - StaticMethod => DlDef(def::DefStaticMethod(did, provenance)), - _ => panic!() - } + DlDef(def::DefMethod(did, provenance)) } Type => { if item_sort(item) == Some('t') { @@ -853,22 +848,13 @@ pub fn get_trait_name(intr: Rc, item_name(&*intr, doc) } -pub fn get_trait_item_name_and_kind(intr: Rc, - cdata: Cmd, - id: ast::NodeId) - -> (ast::Name, def::TraitItemKind) { +pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool { let doc = lookup_item(id, cdata.data()); - let name = item_name(&*intr, doc); match item_sort(doc) { Some('r') | Some('p') => { - let explicit_self = get_explicit_self(doc); - (name, def::TraitItemKind::from_explicit_self_category(explicit_self)) - } - Some('t') => (name, def::TypeTraitItemKind), - c => { - panic!("get_trait_item_name_and_kind(): unknown trait item kind \ - in metadata: `{:?}`", c) + get_explicit_self(doc) == ty::StaticExplicitSelfCategory } + _ => false } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index f7d34f0056b0c..3de29a4ca538a 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -423,13 +423,8 @@ impl tr for def::Def { fn tr(&self, dcx: &DecodeContext) -> def::Def { match *self { def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor), - def::DefStaticMethod(did, p) => { - def::DefStaticMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx))) - } - def::DefMethod(did0, did1, p) => { - def::DefMethod(did0.tr(dcx), - did1.map(|did1| did1.tr(dcx)), - p.map(|did2| did2.tr(dcx))) + def::DefMethod(did, p) => { + def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx))) } def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) } def::DefMod(did) => { def::DefMod(did.tr(dcx)) } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index f1c8ad947642f..0d7e730b5cdd8 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -452,8 +452,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, v.add_qualif(NON_ZERO_SIZED); } } - Some(def::DefFn(..)) | - Some(def::DefStaticMethod(..)) | Some(def::DefMethod(..)) => { + Some(def::DefFn(..)) | Some(def::DefMethod(..)) => { // Count the function pointer. v.add_qualif(NON_ZERO_SIZED); } diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index e1794cc0c8ae2..355c52b374e01 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -10,10 +10,8 @@ pub use self::Def::*; pub use self::MethodProvenance::*; -pub use self::TraitItemKind::*; use middle::subst::ParamSpace; -use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory}; use util::nodemap::NodeMap; use syntax::ast; use syntax::ast_util::local_def; @@ -23,7 +21,6 @@ use std::cell::RefCell; #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Def { DefFn(ast::DefId, bool /* is_ctor */), - DefStaticMethod(/* method */ ast::DefId, MethodProvenance), DefSelfTy(/* trait id */ ast::NodeId), DefMod(ast::DefId), DefForeignMod(ast::DefId), @@ -51,7 +48,7 @@ pub enum Def { DefStruct(ast::DefId), DefRegion(ast::NodeId), DefLabel(ast::NodeId), - DefMethod(ast::DefId /* method */, Option /* trait */, MethodProvenance), + DefMethod(ast::DefId /* method */, MethodProvenance), } /// The result of resolving the prefix of a path to a type: @@ -99,25 +96,6 @@ impl MethodProvenance { } } -#[derive(Clone, Copy, Eq, PartialEq)] -pub enum TraitItemKind { - NonstaticMethodTraitItemKind, - StaticMethodTraitItemKind, - TypeTraitItemKind, -} - -impl TraitItemKind { - pub fn from_explicit_self_category(explicit_self_category: - ExplicitSelfCategory) - -> TraitItemKind { - if explicit_self_category == StaticExplicitSelfCategory { - StaticMethodTraitItemKind - } else { - NonstaticMethodTraitItemKind - } - } -} - impl Def { pub fn local_node_id(&self) -> ast::NodeId { let def_id = self.def_id(); @@ -127,11 +105,10 @@ impl Def { pub fn def_id(&self) -> ast::DefId { match *self { - DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) | - DefForeignMod(id) | DefStatic(id, _) | + DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) | DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | - DefMethod(id, _, _) | DefConst(id) => { + DefMethod(id, _) | DefConst(id) => { id } DefLocal(id) | diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 57aac8f98b6c5..f8065f81aa8d8 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -575,7 +575,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { match def { def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) | - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => { + def::DefFn(..) | def::DefMethod(..) => { Ok(self.cat_rvalue_node(id, span, expr_ty)) } def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) | diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2b0d032aa6df8..c8695ef4ff04a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4584,7 +4584,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { def::DefFn(_, true) => RvalueDpsExpr, // Fn pointers are just scalar values. - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr, + def::DefFn(..) | def::DefMethod(..) => RvalueDatumExpr, // Note: there is actually a good case to be made that // DefArg's, particularly those of immediate type, ought to diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 838ba9c658cf1..439e4331e353a 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -795,7 +795,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // be accurate and we can get slightly wonky error messages (but type // checking is always correct). match self.tcx.def_map.borrow()[path_id].clone() { - def::DefStaticMethod(..) => ck("static method"), def::DefFn(..) => ck("function"), def::DefStatic(..) => ck("static"), def::DefConst(..) => ck("const"), @@ -804,7 +803,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { def::DefTy(_, true) => ck("enum"), def::DefTrait(..) => ck("trait"), def::DefStruct(..) => ck("struct"), - def::DefMethod(_, Some(..), _) => ck("trait method"), def::DefMethod(..) => ck("method"), def::DefMod(..) => ck("module"), _ => {} diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index fefb3c5fe7dc4..abfb226994a53 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -40,8 +40,7 @@ use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn}; use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; -use syntax::ast::{PathListIdent, PathListMod}; -use syntax::ast::{Public, SelfStatic}; +use syntax::ast::{PathListIdent, PathListMod, Public}; use syntax::ast::StmtDecl; use syntax::ast::StructVariantKind; use syntax::ast::TupleVariantKind; @@ -598,22 +597,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { &new_parent, ForbidDuplicateValues, method.span); - let def = match method.pe_explicit_self() - .node { - SelfStatic => { - // Static methods become - // `DefStaticMethod`s. - DefStaticMethod(local_def(method.id), - FromImpl(local_def(item.id))) - } - _ => { - // Non-static methods become - // `DefMethod`s. - DefMethod(local_def(method.id), - None, - FromImpl(local_def(item.id))) - } - }; + let def = DefMethod(local_def(method.id), + FromImpl(local_def(item.id))); // NB: not IMPORTABLE let modifiers = if method.pe_vis() == ast::Public { @@ -674,7 +659,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // Add the names of all the items to the trait info. for trait_item in items { - let (name, kind) = match *trait_item { + let (name, trait_item_id) = match *trait_item { ast::RequiredMethod(_) | ast::ProvidedMethod(_) => { let ty_m = ast_util::trait_item_to_ty_method(trait_item); @@ -682,23 +667,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let name = ty_m.ident.name; // Add it as a name in the trait module. - let (def, static_flag) = match ty_m.explicit_self - .node { - SelfStatic => { - // Static methods become `DefStaticMethod`s. - (DefStaticMethod( - local_def(ty_m.id), - FromTrait(local_def(item.id))), - StaticMethodTraitItemKind) - } - _ => { - // Non-static methods become `DefMethod`s. - (DefMethod(local_def(ty_m.id), - Some(local_def(item.id)), - FromTrait(local_def(item.id))), - NonstaticMethodTraitItemKind) - } - }; + let def = DefMethod(local_def(ty_m.id), + FromTrait(local_def(item.id))); let method_name_bindings = self.add_child(name, @@ -710,7 +680,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { ty_m.span, PUBLIC); - (name, static_flag) + (name, local_def(ty_m.id)) } ast::TypeTraitItem(ref associated_type) => { let def = DefAssociatedTy(local_def(item.id), @@ -726,11 +696,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { associated_type.ty_param.span, PUBLIC); - (associated_type.ty_param.ident.name, TypeTraitItemKind) + (associated_type.ty_param.ident.name, + local_def(associated_type.ty_param.id)) } }; - self.trait_item_map.insert((name, def_id), kind); + self.trait_item_map.insert((name, def_id), trait_item_id); } name_bindings.define_type(DefTrait(def_id), sp, modifiers); @@ -889,7 +860,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id) .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers); } - DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { + DefFn(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { debug!("(building reduced graph for external \ crate) building value (fn/static) {}", final_ident); // impl methods have already been defined with the correct importability modifier @@ -911,21 +882,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let trait_item_def_ids = csearch::get_trait_item_def_ids(&self.session.cstore, def_id); - for trait_item_def_id in &trait_item_def_ids { - let (trait_item_name, trait_item_kind) = - csearch::get_trait_item_name_and_kind( - &self.session.cstore, - trait_item_def_id.def_id()); + for trait_item_def in &trait_item_def_ids { + let trait_item_name = csearch::get_trait_name(&self.session.cstore, + trait_item_def.def_id()); debug!("(building reduced graph for external crate) ... \ adding trait item '{}'", token::get_name(trait_item_name)); - self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind); + self.trait_item_map.insert((trait_item_name, def_id), + trait_item_def.def_id()); if is_exported { - self.external_exports - .insert(trait_item_def_id.def_id()); + self.external_exports.insert(trait_item_def.def_id()); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4a57dd0912e6a..b85ac04cc9e23 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -900,7 +900,7 @@ struct Resolver<'a, 'tcx:'a> { graph_root: NameBindings, - trait_item_map: FnvHashMap<(Name, DefId), TraitItemKind>, + trait_item_map: FnvHashMap<(Name, DefId), DefId>, structs: FnvHashMap>, @@ -3128,7 +3128,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn check_trait_item(&self, name: Name, span: Span) { // If there is a TraitRef in scope for an impl, then the method must be in the trait. if let Some((did, ref trait_ref)) = self.current_trait_ref { - if self.trait_item_map.get(&(name, did)).is_none() { + if !self.trait_item_map.contains_key(&(name, did)) { let path_str = self.path_names_to_string(&trait_ref.path, 0); self.resolve_error(span, &format!("method `{}` is not a member of trait `{}`", @@ -3958,6 +3958,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } + fn is_static_method(this: &Resolver, did: DefId) -> bool { + if did.krate == ast::LOCAL_CRATE { + let explicit_self = match this.ast_map.get(did.node) { + ast_map::NodeTraitItem(m) => match *m { + ast::RequiredMethod(ref m) => &m.explicit_self, + ast::ProvidedMethod(ref m) => m.pe_explicit_self(), + _ => return false + }, + ast_map::NodeImplItem(m) => match *m { + ast::MethodImplItem(ref m) => m.pe_explicit_self(), + _ => return false + }, + _ => return false + }; + explicit_self.node == ast::SelfStatic + } else { + csearch::is_static_method(&this.session.cstore, did) + } + } + let (path, node_id, allowed) = match self.current_self_type { Some(ref ty) => match extract_path_and_node_id(ty, Everything) { Some(x) => x, @@ -3986,41 +4006,30 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::>(); // Look for a method in the current self type's impl module. - match get_module(self, path.span, &name_path[..]) { - Some(module) => match module.children.borrow().get(&name) { - Some(binding) => { - let p_str = self.path_names_to_string(&path, 0); - match binding.def_for_namespace(ValueNS) { - Some(DefStaticMethod(_, provenance)) => { - match provenance { - FromImpl(_) => return StaticMethod(p_str), - FromTrait(_) => unreachable!() - } - } - Some(DefMethod(_, None, _)) if allowed == Everything => return Method, - Some(DefMethod(_, Some(_), _)) => return TraitItem, - _ => () + if let Some(module) = get_module(self, path.span, &name_path) { + if let Some(binding) = module.children.borrow().get(&name) { + if let Some(DefMethod(did, _)) = binding.def_for_namespace(ValueNS) { + if is_static_method(self, did) { + return StaticMethod(self.path_names_to_string(&path, 0)) + } + if self.current_trait_ref.is_some() { + return TraitItem; + } else if allowed == Everything { + return Method; } } - None => {} - }, - None => {} + } } // Look for a method in the current trait. - match self.current_trait_ref { - Some((did, ref trait_ref)) => { - let path_str = self.path_names_to_string(&trait_ref.path, 0); - - match self.trait_item_map.get(&(name, did)) { - Some(&StaticMethodTraitItemKind) => { - return TraitMethod(path_str) - } - Some(_) => return TraitItem, - None => {} + if let Some((trait_did, ref trait_ref)) = self.current_trait_ref { + if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) { + if is_static_method(self, did) { + return TraitMethod(self.path_names_to_string(&trait_ref.path, 0)); + } else { + return TraitItem; } } - None => {} } NoSuggestion diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 0ba7bd84603cf..5484e3c7c5fc2 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -250,7 +250,6 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefSelfTy(_) | def::DefRegion(_) | def::DefLabel(_) | - def::DefStaticMethod(..) | def::DefTyParam(..) | def::DefUse(_) | def::DefMethod(..) | @@ -815,8 +814,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { sub_span, def_id, self.cur_scope), - def::DefStaticMethod(declid, provenence) | - def::DefMethod(declid, _, provenence) => { + def::DefMethod(declid, provenence) => { let sub_span = self.span.sub_span_for_meth_name(span); let defid = if declid.krate == ast::LOCAL_CRATE { let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, @@ -872,7 +870,14 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { } // modules or types in the path prefix match *def { - def::DefStaticMethod(..) => self.write_sub_path_trait_truncated(path), + def::DefMethod(did, _) => { + let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did); + if let ty::MethodTraitItem(m) = ti { + if m.explicit_self == ty::StaticExplicitSelfCategory { + self.write_sub_path_trait_truncated(path); + } + } + } def::DefLocal(_) | def::DefStatic(_,_) | def::DefConst(..) | diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 196686a70d1a1..41e3d4b5bab25 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -165,13 +165,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did); Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) } } - def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) | - def::DefStaticMethod(did, def::FromImpl(_)) => { + def::DefFn(did, _) | def::DefMethod(did, def::FromImpl(_)) => { fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id), bcx.fcx.param_substs).val) } - def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) | - def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => { + def::DefMethod(meth_did, def::FromTrait(trait_did)) => { fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(), meth_did, trait_did, diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 19046d84d6972..e321c5f0a13d5 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -666,7 +666,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::ExprPath(_) | ast::ExprQPath(_) => { let def = cx.tcx().def_map.borrow()[e.id]; match def { - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => { + def::DefFn(..) | def::DefMethod(..) => { expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val } def::DefConst(def_id) => { diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 9e9ee4537524b..95c5122deacb6 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -875,7 +875,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_def_lvalue"); match def { - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) | + def::DefFn(..) | def::DefMethod(..) | def::DefStruct(_) | def::DefVariant(..) => { let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def, bcx.fcx.param_substs); @@ -1275,12 +1275,10 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, match def { def::DefFn(did, _) | def::DefStruct(did) | def::DefVariant(_, did, _) | - def::DefStaticMethod(did, def::FromImpl(_)) | - def::DefMethod(did, _, def::FromImpl(_)) => { + def::DefMethod(did, def::FromImpl(_)) => { callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs) } - def::DefStaticMethod(impl_did, def::FromTrait(trait_did)) | - def::DefMethod(impl_did, _, def::FromTrait(trait_did)) => { + def::DefMethod(impl_did, def::FromTrait(trait_did)) => { meth::trans_static_method_callee(ccx, impl_did, trait_did, ref_expr.id, param_substs) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f797d2b6fe7d7..4daa9a5d80ab0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4627,7 +4627,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ }, ty::GenericPredicates::empty()) } - def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) | + def::DefFn(id, _) | def::DefMethod(id, _) | def::DefStatic(id, _) | def::DefVariant(_, id, _) | def::DefStruct(id) | def::DefConst(id) => { (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id)) @@ -4751,8 +4751,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } // Case 3. Reference to a method. - def::DefStaticMethod(_, providence) | - def::DefMethod(_, _, providence) => { + def::DefMethod(_, providence) => { assert!(path.segments.len() >= 2); match providence { diff --git a/src/test/compile-fail/issue-13641.rs b/src/test/compile-fail/issue-13641.rs index 3f5d29a821758..51b6dc0d07865 100644 --- a/src/test/compile-fail/issue-13641.rs +++ b/src/test/compile-fail/issue-13641.rs @@ -17,9 +17,9 @@ mod a { fn main() { a::Foo::new(); - //~^ ERROR: static method `new` is inaccessible + //~^ ERROR: method `new` is inaccessible //~^^ NOTE: struct `Foo` is private a::Bar::new(); - //~^ ERROR: static method `new` is inaccessible + //~^ ERROR: method `new` is inaccessible //~^^ NOTE: enum `Bar` is private } From fe4f9b8e3a4563956223f3c8998b9b299a22eab8 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 11 Feb 2015 09:33:49 +0200 Subject: [PATCH 12/25] Use partial path resolutions in expressions for UFCS desugaring. --- src/librustc/middle/astconv_util.rs | 33 ++- src/librustc_resolve/lib.rs | 38 +++- src/librustc_typeck/astconv.rs | 223 +++++++++++-------- src/librustc_typeck/check/_match.rs | 6 +- src/librustc_typeck/check/method/mod.rs | 24 +- src/librustc_typeck/check/method/probe.rs | 102 ++++++--- src/librustc_typeck/check/mod.rs | 154 +++++++------ src/librustc_typeck/collect.rs | 4 +- src/test/compile-fail/issue-3973.rs | 2 - src/test/run-pass/const-polymorphic-paths.rs | 14 ++ 10 files changed, 387 insertions(+), 213 deletions(-) diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index 621a231ed7d18..1cd5a19d6788a 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -17,37 +17,36 @@ use middle::def; use middle::ty::{self, Ty}; use syntax::ast; -use syntax::codemap::Span; use util::ppaux::Repr; pub const NO_REGIONS: uint = 1; pub const NO_TPS: uint = 2; -pub fn check_path_args(tcx: &ty::ctxt, - span: Span, - segments: &[ast::PathSegment], - flags: uint) { - if (flags & NO_TPS) != 0 { - if segments.iter().any(|s| s.parameters.has_types()) { - span_err!(tcx.sess, span, E0109, - "type parameters are not allowed on this type"); +pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: uint) { + for segment in segments { + if (flags & NO_TPS) != 0 { + for typ in segment.parameters.types() { + span_err!(tcx.sess, typ.span, E0109, + "type parameters are not allowed on this type"); + break; + } } - } - if (flags & NO_REGIONS) != 0 { - if segments.iter().any(|s| s.parameters.has_lifetimes()) { - span_err!(tcx.sess, span, E0110, - "lifetime parameters are not allowed on this type"); + if (flags & NO_REGIONS) != 0 { + for lifetime in segment.parameters.lifetimes() { + span_err!(tcx.sess, lifetime.span, E0110, + "lifetime parameters are not allowed on this type"); + break; + } } } } pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>, - span: Span, segments: &[ast::PathSegment], nty: ast::PrimTy) -> Ty<'tcx> { - check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS); + check_path_args(tcx, segments, NO_TPS | NO_REGIONS); match nty { ast::TyBool => tcx.types.bool, ast::TyChar => tcx.types.char, @@ -69,7 +68,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) Some(&d) => d }; if let def::DefPrimTy(nty) = def { - Some(prim_ty_to_ty(tcx, path.span, &path.segments[], nty)) + Some(prim_ty_to_ty(tcx, &path.segments[], nty)) } else { None } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b85ac04cc9e23..0c5236101cfb8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3018,7 +3018,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn resolve_generics(&mut self, generics: &Generics) { - for type_parameter in &generics.ty_params { + for type_parameter in &*generics.ty_params { self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); } for predicate in &generics.where_clause.predicates { @@ -4083,16 +4083,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // multiple elements in it or not. ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { - if let ExprQPath(_) = expr.node { + let max_assoc_types = if let ExprQPath(_) = expr.node { // Make sure the trait is valid. let _ = self.resolve_trait_reference(expr.id, path, 1); + 1 + } else { + path.segments.len() + }; + + let mut result = self.with_no_errors(|this| { + this.resolve_path(expr.id, path, 0, ValueNS, true) + }); + for depth in 1..max_assoc_types { + if result.is_some() { + break; + } + self.with_no_errors(|this| { + result = this.resolve_path(expr.id, path, depth, TypeNS, true); + }); + } + if let Some((DefMod(_), _, _)) = result { + // A module is not a valid type or value. + result = None; } // This is a local path in the value namespace. Walk through // scopes looking for it. - match self.resolve_path(expr.id, path, 0, ValueNS, true) { + match result { // Check if struct variant - Some((DefVariant(_, _, true), _, _)) => { + Some((DefVariant(_, _, true), _, 0)) => { let path_name = self.path_names_to_string(path, 0); self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ @@ -4110,6 +4129,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving expr) resolved `{}`", self.path_names_to_string(path, 0)); + // Partial resolutions will need the set of traits in scope, + // so they can be completed during typeck. + if def.2 != 0 { + let method_name = path.segments.last().unwrap().identifier.name; + let traits = self.search_for_traits_containing_method(method_name); + self.trait_map.insert(expr.id, traits); + } + self.record_def(expr.id, def); } None => { @@ -4135,6 +4162,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } _ => { + // Keep reporting some errors even if they're ignored above. + self.resolve_path(expr.id, path, 0, ValueNS, true); + let mut method_scope = false; self.value_ribs.iter().rev().all(|rib| { method_scope = match rib.kind { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bc0986eff1f28..adbc4d546f190 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -246,6 +246,7 @@ pub fn ast_path_substs_for_ty<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, span: Span, + param_mode: PathParamMode, decl_generics: &ty::Generics<'tcx>, item_segment: &ast::PathSegment) -> Substs<'tcx> @@ -265,12 +266,12 @@ pub fn ast_path_substs_for_ty<'tcx>( let (regions, types, assoc_bindings) = match item_segment.parameters { ast::AngleBracketedParameters(ref data) => { - convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data) + convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data) } ast::ParenthesizedParameters(ref data) => { span_err!(tcx.sess, span, E0214, "parenthesized parameters may only be used with a trait"); - convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data) + convert_parenthesized_parameters(this, rscope, span, decl_generics, data) } }; @@ -278,12 +279,21 @@ pub fn ast_path_substs_for_ty<'tcx>( create_substs_for_ast_path(this, span, + param_mode, decl_generics, None, types, regions) } +#[derive(PartialEq, Eq)] +pub enum PathParamMode { + // Any path in a type context. + Explicit, + // The `module::Type` in `module::Type::method` in an expression. + Optional +} + fn create_region_substs<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, @@ -331,6 +341,7 @@ fn create_region_substs<'tcx>( fn create_substs_for_ast_path<'tcx>( this: &AstConv<'tcx>, span: Span, + param_mode: PathParamMode, decl_generics: &ty::Generics<'tcx>, self_ty: Option>, types_provided: Vec>, @@ -349,13 +360,21 @@ fn create_substs_for_ast_path<'tcx>( // Convert the type parameters supplied by the user. let ty_param_defs = decl_generics.types.get_slice(TypeSpace); - let supplied_ty_param_count = types_provided.len(); 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 = types_provided; + // Fill with `ty_infer` if no params were specified, as long as + // they were optional (e.g. paths inside expressions). + let mut type_substs = if param_mode == PathParamMode::Optional && + types_provided.is_empty() { + (0..formal_ty_param_count).map(|_| this.ty_infer(span)).collect() + } else { + types_provided + }; + + let supplied_ty_param_count = type_substs.len(); check_type_argument_count(this.tcx(), span, supplied_ty_param_count, required_ty_param_count, formal_ty_param_count); @@ -415,7 +434,7 @@ fn create_substs_for_ast_path<'tcx>( } } - return substs; + substs } struct ConvertedBinding<'tcx> { @@ -607,6 +626,7 @@ pub fn instantiate_trait_ref<'tcx>( let trait_ref = ast_path_to_trait_ref(this, rscope, path.span, + PathParamMode::Explicit, trait_def_id, self_ty, path.segments.last().unwrap(), @@ -627,6 +647,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, span: Span, + param_mode: PathParamMode, trait_def_id: ast::DefId, trait_segment: &ast::PathSegment, mut projections: &mut Vec>) @@ -640,6 +661,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>( let trait_ref = ty::Binder(ast_path_to_trait_ref(this, &shifted_rscope, span, + param_mode, trait_def_id, None, trait_segment, @@ -652,6 +674,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, span: Span, + param_mode: PathParamMode, trait_def_id: ast::DefId, self_ty: Option>, trait_segment: &ast::PathSegment, @@ -674,7 +697,7 @@ fn ast_path_to_trait_ref<'a,'tcx>( the crate attributes to enable"); } - convert_angle_bracketed_parameters(this, rscope, path.span, &trait_def.generics, data) + convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data) } ast::ParenthesizedParameters(ref data) => { // For now, require that parenthetical notation be used @@ -688,12 +711,13 @@ fn ast_path_to_trait_ref<'a,'tcx>( the crate attributes to enable"); } - convert_parenthesized_parameters(this, rscope, path.span, &trait_def.generics, data) + convert_parenthesized_parameters(this, rscope, span, &trait_def.generics, data) } }; let substs = create_substs_for_ast_path(this, span, + param_mode, &trait_def.generics, self_ty, types, @@ -830,6 +854,7 @@ fn ast_path_to_ty<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, span: Span, + param_mode: PathParamMode, did: ast::DefId, item_segment: &ast::PathSegment) -> Ty<'tcx> @@ -839,7 +864,9 @@ fn ast_path_to_ty<'tcx>( ty: decl_ty } = this.get_item_type_scheme(did); - let substs = ast_path_substs_for_ty(this, rscope, span, &generics, item_segment); + let substs = ast_path_substs_for_ty(this, rscope, + span, param_mode, + &generics, item_segment); // FIXME(#12938): This is a hack until we have full support for DST. if Some(did) == this.tcx().lang_items.owned_box() { @@ -878,6 +905,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, let trait_ref = object_path_to_poly_trait_ref(this, rscope, path.span, + PathParamMode::Explicit, trait_def_id, path.segments.last().unwrap(), &mut projection_bounds); @@ -950,8 +978,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, -> (Ty<'tcx>, def::Def) { let tcx = this.tcx(); - check_path_args(tcx, span, slice::ref_slice(item_segment), - NO_TPS | NO_REGIONS); + check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); let assoc_name = item_segment.identifier.name; let ty_param_node_id = if let ty::ty_param(_) = ty.sty { @@ -1043,7 +1070,8 @@ fn trait_defines_associated_type_named(this: &AstConv, fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, rscope: &RegionScope, span: Span, - opt_self_ty: Option<&ast::Ty>, + param_mode: PathParamMode, + opt_self_ty: Option>, trait_def_id: ast::DefId, trait_segment: &ast::PathSegment, item_segment: &ast::PathSegment) @@ -1051,11 +1079,10 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, { let tcx = this.tcx(); - check_path_args(tcx, span, slice::ref_slice(item_segment), - NO_TPS | NO_REGIONS); + check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); let self_ty = if let Some(ty) = opt_self_ty { - ast_ty_to_ty(this, rscope, ty) + ty } else { let path_str = ty::item_path_str(tcx, trait_def_id); span_err!(tcx.sess, span, E0223, @@ -1070,6 +1097,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, let trait_ref = ast_path_to_trait_ref(this, rscope, span, + param_mode, trait_def_id, Some(self_ty), trait_segment, @@ -1113,6 +1141,88 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>, } } +pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, + rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, + def: &mut def::Def, + opt_self_ty: Option>, + segments: &[ast::PathSegment], + assoc_segments: &[ast::PathSegment]) + -> Ty<'tcx> { + let tcx = this.tcx(); + + let base_ty = match *def { + def::DefTrait(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 = object_path_to_poly_trait_ref(this, + rscope, + span, + param_mode, + trait_def_id, + segments.last().unwrap(), + &mut projection_bounds); + + check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS); + trait_ref_to_object_type(this, rscope, span, trait_ref, + projection_bounds, &[]) + } + def::DefTy(did, _) | def::DefStruct(did) => { + check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS); + ast_path_to_ty(this, rscope, span, + param_mode, did, + segments.last().unwrap()) + } + def::DefTyParam(space, index, _, name) => { + check_path_args(tcx, segments, NO_TPS | NO_REGIONS); + ty::mk_param(tcx, space, index, name) + } + def::DefSelfTy(_) => { + // n.b.: resolve guarantees that the this type only appears in a + // trait, which we rely upon in various places when creating + // substs + check_path_args(tcx, segments, NO_TPS | NO_REGIONS); + ty::mk_self_type(tcx) + } + def::DefAssociatedTy(trait_did, _) => { + check_path_args(tcx, &segments[..segments.len()-2], NO_TPS | NO_REGIONS); + qpath_to_ty(this, rscope, span, param_mode, + opt_self_ty, trait_did, + &segments[segments.len()-2], + segments.last().unwrap()) + } + def::DefMod(id) => { + tcx.sess.span_bug(span, + &format!("found module name used as a type: {}", + tcx.map.node_to_string(id.node))); + } + def::DefPrimTy(prim_ty) => { + prim_ty_to_ty(tcx, segments, prim_ty) + } + _ => { + span_fatal!(tcx.sess, span, E0248, + "found value name used as a type: {:?}", *def); + } + }; + + // If any associated type segments remain, attempt to resolve them. + let mut ty = base_ty; + for segment in assoc_segments { + if ty.sty == ty::ty_err { + break; + } + // This is pretty bad (it will fail except for T::A and Self::A). + let (a_ty, a_def) = associated_path_def_to_ty(this, span, + ty, *def, segment); + ty = a_ty; + *def = a_def; + } + ty +} + /// Parses the programmer's textual representation of a type into our /// internal notion of a type. pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, @@ -1201,81 +1311,18 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, tcx.sess.span_bug(ast_ty.span, &format!("unbound path {}", ast_ty.repr(tcx))) }; - let (base_def, max_depth) = result; - let span = ast_ty.span; // Could be more granular. - let segments = &path.segments[..path.segments.len()-max_depth]; - let base_ty = match base_def { - def::DefTrait(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 = object_path_to_poly_trait_ref(this, - rscope, - span, - trait_def_id, - segments.last().unwrap(), - &mut projection_bounds); - - check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS); - trait_ref_to_object_type(this, rscope, span, trait_ref, - projection_bounds, &[]) - } - def::DefTy(did, _) | def::DefStruct(did) => { - check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS); - ast_path_to_ty(this, rscope, span, did, segments.last().unwrap()) - } - def::DefTyParam(space, index, _, name) => { - check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS); - ty::mk_param(tcx, space, index, name) - } - def::DefSelfTy(_) => { - // n.b.: resolve guarantees that the this type only appears in a - // trait, which we rely upon in various places when creating - // substs - check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS); - ty::mk_self_type(tcx) - } - def::DefAssociatedTy(trait_did, _) => { - let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { - Some(&*qpath.self_type) - } else { - None - }; - check_path_args(tcx, span, &segments[..segments.len()-2], - NO_TPS | NO_REGIONS); - qpath_to_ty(this, rscope, span, opt_self_ty, trait_did, - &segments[segments.len()-2], - segments.last().unwrap()) - } - def::DefMod(id) => { - tcx.sess.span_bug(span, - &format!("found module name used as a type: {}", - tcx.map.node_to_string(id.node))); - } - def::DefPrimTy(prim_ty) => { - prim_ty_to_ty(tcx, span, segments, prim_ty) - } - _ => { - span_fatal!(tcx.sess, span, E0248, - "found value name used as a type: {:?}", base_def); - } + let (mut def, max_depth) = result; + let base_ty_end = path.segments.len() - max_depth; + let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { + Some(ast_ty_to_ty(this, rscope, &*qpath.self_type)) + } else { + None }; - - // If any associated type segments remain, attempt to resolve them. - let mut ty = base_ty; - let mut def = base_def; - for depth in (0..max_depth).rev() { - if ty.sty == ty::ty_err { - break; - } - // This is pretty bad (it will fail except for T::A and Self::A). - let segment = &path.segments[path.segments.len()-depth-1]; - let (a_ty, a_def) = associated_path_def_to_ty(this, span, - ty, def, segment); - ty = a_ty; - def = a_def; - } + let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span, + PathParamMode::Explicit, &mut def, + opt_self_ty, + &path.segments[..base_ty_end], + &path.segments[base_ty_end..]); if max_depth != 0 && ty.sty != ty::ty_err { // Write back the new resolution. diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 34c52981b794d..edbda795bde3c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -470,7 +470,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, }; instantiate_path(pcx.fcx, - path, + &path.segments, ty::lookup_item_type(tcx, enum_def_id), &ty::lookup_predicates(tcx, enum_def_id), None, @@ -517,7 +517,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } else { ctor_scheme }; - instantiate_path(pcx.fcx, path, path_scheme, &ctor_predicates, None, def, pat.span, pat.id); + instantiate_path(pcx.fcx, &path.segments, + path_scheme, &ctor_predicates, + None, def, pat.span, pat.id); let pat_ty = fcx.node_ty(pat.id); demand::eqtype(fcx, pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 256cd415a33af..488d9d53dbe39 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -14,6 +14,7 @@ use astconv::AstConv; use check::{FnCtxt}; use check::vtable; use check::vtable::select_new_fcx_obligations; +use middle::def; use middle::subst; use middle::traits; use middle::ty::*; @@ -66,7 +67,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, call_expr_id: ast::NodeId) -> bool { - match probe::probe(fcx, span, method_name, self_ty, call_expr_id) { + let mode = probe::Mode::MethodCall; + match probe::probe(fcx, span, mode, method_name, self_ty, call_expr_id) { Ok(..) => true, Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, @@ -103,8 +105,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, call_expr.repr(fcx.tcx()), self_expr.repr(fcx.tcx())); + let mode = probe::Mode::MethodCall; let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty); - let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id)); + let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id)); Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types)) } @@ -301,6 +304,23 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Some(callee) } +pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + span: Span, + method_name: ast::Name, + self_ty: Ty<'tcx>, + expr_id: ast::NodeId) + -> Result +{ + let mode = probe::Mode::Path; + let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id)); + let def_id = pick.method_ty.def_id; + let provenance = match pick.kind { + probe::InherentImplPick(impl_def_id) => def::FromImpl(impl_def_id), + _ => def::FromTrait(pick.method_ty.container.id()) + }; + Ok(def::DefMethod(def_id, provenance)) +} + /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its /// index (or `None`, if no such method). diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 1cc4fe37fbddd..938b7edeef2ff 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -37,6 +37,7 @@ pub use self::PickKind::*; struct ProbeContext<'a, 'tcx:'a> { fcx: &'a FnCtxt<'a, 'tcx>, span: Span, + mode: Mode, method_name: ast::Name, steps: Rc>>, opt_simplified_steps: Option>, @@ -108,17 +109,30 @@ pub enum PickAdjustment { AutoRef(ast::Mutability, Box), } +#[derive(PartialEq, Eq, Copy)] +pub enum Mode { + // An expression of the form `receiver.method_name(...)`. + // Autoderefs are performed on `receiver`, lookup is done based on the + // `self` argument of the method, and static methods aren't considered. + MethodCall, + // An expression of the form `Type::method` or `::method`. + // No autoderefs are performed, lookup is done based on the type each + // implementation is for, and static methods are included. + Path +} + pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, + mode: Mode, method_name: ast::Name, self_ty: Ty<'tcx>, - call_expr_id: ast::NodeId) + scope_expr_id: ast::NodeId) -> PickResult<'tcx> { - debug!("probe(self_ty={}, method_name={}, call_expr_id={})", + debug!("probe(self_ty={}, method_name={}, scope_expr_id={})", self_ty.repr(fcx.tcx()), method_name, - call_expr_id); + scope_expr_id); // FIXME(#18741) -- right now, creating the steps involves evaluating the // `*` operator, which registers obligations that then escape into @@ -127,9 +141,16 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // it ride, although it's really not great, and in fact could I // think cause spurious errors. Really though this part should // take place in the `fcx.infcx().probe` below. - let steps = match create_steps(fcx, span, self_ty) { - Some(steps) => steps, - None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())), + let steps = if mode == Mode::MethodCall { + match create_steps(fcx, span, self_ty) { + Some(steps) => steps, + None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())), + } + } else { + vec![CandidateStep { + self_ty: self_ty, + adjustment: AutoDeref(0) + }] }; // Create a list of simplified self types, if we can. @@ -153,12 +174,15 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // this creates one big transaction so that all type variables etc // that we create during the probe process are removed later - let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures fcx.infcx().probe(|_| { - let (steps, opt_simplified_steps) = dummy.take().unwrap(); - let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps); + let mut probe_cx = ProbeContext::new(fcx, + span, + mode, + method_name, + steps, + opt_simplified_steps); probe_cx.assemble_inherent_candidates(); - try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(call_expr_id)); + try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)); probe_cx.pick() }) } @@ -198,6 +222,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, impl<'a,'tcx> ProbeContext<'a,'tcx> { fn new(fcx: &'a FnCtxt<'a,'tcx>, span: Span, + mode: Mode, method_name: ast::Name, steps: Vec>, opt_simplified_steps: Option>) @@ -206,6 +231,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { ProbeContext { fcx: fcx, span: span, + mode: mode, method_name: method_name, inherent_candidates: Vec::new(), extension_candidates: Vec::new(), @@ -292,11 +318,12 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { return self.record_static_candidate(ImplSource(impl_def_id)); } - let impl_substs = self.impl_substs(impl_def_id); + let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); + let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty); // Determine the receiver type that the method itself expects. let xform_self_ty = - self.xform_self_ty(&method, &impl_substs); + self.xform_self_ty(&method, impl_ty, &impl_substs); self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, @@ -330,7 +357,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { new_trait_ref.def_id, method_num); - let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs); + let xform_self_ty = this.xform_self_ty(&m, + new_trait_ref.self_ty(), + new_trait_ref.substs); this.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, @@ -373,7 +402,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { this.erase_late_bound_regions(&poly_trait_ref); let xform_self_ty = - this.xform_self_ty(&m, trait_ref.substs); + this.xform_self_ty(&m, + trait_ref.self_ty(), + trait_ref.substs); debug!("found match: trait_ref={} substs={} m={}", trait_ref.repr(this.tcx()), @@ -540,7 +571,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { continue; } - let impl_substs = self.impl_substs(impl_def_id); + let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id); debug!("impl_substs={}", impl_substs.repr(self.tcx())); @@ -553,7 +584,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // Determine the receiver type that the method itself expects. let xform_self_ty = - self.xform_self_ty(&method, impl_trait_ref.substs); + self.xform_self_ty(&method, + impl_trait_ref.self_ty(), + impl_trait_ref.substs); debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx())); @@ -630,7 +663,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { &trait_def.generics, step.self_ty); - let xform_self_ty = self.xform_self_ty(&method_ty, &substs); + let xform_self_ty = self.xform_self_ty(&method_ty, + step.self_ty, + &substs); self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, method_ty: method_ty.clone(), @@ -684,7 +719,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { bound.repr(self.tcx())); if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() { - let xform_self_ty = self.xform_self_ty(&method, bound.substs); + let xform_self_ty = self.xform_self_ty(&method, + bound.self_ty(), + bound.substs); debug!("assemble_projection_candidates: bound={} xform_self_ty={}", bound.repr(self.tcx()), @@ -714,7 +751,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { .filter(|b| b.def_id() == trait_def_id) { let bound = self.erase_late_bound_regions(&poly_bound); - let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs); + let xform_self_ty = self.xform_self_ty(&method_ty, + bound.self_ty(), + bound.substs); debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}", bound.repr(self.tcx()), @@ -1023,7 +1062,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // "fast track" -- check for usage of sugar match method.explicit_self { ty::StaticExplicitSelfCategory => { - // fallthrough + if self.mode == Mode::Path { + return true; + } } ty::ByValueExplicitSelfCategory | ty::ByReferenceExplicitSelfCategory(..) | @@ -1047,11 +1088,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn xform_self_ty(&self, method: &Rc>, + impl_ty: Ty<'tcx>, substs: &subst::Substs<'tcx>) -> Ty<'tcx> { - debug!("xform_self_ty(self_ty={}, substs={})", - method.fty.sig.0.inputs[0].repr(self.tcx()), + debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})", + impl_ty.repr(self.tcx()), + method.fty.sig.0.inputs.get(0).repr(self.tcx()), substs.repr(self.tcx())); assert!(!substs.has_escaping_regions()); @@ -1063,6 +1106,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // if there are any. assert_eq!(substs.types.len(subst::FnSpace), 0); assert_eq!(substs.regions().len(subst::FnSpace), 0); + + if self.mode == Mode::Path { + return impl_ty; + } + let placeholder; let mut substs = substs; if @@ -1094,9 +1142,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { xform_self_ty } - fn impl_substs(&self, - impl_def_id: ast::DefId) - -> subst::Substs<'tcx> + /// Get the type of an impl and generate substitutions with placeholders. + fn impl_ty_and_substs(&self, + impl_def_id: ast::DefId) + -> (Ty<'tcx>, subst::Substs<'tcx>) { let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id); @@ -1108,7 +1157,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { impl_pty.generics.regions.map( |_| ty::ReStatic); // see erase_late_bound_regions() for an expl of why 'static - subst::Substs::new(type_vars, region_placeholders) + let substs = subst::Substs::new(type_vars, region_placeholders); + (impl_pty.ty, substs) } /// Replace late-bound-regions bound by `value` with `'static` using diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4daa9a5d80ab0..7a4fab5e56cf0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -82,9 +82,10 @@ pub use self::compare_method::compare_impl_method; use self::IsBinopAssignment::*; use self::TupleArgumentsFlag::*; -use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv}; +use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode}; use check::_match::pat_ctxt; use fmt_macros::{Parser, Piece, Position}; +use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS}; use middle::{const_eval, def}; use middle::infer; use middle::mem_categorization as mc; @@ -1598,26 +1599,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did); - let wants_params = - generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace); - - let needs_defaults = - wants_params && - path.segments.iter().all(|s| s.parameters.is_empty()); - - let substs = if needs_defaults { - let tps = - self.infcx().next_ty_vars(generics.types.len(TypeSpace)); - let rps = - self.infcx().region_vars_for_defs(path.span, - generics.regions.get_slice(TypeSpace)); - Substs::new_type(tps, rps) - } else { - astconv::ast_path_substs_for_ty(self, self, - path.span, - &generics, - path.segments.last().unwrap()) - }; + let substs = astconv::ast_path_substs_for_ty(self, self, + path.span, + PathParamMode::Optional, + &generics, + path.segments.last().unwrap()); let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty); @@ -3604,21 +3590,57 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }; fcx.write_ty(id, oprnd_t); } - ast::ExprPath(ref path) => { - let defn = lookup_def(fcx, path.span, id); - let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id); + ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => { + let opt_self_ty = if let ast::ExprQPath(ref qpath) = expr.node { + Some(fcx.to_ty(&*qpath.self_type)) + } else { + None + }; - // We always require that the type provided as the value for - // a type parameter outlives the moment of instantiation. - constrain_path_type_parameters(fcx, expr); - } - ast::ExprQPath(ref qpath) => { - let self_ty = fcx.to_ty(&*qpath.self_type); - let defn = lookup_def(fcx, expr.span, id); - let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - instantiate_path(fcx, &qpath.path, scheme, &predicates, Some(self_ty), - defn, expr.span, expr.id); + // Helpers to avoid keeping the RefCell borrow for too long. + let get_def = |&:| tcx.def_map.borrow().get(&id).cloned(); + let get_partial_def = |&:| tcx.partial_def_map.borrow().get(&id).cloned(); + + if let Some(def) = get_def() { + let (scheme, predicates) = + type_scheme_and_predicates_for_def(fcx, expr.span, def); + instantiate_path(fcx, &path.segments, + scheme, &predicates, + None, def, expr.span, id); + } else if let Some(partial) = get_partial_def() { + let mut def = partial.base_type; + let ty_segments = path.segments.init(); + let ty_assoc_num = partial.extra_associated_types as usize; + let base_ty_end = ty_segments.len() - ty_assoc_num; + let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span, + PathParamMode::Optional, + &mut def, + opt_self_ty, + &ty_segments[..base_ty_end], + &ty_segments[base_ty_end..]); + let method_segment = path.segments.last().unwrap(); + let method_name = method_segment.identifier.name; + match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) { + Ok(def) => { + // Write back the new resolution. + tcx.def_map.borrow_mut().insert(id, def); + + let (scheme, predicates) = + type_scheme_and_predicates_for_def(fcx, expr.span, def); + instantiate_path(fcx, slice::ref_slice(method_segment), + scheme, &predicates, + Some(ty), def, expr.span, id); + } + Err(error) => { + method::report_error(fcx, expr.span, ty, + method_name, expr, error); + fcx.write_error(id); + } + } + } else { + tcx.sess.span_bug(expr.span, + &format!("unbound path {}", expr.repr(tcx))[]) + } // We always require that the type provided as the value for // a type parameter outlives the moment of instantiation. @@ -4641,7 +4663,6 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefForeignMod(..) | def::DefUse(..) | def::DefRegion(..) | - def::DefTyParamBinder(..) | def::DefLabel(..) | def::DefSelfTy(..) => { fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn)); @@ -4652,15 +4673,15 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - path: &ast::Path, + segments: &[ast::PathSegment], type_scheme: TypeScheme<'tcx>, type_predicates: &ty::GenericPredicates<'tcx>, opt_self_ty: Option>, def: def::Def, span: Span, node_id: ast::NodeId) { - debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})", - path.repr(fcx.tcx()), + debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})", + segments, def.repr(fcx.tcx()), node_id, type_scheme.repr(fcx.tcx())); @@ -4724,7 +4745,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // // The first step then is to categorize the segments appropriately. - assert!(path.segments.len() >= 1); + assert!(segments.len() >= 1); + + // In `>::method`, `A` and `B` are mandatory. + let mut require_type_space = opt_self_ty.is_some(); + let mut segment_spaces: Vec<_>; match def { // Case 1 and 1b. Reference to a *type* or *enum variant*. @@ -4738,7 +4763,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefTyParam(..) => { // Everything but the final segment should have no // parameters at all. - segment_spaces = repeat(None).take(path.segments.len() - 1).collect(); + segment_spaces = repeat(None).take(segments.len() - 1).collect(); segment_spaces.push(Some(subst::TypeSpace)); } @@ -4746,14 +4771,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefFn(..) | def::DefConst(..) | def::DefStatic(..) => { - segment_spaces = repeat(None).take(path.segments.len() - 1).collect(); + segment_spaces = repeat(None).take(segments.len() - 1).collect(); segment_spaces.push(Some(subst::FnSpace)); } // Case 3. Reference to a method. def::DefMethod(_, providence) => { - assert!(path.segments.len() >= 2); - match providence { def::FromTrait(trait_did) => { callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did) @@ -4761,9 +4784,16 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::FromImpl(_) => {} } - segment_spaces = repeat(None).take(path.segments.len() - 2).collect(); - segment_spaces.push(Some(subst::TypeSpace)); - segment_spaces.push(Some(subst::FnSpace)); + if segments.len() >= 2 { + segment_spaces = repeat(None).take(segments.len() - 2).collect(); + segment_spaces.push(Some(subst::TypeSpace)); + segment_spaces.push(Some(subst::FnSpace)); + } else { + // `::method` will end up here, and so can `T::method`. + assert!(opt_self_ty.is_some()); + require_type_space = false; + segment_spaces = vec![Some(subst::FnSpace)]; + } } // Other cases. Various nonsense that really shouldn't show up @@ -4776,10 +4806,10 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefRegion(..) | def::DefLabel(..) | def::DefUpvar(..) => { - segment_spaces = repeat(None).take(path.segments.len()).collect(); + segment_spaces = repeat(None).take(segments.len()).collect(); } } - assert_eq!(segment_spaces.len(), path.segments.len()); + assert_eq!(segment_spaces.len(), segments.len()); debug!("segment_spaces={:?}", segment_spaces); @@ -4793,16 +4823,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // 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(path.segments.iter()) { + for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) { match *opt_space { None => { - report_error_if_segment_contains_type_parameters(fcx, segment); + check_path_args(fcx.tcx(), slice::ref_slice(segment), + NO_TPS | NO_REGIONS); } Some(space) => { push_explicit_parameters_from_segment_to_substs(fcx, space, - path.span, + span, type_defs, region_defs, segment, @@ -4824,7 +4855,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // a problem. for &space in &ParamSpace::all() { adjust_type_parameters(fcx, span, space, type_defs, - opt_self_ty.is_some(), &mut substs); + require_type_space, &mut substs); assert_eq!(substs.types.len(space), type_defs.len(space)); adjust_region_parameters(fcx, span, space, region_defs, &mut substs); @@ -4851,23 +4882,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_substs(node_id, ty::ItemSubsts { substs: substs }); return; - fn report_error_if_segment_contains_type_parameters( - fcx: &FnCtxt, - segment: &ast::PathSegment) - { - for typ in &segment.parameters.types() { - span_err!(fcx.tcx().sess, typ.span, E0085, - "type parameters may not appear here"); - break; - } - - for lifetime in &segment.parameters.lifetimes() { - span_err!(fcx.tcx().sess, lifetime.span, E0086, - "lifetime parameters may not appear here"); - break; - } - } - /// 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. /// diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 46e1f6f076a7b..976c794735fbb 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1684,8 +1684,8 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, -> bool { match ast_ty.node { - ast::TyPath(_, id) => { - match ccx.tcx.def_map.borrow()[id] { + ast::TyPath(_) => { + match ccx.tcx.def_map.borrow()[ast_ty.id] { def::DefTyParam(s, i, _, _) => { space == s && index == i } diff --git a/src/test/compile-fail/issue-3973.rs b/src/test/compile-fail/issue-3973.rs index e4f7521c33303..2652fb5dfc2fd 100644 --- a/src/test/compile-fail/issue-3973.rs +++ b/src/test/compile-fail/issue-3973.rs @@ -30,7 +30,5 @@ impl ToString_ for Point { fn main() { let p = Point::new(0.0, 0.0); - //~^ ERROR unresolved name `Point::new` - //~^^ ERROR failed to resolve. Use of undeclared type or module `Point` println!("{}", p.to_string()); } diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs index dce12030f7942..23d90c5ee292b 100644 --- a/src/test/run-pass/const-polymorphic-paths.rs +++ b/src/test/run-pass/const-polymorphic-paths.rs @@ -77,18 +77,27 @@ tests! { // , (vec![b'f', b'o', b'o'], u8_as_i8); // Trait static methods. + bool::size, fn() -> uint, (); ::size, fn() -> uint, (); + Default::default, fn() -> int, (); + int::default, fn() -> int, (); ::default, fn() -> int, (); + Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); + int::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); ::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); Rand::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); + int::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); ::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); // Trait non-static methods. Clone::clone, fn(&int) -> int, (&5); + int::clone, fn(&int) -> int, (&5); ::clone, fn(&int) -> int, (&5); + FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + Vec::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, @@ -97,9 +106,14 @@ tests! { (Some(5).into_iter()); as FromIterator<_>>::from_iter::>, fn(OptionIter) -> Vec, (Some(5).into_iter()); + Add::add, fn(i32, i32) -> i32, (5, 6); + i32::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); + + String::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, From 6700166442cb88c813e5d3bd39dba3b5f1abc1b0 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 11 Feb 2015 21:01:03 +0200 Subject: [PATCH 13/25] core: fix typo that wasn't caught by the hacky previous implementation. --- src/libcore/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 09089f2d04c5f..48ec13429717c 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -981,7 +981,7 @@ pub trait IteratorExt: Iterator + Sized { #[unstable(feature = "core", reason = "recent addition")] fn cloned(self) -> Cloned where Self::Item: Deref, - ::Output: Clone, + ::Target: Clone, { Cloned { it: self } } From 06f362aeb3c6956bb471fe44de72185dd831eb48 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 20 Feb 2015 08:17:05 +0200 Subject: [PATCH 14/25] rustc_resolve: don't handle impl items as if they were modules. --- src/librustc/middle/ty.rs | 4 + src/librustc_driver/driver.rs | 6 +- src/librustc_privacy/lib.rs | 10 +- src/librustc_resolve/build_reduced_graph.rs | 238 +----------------- src/librustc_resolve/lib.rs | 59 ++--- src/librustc_typeck/check/method/mod.rs | 13 +- src/librustc_typeck/check/method/probe.rs | 5 + src/librustc_typeck/check/method/suggest.rs | 82 +++--- src/librustc_typeck/check/mod.rs | 23 +- src/librustc_typeck/coherence/orphan.rs | 16 +- src/librustc_typeck/diagnostics.rs | 1 + .../compile-fail/bad-mid-path-type-params.rs | 2 +- .../generic-impl-less-params-with-defaults.rs | 2 +- .../generic-impl-more-params-with-defaults.rs | 2 +- .../compile-fail/impl-duplicate-methods.rs | 2 +- src/test/compile-fail/issue-14254.rs | 10 +- src/test/compile-fail/issue-21202.rs | 2 +- src/test/compile-fail/issue-2356.rs | 14 +- src/test/compile-fail/issue-4265.rs | 2 +- .../compile-fail/method-macro-backtrace.rs | 2 +- .../compile-fail/trait-or-new-type-instead.rs | 4 +- src/test/compile-fail/use-from-trait.rs | 2 +- .../impl-not-adjacent-to-type.rs} | 22 +- .../trait-impl-2.rs} | 17 +- 24 files changed, 156 insertions(+), 384 deletions(-) rename src/test/{compile-fail/trait-impl-2.rs => run-pass/impl-not-adjacent-to-type.rs} (53%) rename src/test/{compile-fail/impl-not-adjacent-to-type.rs => run-pass/trait-impl-2.rs} (64%) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c8695ef4ff04a..7dcdeaf16d2e8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -51,6 +51,7 @@ use middle::dependency_format; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem}; use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem}; use middle::mem_categorization as mc; +use middle::privacy::LastPrivateMap; use middle::region; use middle::resolve_lifetime; use middle::infer; @@ -683,6 +684,7 @@ pub struct ctxt<'tcx> { pub sess: Session, pub def_map: DefMap, pub partial_def_map: PartialDefMap, + pub last_private_map: RefCell, pub named_region_map: resolve_lifetime::NamedRegionMap, @@ -2426,6 +2428,7 @@ pub fn mk_ctxt<'tcx>(s: Session, arenas: &'tcx CtxtArenas<'tcx>, def_map: DefMap, partial_def_map: PartialDefMap, + last_private_map: LastPrivateMap, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, freevars: RefCell, @@ -2449,6 +2452,7 @@ pub fn mk_ctxt<'tcx>(s: Session, sess: s, def_map: def_map, partial_def_map: partial_def_map, + last_private_map: RefCell::new(last_private_map), region_maps: region_maps, node_types: RefCell::new(FnvHashMap()), item_substs: RefCell::new(NodeMap()), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b5933ca11bafc..aafa4dec0de94 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -609,6 +609,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, arenas, def_map, partial_def_map, + last_private_map, named_region_map, ast_map, freevars, @@ -622,10 +623,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, time(time_passes, "const checking", (), |_| middle::check_const::check_crate(&ty_cx)); - let maps = (external_exports, last_private_map); let (exported_items, public_items) = - time(time_passes, "privacy checking", maps, |(a, b)| - rustc_privacy::check_crate(&ty_cx, &export_map, a, b)); + time(time_passes, "privacy checking", (), |_| + rustc_privacy::check_crate(&ty_cx, &export_map, external_exports)); // Do not move this check past lint time(time_passes, "stability index", (), |_| diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 439e4331e353a..1452c44ca7144 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -38,8 +38,7 @@ use rustc::middle::def; use rustc::middle::privacy::ImportUse::*; use rustc::middle::privacy::LastPrivate::*; use rustc::middle::privacy::PrivateDep::*; -use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap}; -use rustc::middle::privacy::{ExternalExports}; +use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems}; use rustc::middle::ty::{MethodTypeParam, MethodStatic}; use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam}; use rustc::middle::ty::{MethodStaticClosure, MethodObject}; @@ -379,7 +378,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> { in_foreign: bool, parents: NodeMap, external_exports: ExternalExports, - last_private_map: LastPrivateMap, } enum PrivacyResult { @@ -730,7 +728,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { &format!("{} `{}`", tyname, name)) }; - match self.last_private_map[path_id] { + match self.tcx.last_private_map.borrow()[path_id] { LastMod(AllPublic) => {}, LastMod(DependsOn(def)) => { self.report_error(ck_public(def)); @@ -1500,8 +1498,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { pub fn check_crate(tcx: &ty::ctxt, export_map: &def::ExportMap, - external_exports: ExternalExports, - last_private_map: LastPrivateMap) + external_exports: ExternalExports) -> (ExportedItems, PublicItems) { let krate = tcx.map.krate(); @@ -1519,7 +1516,6 @@ pub fn check_crate(tcx: &ty::ctxt, tcx: tcx, parents: visitor.parents, external_exports: external_exports, - last_private_map: last_private_map, }; visit::walk_crate(&mut visitor, krate); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index abfb226994a53..e4612d6c8b9b3 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -39,18 +39,16 @@ use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn}; use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; -use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; +use syntax::ast::{Name, NamedField, NodeId}; use syntax::ast::{PathListIdent, PathListMod, Public}; use syntax::ast::StmtDecl; use syntax::ast::StructVariantKind; use syntax::ast::TupleVariantKind; -use syntax::ast::TyObjectSum; -use syntax::ast::{TypeImplItem, UnnamedField}; +use syntax::ast::UnnamedField; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; use syntax::ast::{Visibility}; -use syntax::ast::TyPath; use syntax::ast; -use syntax::ast_util::{self, PostExpansionMethod, local_def}; +use syntax::ast_util::{self, local_def}; use syntax::attr::AttrMetaMethods; use syntax::parse::token::{self, special_idents}; use syntax::codemap::{Span, DUMMY_SP}; @@ -177,12 +175,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(TypeNS) } ForbidDuplicateTypesAndModules => { - match child.def_for_namespace(TypeNS) { - None => {} - Some(_) if child.get_module_if_available() - .map(|m| m.kind.get()) == - Some(ImplModuleKind) => {} - Some(_) => duplicate_type = TypeError + if child.defined_in_namespace(TypeNS) { + duplicate_type = TypeError; } Some(TypeNS) } @@ -461,9 +455,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers); let parent_link = self.get_parent_link(parent, name); - // We want to make sure the module type is EnumModuleKind - // even if there's already an ImplModuleKind module defined, - // since that's how we prevent duplicate enum definitions name_bindings.set_module_kind(parent_link, Some(local_def(item.id)), EnumModuleKind, @@ -513,133 +504,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { parent.clone() } - ItemImpl(_, _, _, None, ref ty, ref impl_items) => { - // If this implements an anonymous trait, then add all the - // methods within to a new module, if the type was defined - // within this module. - - let mod_name = match ty.node { - TyPath(ref path) if path.segments.len() == 1 => { - // FIXME(18446) we should distinguish between the name of - // a trait and the name of an impl of that trait. - Some(path.segments.last().unwrap().identifier.name) - } - TyObjectSum(ref lhs_ty, _) => { - match lhs_ty.node { - TyPath(ref path) if path.segments.len() == 1 => { - Some(path.segments.last().unwrap().identifier.name) - } - _ => { - None - } - } - } - _ => { - None - } - }; - - let mod_name = match mod_name { - Some(mod_name) => mod_name, - None => { - self.resolve_error(ty.span, - "inherent implementations may \ - only be implemented in the same \ - module as the type they are \ - implemented for"); - return parent.clone(); - } - }; - // Create the module and add all methods. - let child_opt = parent.children.borrow().get(&mod_name) - .and_then(|m| m.get_module_if_available()); - let new_parent = match child_opt { - // It already exists - Some(ref child) if (child.kind.get() == ImplModuleKind || - child.kind.get() == TraitModuleKind) => { - child.clone() - } - Some(ref child) if child.kind.get() == EnumModuleKind || - child.kind.get() == TypeModuleKind => { - child.clone() - } - // Create the module - _ => { - let name_bindings = - self.add_child(mod_name, parent, ForbidDuplicateModules, sp); - - let parent_link = self.get_parent_link(parent, name); - let def_id = local_def(item.id); - let ns = TypeNS; - let is_public = - !name_bindings.defined_in_namespace(ns) || - name_bindings.defined_in_public_namespace(ns); - - name_bindings.define_module(parent_link, - Some(def_id), - ImplModuleKind, - false, - is_public, - sp); - - name_bindings.get_module() - } - }; - - // For each implementation item... - for impl_item in impl_items { - match *impl_item { - MethodImplItem(ref method) => { - // Add the method to the module. - let name = method.pe_ident().name; - let method_name_bindings = - self.add_child(name, - &new_parent, - ForbidDuplicateValues, - method.span); - let def = DefMethod(local_def(method.id), - FromImpl(local_def(item.id))); - - // NB: not IMPORTABLE - let modifiers = if method.pe_vis() == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - method_name_bindings.define_value( - def, - method.span, - modifiers); - } - TypeImplItem(ref typedef) => { - // Add the typedef to the module. - let name = typedef.ident.name; - let typedef_name_bindings = - self.add_child( - name, - &new_parent, - ForbidDuplicateTypesAndModules, - typedef.span); - let def = DefAssociatedTy(local_def(item.id), - local_def(typedef.id)); - // NB: not IMPORTABLE - let modifiers = if typedef.vis == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - typedef_name_bindings.define_type( - def, - typedef.span, - modifiers); - } - } - } - parent.clone() - } - + ItemImpl(..) => parent.clone(), ItemDefaultImpl(_, _) | - ItemImpl(_, _, _, Some(_), _, _) => parent.clone(), ItemTrait(_, _, _, ref items) => { let name_bindings = @@ -805,8 +671,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let kind = match def { DefTy(_, true) => EnumModuleKind, - DefTy(_, false) => TypeModuleKind, - DefStruct(..) => ImplModuleKind, + DefTy(_, false) | DefStruct(..) => TypeModuleKind, _ => NormalModuleKind }; @@ -980,92 +845,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } } } - DlImpl(def) => { - match csearch::get_type_name_if_impl(&self.session.cstore, def) { - None => {} - Some(final_name) => { - let methods_opt = - csearch::get_methods_if_impl(&self.session.cstore, def); - match methods_opt { - Some(ref methods) if - methods.len() >= 1 => { - debug!("(building reduced graph for \ - external crate) processing \ - static methods for type name {}", - token::get_name(final_name)); - - let child_name_bindings = - self.add_child( - final_name, - root, - OverwriteDuplicates, - DUMMY_SP); - - // Process the static methods. First, - // create the module. - let type_module; - let type_def = child_name_bindings.type_def.borrow().clone(); - match type_def { - Some(TypeNsDef { - module_def: Some(module_def), - .. - }) => { - // We already have a module. This - // is OK. - type_module = module_def; - - // Mark it as an impl module if - // necessary. - type_module.kind.set(ImplModuleKind); - } - Some(_) | None => { - let parent_link = - self.get_parent_link(root, final_name); - child_name_bindings.define_module( - parent_link, - Some(def), - ImplModuleKind, - true, - true, - DUMMY_SP); - type_module = - child_name_bindings. - get_module(); - } - } - - // Add each static method to the module. - let new_parent = type_module; - for method_info in methods { - let name = method_info.name; - debug!("(building reduced graph for \ - external crate) creating \ - static method '{}'", - token::get_name(name)); - - let method_name_bindings = - self.add_child(name, - &new_parent, - OverwriteDuplicates, - DUMMY_SP); - let def = DefFn(method_info.def_id, false); - - // NB: not IMPORTABLE - let modifiers = if method_info.vis == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - method_name_bindings.define_value( - def, DUMMY_SP, modifiers); - } - } - - // Otherwise, do nothing. - Some(_) | None => {} - } - } - } + DlImpl(_) => { + debug!("(building reduced graph for external crate) \ + ignoring impl"); } DlField => { debug!("(building reduced graph for external crate) \ diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0c5236101cfb8..6b05a64874654 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -514,7 +514,6 @@ enum ParentLink { enum ModuleKind { NormalModuleKind, TraitModuleKind, - ImplModuleKind, EnumModuleKind, TypeModuleKind, AnonymousModuleKind, @@ -1863,13 +1862,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match import_resolution.value_target { Some(ref target) if target.shadowable != Shadowable::Always => { if let Some(ref value) = *name_bindings.value_def.borrow() { - let msg = format!("import `{}` conflicts with value \ - in this module", - &token::get_name(name)); - span_err!(self.session, import_span, E0255, "{}", &msg[..]); + span_err!(self.session, import_span, E0255, + "import `{}` conflicts with value in this module", + &token::get_name(name)); if let Some(span) = value.value_span { - self.session.span_note(span, - "conflicting value here"); + self.session.span_note(span, "conflicting value here"); } } } @@ -1879,41 +1876,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match import_resolution.type_target { Some(ref target) if target.shadowable != Shadowable::Always => { if let Some(ref ty) = *name_bindings.type_def.borrow() { - match ty.module_def { - None => { - let msg = format!("import `{}` conflicts with type in \ - this module", - &token::get_name(name)); - span_err!(self.session, import_span, E0256, "{}", &msg[..]); - if let Some(span) = ty.type_span { - self.session.span_note(span, - "note conflicting type here") - } - } - Some(ref module_def) => { - match module_def.kind.get() { - ImplModuleKind => { - if let Some(span) = ty.type_span { - let msg = format!("inherent implementations \ - are only allowed on types \ - defined in the current module"); - span_err!(self.session, span, E0257, "{}", &msg[..]); - self.session.span_note(import_span, - "import from other module here") - } - } - _ => { - let msg = format!("import `{}` conflicts with existing \ - submodule", - &token::get_name(name)); - span_err!(self.session, import_span, E0258, "{}", &msg[..]); - if let Some(span) = ty.type_span { - self.session.span_note(span, - "note conflicting module here") - } - } - } - } + let (what, note) = if ty.module_def.is_some() { + ("existing submodule", "note conflicting module here") + } else { + ("type in this module", "note conflicting type here") + }; + span_err!(self.session, import_span, E0256, + "import `{}` conflicts with {}", + &token::get_name(name), what); + if let Some(span) = ty.type_span { + self.session.span_note(span, note); } } } @@ -2267,7 +2239,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Failed(None); } TraitModuleKind | - ImplModuleKind | EnumModuleKind | TypeModuleKind | AnonymousModuleKind => { @@ -2365,7 +2336,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match new_module.kind.get() { NormalModuleKind => return Some(new_module), TraitModuleKind | - ImplModuleKind | EnumModuleKind | TypeModuleKind | AnonymousModuleKind => module_ = new_module, @@ -2382,7 +2352,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match module_.kind.get() { NormalModuleKind => return module_, TraitModuleKind | - ImplModuleKind | EnumModuleKind | TypeModuleKind | AnonymousModuleKind => { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 488d9d53dbe39..7ef2db2c28d88 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -15,6 +15,7 @@ use check::{FnCtxt}; use check::vtable; use check::vtable::select_new_fcx_obligations; use middle::def; +use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod}; use middle::subst; use middle::traits; use middle::ty::*; @@ -309,16 +310,22 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_name: ast::Name, self_ty: Ty<'tcx>, expr_id: ast::NodeId) - -> Result + -> Result<(def::Def, LastPrivate), MethodError> { let mode = probe::Mode::Path; let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id)); let def_id = pick.method_ty.def_id; + let mut lp = LastMod(AllPublic); let provenance = match pick.kind { - probe::InherentImplPick(impl_def_id) => def::FromImpl(impl_def_id), + probe::InherentImplPick(impl_def_id) => { + if pick.method_ty.vis != ast::Public { + lp = LastMod(DependsOn(def_id)); + } + def::FromImpl(impl_def_id) + } _ => def::FromTrait(pick.method_ty.container.id()) }; - Ok(def::DefMethod(def_id, provenance)) + Ok((def::DefMethod(def_id, provenance), lp)) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 938b7edeef2ff..f24da78bc7d39 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -281,6 +281,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { ty::ty_closure(did, _, _) => { self.assemble_inherent_impl_candidates_for_type(did); } + ty::ty_uniq(_) => { + if let Some(box_did) = self.tcx().lang_items.owned_box() { + self.assemble_inherent_impl_candidates_for_type(box_did); + } + } ty::ty_param(p) => { self.assemble_inherent_candidates_from_param(self_ty, p); } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f5a03f0721a65..9832fe1cb6eac 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -33,7 +33,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, method_name: ast::Name, - callee_expr: &ast::Expr, + rcvr_expr: Option<&ast::Expr>, error: MethodError) { // avoid suggestions when we don't know what's going on. @@ -46,16 +46,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let cx = fcx.tcx(); let method_ustring = method_name.user_string(cx); - // True if the type is a struct and contains a field with - // the same name as the not-found method - let is_field = match rcvr_ty.sty { - ty::ty_struct(did, _) => - ty::lookup_struct_fields(cx, did) - .iter() - .any(|f| f.name.user_string(cx) == method_ustring), - _ => false - }; - fcx.type_error_message( span, |actual| { @@ -68,10 +58,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, None); // If the method has the name of a field, give a help note - if is_field { - cx.sess.span_note(span, - &format!("use `(s.{0})(...)` if you meant to call the \ - function stored in the `{0}` field", method_ustring)); + if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) { + let fields = ty::lookup_struct_fields(cx, did); + if fields.iter().any(|f| f.name == method_name) { + cx.sess.span_note(span, + &format!("use `(s.{0})(...)` if you meant to call the \ + function stored in the `{0}` field", method_ustring)); + } } if static_sources.len() > 0 { @@ -82,7 +75,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, report_candidates(fcx, span, method_name, static_sources); } - suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits) + suggest_traits_to_import(fcx, span, rcvr_ty, method_name, + rcvr_expr, out_of_scope_traits) } MethodError::Ambiguity(sources) => { @@ -93,15 +87,18 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } MethodError::ClosureAmbiguity(trait_def_id) => { - fcx.sess().span_err( - span, - &*format!("the `{}` method from the `{}` trait cannot be explicitly \ - invoked on this closure as we have not yet inferred what \ - kind of closure it is; use overloaded call notation instead \ - (e.g., `{}()`)", - method_name.user_string(fcx.tcx()), - ty::item_path_str(fcx.tcx(), trait_def_id), - pprust::expr_to_string(callee_expr))); + let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \ + invoked on this closure as we have not yet inferred what \ + kind of closure it is", + method_name.user_string(fcx.tcx()), + ty::item_path_str(fcx.tcx(), trait_def_id)); + let msg = if let Some(callee) = rcvr_expr { + format!("{}; use overloaded call notation instead (e.g., `{}()`)", + msg, pprust::expr_to_string(callee)) + } else { + msg + }; + fcx.sess().span_err(span, &msg); } } @@ -156,6 +153,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, method_name: ast::Name, + rcvr_expr: Option<&ast::Expr>, valid_out_of_scope_traits: Vec) { let tcx = fcx.tcx(); @@ -184,7 +182,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, return } - let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty); + let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr); // there's no implemented traits, so lets suggest some traits to // implement, by finding ones that have the method name, and are @@ -233,33 +231,39 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// autoderefs of `rcvr_ty`. fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, - rcvr_ty: Ty<'tcx>) -> bool { - check::autoderef(fcx, span, rcvr_ty, None, - check::UnresolvedTypeAction::Ignore, check::NoPreference, - |&: ty, _| { - let is_local = match ty.sty { + rcvr_ty: Ty<'tcx>, + rcvr_expr: Option<&ast::Expr>) -> bool { + fn is_local(ty: Ty) -> bool { + match ty.sty { ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did), ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()), ty::ty_param(_) => true, - // the user cannot implement traits for unboxed closures, so - // there's no point suggesting anything at all, local or not. - ty::ty_closure(..) => return Some(false), - // everything else (primitive types etc.) is effectively // non-local (there are "edge" cases, e.g. (LocalType,), but // the noise from these sort of types is usually just really // annoying, rather than any sort of help). _ => false - }; - if is_local { - Some(true) + } + } + + // This occurs for UFCS desugaring of `T::method`, where there is no + // receiver expression for the method call, and thus no autoderef. + if rcvr_expr.is_none() { + return is_local(fcx.resolve_type_vars_if_possible(rcvr_ty)); + } + + check::autoderef(fcx, span, rcvr_ty, None, + check::UnresolvedTypeAction::Ignore, check::NoPreference, + |ty, _| { + if is_local(ty) { + Some(()) } else { None } - }).2.unwrap_or(false) + }).2.is_some() } #[derive(Copy)] diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7a4fab5e56cf0..068e03dab120b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -91,6 +91,7 @@ use middle::infer; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::pat_util::{self, pat_id_map}; +use middle::privacy::{AllPublic, LastMod}; use middle::region::{self, CodeExtent}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; use middle::traits; @@ -2687,7 +2688,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } Err(error) => { method::report_error(fcx, method_name.span, expr_t, - method_name.node.name, rcvr, error); + method_name.node.name, Some(rcvr), error); fcx.write_error(expr.id); fcx.tcx().types.err } @@ -3598,8 +3599,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }; // Helpers to avoid keeping the RefCell borrow for too long. - let get_def = |&:| tcx.def_map.borrow().get(&id).cloned(); - let get_partial_def = |&:| tcx.partial_def_map.borrow().get(&id).cloned(); + let get_def = || tcx.def_map.borrow().get(&id).cloned(); + let get_partial_def = || tcx.partial_def_map.borrow().get(&id).cloned(); if let Some(def) = get_def() { let (scheme, predicates) = @@ -3621,10 +3622,16 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let method_segment = path.segments.last().unwrap(); let method_name = method_segment.identifier.name; match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) { - Ok(def) => { + Ok((def, lp)) => { // Write back the new resolution. tcx.def_map.borrow_mut().insert(id, def); + if let LastMod(AllPublic) = lp { + // Public method, don't change the last private entry. + } else { + tcx.last_private_map.borrow_mut().insert(id, lp); + } + let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, def); instantiate_path(fcx, slice::ref_slice(method_segment), @@ -3633,7 +3640,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } Err(error) => { method::report_error(fcx, expr.span, ty, - method_name, expr, error); + method_name, None, error); fcx.write_error(id); } } @@ -4842,9 +4849,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } if let Some(self_ty) = opt_self_ty { - // `::foo` shouldn't have resolved to a `Self`-less item. - assert_eq!(type_defs.len(subst::SelfSpace), 1); - substs.types.push(subst::SelfSpace, self_ty); + if type_defs.len(subst::SelfSpace) == 1 { + substs.types.push(subst::SelfSpace, self_ty); + } } // Now we have to compare the types that the user *actually* diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index d34a16a924f70..34fadc70af8b7 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -15,8 +15,8 @@ use middle::traits; use middle::ty; use syntax::ast::{Item, ItemImpl}; use syntax::ast; +use syntax::ast_map; use syntax::ast_util; -use syntax::codemap::Span; use syntax::visit; use util::ppaux::{Repr, UserString}; @@ -30,9 +30,9 @@ struct OrphanChecker<'cx, 'tcx:'cx> { } impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { - fn check_def_id(&self, span: Span, def_id: ast::DefId) { + fn check_def_id(&self, item: &ast::Item, def_id: ast::DefId) { if def_id.krate != ast::LOCAL_CRATE { - span_err!(self.tcx.sess, span, E0116, + span_err!(self.tcx.sess, item.span, E0116, "cannot associate methods with a type outside the \ crate the type is defined in; define and implement \ a trait or new type instead"); @@ -41,7 +41,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { } impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { - fn visit_item(&mut self, item: &'v ast::Item) { + fn visit_item(&mut self, item: &ast::Item) { let def_id = ast_util::local_def(item.id); match item.node { ast::ItemImpl(_, _, _, None, _, _) => { @@ -52,15 +52,13 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { match self_ty.sty { ty::ty_enum(def_id, _) | ty::ty_struct(def_id, _) => { - self.check_def_id(item.span, def_id); + self.check_def_id(item, def_id); } ty::ty_trait(ref data) => { - self.check_def_id(item.span, data.principal_def_id()); + self.check_def_id(item, data.principal_def_id()); } ty::ty_uniq(..) => { - self.check_def_id(item.span, - self.tcx.lang_items.owned_box() - .unwrap()); + self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap()); } _ => { span_err!(self.tcx.sess, item.span, E0118, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6f363faef6039..7b43a9fef06dc 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -80,6 +80,7 @@ register_diagnostics! { E0120, E0121, E0122, + E0123, E0124, E0127, E0128, diff --git a/src/test/compile-fail/bad-mid-path-type-params.rs b/src/test/compile-fail/bad-mid-path-type-params.rs index 3e02a11c378bd..7a7406115d393 100644 --- a/src/test/compile-fail/bad-mid-path-type-params.rs +++ b/src/test/compile-fail/bad-mid-path-type-params.rs @@ -43,7 +43,7 @@ fn foo<'a>() { //~^ ERROR too many type parameters provided let _ = S::<'a,isize>::new::(1, 1.0); - //~^ ERROR too many lifetime parameters provided + //~^ ERROR wrong number of lifetime parameters let _: S2 = Trait::new::(1, 1.0); //~^ ERROR too many type parameters provided diff --git a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs index 9fea5e609d1f4..5fa429445a35e 100644 --- a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs @@ -19,5 +19,5 @@ impl Foo { fn main() { Foo::::new(); - //~^ ERROR too few type parameters provided + //~^ ERROR wrong number of type arguments } diff --git a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs index 73c19aa012dcf..d3babb8982ddc 100644 --- a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs @@ -21,5 +21,5 @@ impl Vec { fn main() { Vec::::new(); - //~^ ERROR too many type parameters provided + //~^ ERROR wrong number of type arguments } diff --git a/src/test/compile-fail/impl-duplicate-methods.rs b/src/test/compile-fail/impl-duplicate-methods.rs index c6ce4d04e1086..c0c951dd8b108 100644 --- a/src/test/compile-fail/impl-duplicate-methods.rs +++ b/src/test/compile-fail/impl-duplicate-methods.rs @@ -11,7 +11,7 @@ struct Foo; impl Foo { fn orange(&self){} - fn orange(&self){} //~ ERROR error: duplicate definition of value `orange` + fn orange(&self){} //~ ERROR error: duplicate method in trait impl } fn main() {} diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs index 74eea0c57a01a..ce5fa1f1fe1a5 100644 --- a/src/test/compile-fail/issue-14254.rs +++ b/src/test/compile-fail/issue-14254.rs @@ -29,7 +29,7 @@ impl Foo for *const BarTy { baz(); //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? a; - //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + //~^ ERROR: unresolved name `a` } } @@ -42,11 +42,11 @@ impl<'a> Foo for &'a BarTy { y; //~^ ERROR: unresolved name `y`. Did you mean `self.y`? a; - //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + //~^ ERROR: unresolved name `a` bah; //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? b; - //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`? + //~^ ERROR: unresolved name `b` } } @@ -59,11 +59,11 @@ impl<'a> Foo for &'a mut BarTy { y; //~^ ERROR: unresolved name `y`. Did you mean `self.y`? a; - //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + //~^ ERROR: unresolved name `a` bah; //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? b; - //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`? + //~^ ERROR: unresolved name `b` } } diff --git a/src/test/compile-fail/issue-21202.rs b/src/test/compile-fail/issue-21202.rs index 5c1de6dfc55b4..05485008e51fd 100644 --- a/src/test/compile-fail/issue-21202.rs +++ b/src/test/compile-fail/issue-21202.rs @@ -18,7 +18,7 @@ mod B { use crate1::A::Foo; fn bar(f: Foo) { Foo::foo(&f); - //~^ ERROR: function `foo` is private + //~^ ERROR: method `foo` is private } } diff --git a/src/test/compile-fail/issue-2356.rs b/src/test/compile-fail/issue-2356.rs index f0ae0eb59f532..48cc27e228940 100644 --- a/src/test/compile-fail/issue-2356.rs +++ b/src/test/compile-fail/issue-2356.rs @@ -36,7 +36,7 @@ impl Groom for cat { shave(4); //~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`? purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` } } @@ -45,13 +45,13 @@ impl cat { fn purr_louder() { static_method(); - //~^ ERROR: unresolved name `static_method`. Did you mean to call `cat::static_method` + //~^ ERROR: unresolved name `static_method` purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` } } @@ -65,7 +65,7 @@ impl cat { fn purr(&self) { grow_older(); - //~^ ERROR: unresolved name `grow_older`. Did you mean to call `cat::grow_older` + //~^ ERROR: unresolved name `grow_older` shave(); //~^ ERROR: unresolved name `shave` } @@ -79,7 +79,7 @@ impl cat { whiskers = 4; //~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`? purr_louder(); - //~^ ERROR: unresolved name `purr_louder`. Did you mean to call `cat::purr_louder` + //~^ ERROR: unresolved name `purr_louder` } } diff --git a/src/test/compile-fail/issue-4265.rs b/src/test/compile-fail/issue-4265.rs index b4bc7ecdc5f89..ab18e0bcddcf0 100644 --- a/src/test/compile-fail/issue-4265.rs +++ b/src/test/compile-fail/issue-4265.rs @@ -17,7 +17,7 @@ impl Foo { Foo { baz: 0 }.bar(); } - fn bar() { //~ ERROR duplicate definition of value `bar` + fn bar() { //~ ERROR duplicate method in trait impl } } diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index f4740492651ae..c9ef2df8e1326 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -29,7 +29,7 @@ impl S { // Cause an error. It shouldn't have any macro backtrace frames. fn bar(&self) { } - fn bar(&self) { } //~ ERROR duplicate definition + fn bar(&self) { } //~ ERROR duplicate method } fn main() { } diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs index 047e4e50c8223..3aec23a55b811 100644 --- a/src/test/compile-fail/trait-or-new-type-instead.rs +++ b/src/test/compile-fail/trait-or-new-type-instead.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME(eddyb/UFCS) This should have a nicer error, but that's not possible just yet. -impl Option { //~ ERROR use of undeclared type name `Option` +impl Option { +//~^ ERROR cannot associate methods with a type outside the crate the type is defined in pub fn foo(&self) { } } diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs index 2a97155dd2efb..49d8622976bb2 100644 --- a/src/test/compile-fail/use-from-trait.rs +++ b/src/test/compile-fail/use-from-trait.rs @@ -11,7 +11,7 @@ use Trait::foo; //~^ ERROR `foo` is not directly importable use Foo::new; -//~^ ERROR `new` is not directly importable +//~^ ERROR unresolved import `Foo::new`. Not a module `Foo` pub trait Trait { fn foo(); diff --git a/src/test/compile-fail/trait-impl-2.rs b/src/test/run-pass/impl-not-adjacent-to-type.rs similarity index 53% rename from src/test/compile-fail/trait-impl-2.rs rename to src/test/run-pass/impl-not-adjacent-to-type.rs index 303e3d937444d..c1dc68b245655 100644 --- a/src/test/compile-fail/trait-impl-2.rs +++ b/src/test/run-pass/impl-not-adjacent-to-type.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,17 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test calling methods on an impl for a bare trait. This test checks trait impls -// must be in the same module as the trait. - -mod Foo { - trait T {} +mod foo { + pub struct Point { + pub x: i32, + pub y: i32, + } } -mod Bar { - impl<'a> ::Foo::T+'a { //~ERROR: inherent implementations may only be implemented in the same - fn foo(&self) {} - } +impl foo::Point { + fn x(&self) -> i32 { self.x } } -fn main() {} +fn main() { + assert_eq!((foo::Point { x: 1, y: 3}).x(), 1); +} diff --git a/src/test/compile-fail/impl-not-adjacent-to-type.rs b/src/test/run-pass/trait-impl-2.rs similarity index 64% rename from src/test/compile-fail/impl-not-adjacent-to-type.rs rename to src/test/run-pass/trait-impl-2.rs index 7a7673d871d75..727c33d6ce56f 100644 --- a/src/test/compile-fail/impl-not-adjacent-to-type.rs +++ b/src/test/run-pass/trait-impl-2.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,17 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -mod foo { - pub struct Foo { - x: isize, - y: isize, +mod Foo { + trait Trait { + fn foo(&self); } } -impl foo::Foo { -//~^ ERROR implementations may only be implemented in the same module - fn bar() {} +mod Bar { + impl<'a> ::Foo::Trait+'a { + fn bar(&self) { self.foo() } + } } fn main() {} - From 5a6a9ed792dd2a716ef583a50051a52a17574efc Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 17 Feb 2015 06:44:23 +0200 Subject: [PATCH 15/25] rustc: combine partial_def_map and last_private_map into def_map. --- src/librustc/lint/builtin.rs | 25 +- src/librustc/metadata/encoder.rs | 4 +- src/librustc/middle/astconv_util.rs | 2 +- src/librustc/middle/astencode.rs | 12 +- src/librustc/middle/cfg/construct.rs | 38 +- src/librustc/middle/check_const.rs | 4 +- src/librustc/middle/check_match.rs | 30 +- src/librustc/middle/check_static_recursion.rs | 6 +- src/librustc/middle/const_eval.rs | 10 +- src/librustc/middle/dead.rs | 10 +- src/librustc/middle/def.rs | 48 +- src/librustc/middle/expr_use_visitor.rs | 14 +- src/librustc/middle/infer/error_reporting.rs | 2 +- src/librustc/middle/liveness.rs | 10 +- src/librustc/middle/mem_categorization.rs | 13 +- src/librustc/middle/pat_util.rs | 12 +- src/librustc/middle/privacy.rs | 5 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 4 +- src/librustc/middle/stability.rs | 14 +- src/librustc/middle/ty.rs | 21 +- src/librustc_driver/driver.rs | 4 - src/librustc_privacy/lib.rs | 26 +- src/librustc_resolve/check_unused.rs | 28 +- src/librustc_resolve/lib.rs | 412 +++++++++--------- src/librustc_trans/save/mod.rs | 18 +- src/librustc_trans/trans/_match.rs | 20 +- src/librustc_trans/trans/common.rs | 2 +- src/librustc_trans/trans/consts.rs | 8 +- src/librustc_trans/trans/controlflow.rs | 9 +- src/librustc_trans/trans/expr.rs | 2 +- src/librustc_typeck/astconv.rs | 20 +- src/librustc_typeck/check/_match.rs | 6 +- src/librustc_typeck/check/mod.rs | 42 +- src/librustc_typeck/lib.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 4 +- src/librustdoc/visit_ast.rs | 2 +- 38 files changed, 444 insertions(+), 449 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 8c6984972718f..28baeb5dc9e62 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -406,7 +406,7 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_def(&mut self, sp: Span, id: ast::NodeId) { - match self.cx.tcx.def_map.borrow()[id].clone() { + match self.cx.tcx.def_map.borrow()[id].full_def() { def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => { self.cx.span_lint(IMPROPER_CTYPES, sp, "found rust type `isize` in foreign module, while \ @@ -1000,7 +1000,8 @@ impl LintPass for NonSnakeCase { fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { if let &ast::PatIdent(_, ref path1, _) = &p.node { - if let Some(&def::DefLocal(_)) = cx.tcx.def_map.borrow().get(&p.id) { + let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); + if let Some(def::DefLocal(_)) = def { self.check_snake_case(cx, "variable", path1.node, p.span); } } @@ -1065,8 +1066,8 @@ impl LintPass for NonUpperCaseGlobals { fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { // Lint for constants that look like binding identifiers (#7526) - match (&p.node, cx.tcx.def_map.borrow().get(&p.id)) { - (&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => { + match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) { + (&ast::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => { NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", path1.node, p.span); } @@ -1226,10 +1227,13 @@ impl LintPass for NonShorthandFieldPatterns { fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { let def_map = cx.tcx.def_map.borrow(); if let ast::PatStruct(_, ref v, _) = pat.node { - for fieldpat in v.iter() - .filter(|fieldpat| !fieldpat.node.is_shorthand) - .filter(|fieldpat| def_map.get(&fieldpat.node.pat.id) - == Some(&def::DefLocal(fieldpat.node.pat.id))) { + let field_pats = v.iter() + .filter(|fieldpat| !fieldpat.node.is_shorthand) + .filter(|fieldpat| { + let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def()); + def == Some(def::DefLocal(fieldpat.node.pat.id)) + }); + for fieldpat in field_pats { if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node { if ident.node.as_str() == fieldpat.node.ident.as_str() { cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, @@ -1908,10 +1912,7 @@ impl LintPass for UnconditionalRecursion { _: ast::Ident, id: ast::NodeId) -> bool { tcx.def_map.borrow().get(&id) - .map_or(false, |def| { - let did = def.def_id(); - ast_util::is_local(did) && did.node == fn_id - }) + .map_or(false, |def| def.def_id() == ast_util::local_def(fn_id)) } // check if the method call `id` refers to method `method_id` diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 1a695baf7216b..4aea73cfb0ec0 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1870,9 +1870,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> { impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> { fn visit_item(&mut self, item: &ast::Item) { if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node { - let def_map = &self.ecx.tcx.def_map; - let trait_def = def_map.borrow()[trait_ref.ref_id].clone(); - let def_id = trait_def.def_id(); + let def_id = self.ecx.tcx.def_map.borrow()[trait_ref.ref_id].def_id(); // Load eagerly if this is an implementation of the Drop trait // or if the trait is not defined in this crate. diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index 1cd5a19d6788a..c9196f0cb2a64 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -65,7 +65,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) tcx.sess.span_bug(ast_ty.span, &format!("unbound path {}", path.repr(tcx))) } - Some(&d) => d + Some(d) => d.full_def() }; if let def::DefPrimTy(nty) = def { Some(prim_ty_to_ty(tcx, &path.segments[], nty)) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 3de29a4ca538a..5983829ed8fbe 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -25,6 +25,7 @@ use metadata::tydecode::{RegionParameter, ClosureSource}; use metadata::tyencode; use middle::check_const::ConstQualif; use middle::mem_categorization::Typer; +use middle::privacy::{AllPublic, LastMod}; use middle::subst; use middle::subst::VecPerParamSpace; use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin}; @@ -1148,10 +1149,10 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, debug!("Encoding side tables for id {}", id); - if let Some(def) = tcx.def_map.borrow().get(&id) { + if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) { rbml_w.tag(c::tag_table_def, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| (*def).encode(rbml_w).unwrap()); + rbml_w.tag(c::tag_table_val, |rbml_w| def.encode(rbml_w).unwrap()); }) } @@ -1851,7 +1852,12 @@ fn decode_side_tables(dcx: &DecodeContext, match value { c::tag_table_def => { let def = decode_def(dcx, val_doc); - dcx.tcx.def_map.borrow_mut().insert(id, def); + dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution { + base_def: def, + // This doesn't matter cross-crate. + last_private: LastMod(AllPublic), + depth: 0 + }); } c::tag_table_node_type => { let ty = val_dsr.read_ty(dcx); diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 52eedc460eb87..ca9455ac421f2 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -610,32 +610,24 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn find_scope(&self, expr: &ast::Expr, label: Option) -> LoopScope { - match label { - None => { - return *self.loop_scopes.last().unwrap(); - } - - Some(_) => { - match self.tcx.def_map.borrow().get(&expr.id) { - Some(&def::DefLabel(loop_id)) => { - for l in &self.loop_scopes { - if l.loop_id == loop_id { - return *l; - } - } - self.tcx.sess.span_bug( - expr.span, - &format!("no loop scope for id {}", - loop_id)); - } + if label.is_none() { + return *self.loop_scopes.last().unwrap(); + } - r => { - self.tcx.sess.span_bug( - expr.span, - &format!("bad entry `{:?}` in def_map for label", - r)); + match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { + Some(def::DefLabel(loop_id)) => { + for l in &self.loop_scopes { + if l.loop_id == loop_id { + return *l; } } + self.tcx.sess.span_bug(expr.span, + &format!("no loop scope for id {}", loop_id)); + } + + r => { + self.tcx.sess.span_bug(expr.span, + &format!("bad entry `{:?}` in def_map for label", r)); } } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 0d7e730b5cdd8..57e4d3d2f0203 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -440,7 +440,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } } ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = v.tcx.def_map.borrow().get(&e.id).cloned(); + let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); match def { Some(def::DefVariant(_, _, _)) => { // Count the discriminator or function pointer. @@ -499,7 +499,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, _ => break }; } - let def = v.tcx.def_map.borrow().get(&callee.id).cloned(); + let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); match def { Some(def::DefStruct(..)) => {} Some(def::DefVariant(..)) => { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 7bd64a4f487d6..c409c8fb13f14 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -242,7 +242,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => { let pat_ty = ty::pat_ty(cx.tcx, p); if let ty::ty_enum(def_id, _) = pat_ty.sty { - let def = cx.tcx.def_map.borrow().get(&p.id).cloned(); + let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); if let Some(DefLocal(_)) = def { if ty::enum_variants(cx.tcx, def_id).iter().any(|variant| token::get_name(variant.name) == token::get_name(ident.node.name) @@ -434,7 +434,7 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { fn fold_pat(&mut self, pat: P) -> P { return match pat.node { ast::PatIdent(..) | ast::PatEnum(..) => { - let def = self.tcx.def_map.borrow().get(&pat.id).cloned(); + let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()); match def { Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) { Some(const_expr) => { @@ -733,28 +733,28 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, let pat = raw_pat(p); match pat.node { ast::PatIdent(..) => - match cx.tcx.def_map.borrow().get(&pat.id) { - Some(&DefConst(..)) => + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => cx.tcx.sess.span_bug(pat.span, "const pattern should've \ been rewritten"), - Some(&DefStruct(_)) => vec!(Single), - Some(&DefVariant(_, id, _)) => vec!(Variant(id)), + Some(DefStruct(_)) => vec!(Single), + Some(DefVariant(_, id, _)) => vec!(Variant(id)), _ => vec!() }, ast::PatEnum(..) => - match cx.tcx.def_map.borrow().get(&pat.id) { - Some(&DefConst(..)) => + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => cx.tcx.sess.span_bug(pat.span, "const pattern should've \ been rewritten"), - Some(&DefVariant(_, id, _)) => vec!(Variant(id)), + Some(DefVariant(_, id, _)) => vec!(Variant(id)), _ => vec!(Single) }, ast::PatStruct(..) => - match cx.tcx.def_map.borrow().get(&pat.id) { - Some(&DefConst(..)) => + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => cx.tcx.sess.span_bug(pat.span, "const pattern should've \ been rewritten"), - Some(&DefVariant(_, id, _)) => vec!(Variant(id)), + Some(DefVariant(_, id, _)) => vec!(Variant(id)), _ => vec!(Single) }, ast::PatLit(ref expr) => @@ -847,7 +847,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], Some(repeat(DUMMY_WILD_PAT).take(arity).collect()), ast::PatIdent(_, _, _) => { - let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned(); + let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def()); match opt_def { Some(DefConst(..)) => cx.tcx.sess.span_bug(pat_span, "const pattern should've \ @@ -862,7 +862,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], } ast::PatEnum(_, ref args) => { - let def = cx.tcx.def_map.borrow()[pat_id].clone(); + let def = cx.tcx.def_map.borrow()[pat_id].full_def(); match def { DefConst(..) => cx.tcx.sess.span_bug(pat_span, "const pattern should've \ @@ -880,7 +880,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], ast::PatStruct(_, ref pattern_fields, _) => { // Is this a struct or an enum variant? - let def = cx.tcx.def_map.borrow()[pat_id].clone(); + let def = cx.tcx.def_map.borrow()[pat_id].full_def(); let class_id = match def { DefConst(..) => cx.tcx.sess.span_bug(pat_span, "const pattern should've \ diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index 4280b7fe3f096..a4393f4648b1e 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -94,9 +94,9 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { ast::ExprPath(_) | ast::ExprQPath(_) => { - match self.def_map.borrow().get(&e.id) { - Some(&DefStatic(def_id, _)) | - Some(&DefConst(def_id)) if + match self.def_map.borrow().get(&e.id).map(|d| d.full_def()) { + Some(DefStatic(def_id, _)) | + Some(DefConst(def_id)) if ast_util::is_local(def_id) => { match self.ast_map.get(def_id.node) { ast_map::NodeItem(item) => diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 5bf7422dbc0d4..d3c6a585fa3fd 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -31,7 +31,7 @@ use std::{i8, i16, i32, i64}; use std::rc::Rc; fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> { - let opt_def = tcx.def_map.borrow().get(&e.id).cloned(); + let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); match opt_def { Some(def::DefConst(def_id)) => { lookup_const_by_id(tcx, def_id) @@ -148,11 +148,11 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()), ast::ExprCall(ref callee, ref args) => { - let def = tcx.def_map.borrow()[callee.id].clone(); + let def = tcx.def_map.borrow()[callee.id]; if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) { entry.insert(def); } - let path = match def { + let path = match def.full_def() { def::DefStruct(def_id) => def_to_path(tcx, def_id), def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did), _ => unreachable!() @@ -179,7 +179,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P } ast::ExprPath(ref path) => { - let opt_def = tcx.def_map.borrow().get(&expr.id).cloned(); + let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()); match opt_def { Some(def::DefStruct(..)) => ast::PatStruct(path.clone(), vec![], false), @@ -389,7 +389,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, cast_const(val, ety) } ast::ExprPath(_) | ast::ExprQPath(_) => { - let opt_def = tcx.def_map.borrow().get(&e.id).cloned(); + let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); let (const_expr, const_ty) = match opt_def { Some(def::DefConst(def_id)) => { if ast_util::is_local(def_id) { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index ff78deb8d12ea..2d837ce52b56a 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -71,13 +71,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) { self.tcx.def_map.borrow().get(id).map(|def| { - match def { - &def::DefConst(_) => { + match def.full_def() { + def::DefConst(_) => { self.check_def_id(def.def_id()) } _ if self.ignore_non_const_paths => (), - &def::DefPrimTy(_) => (), - &def::DefVariant(enum_id, variant_id, _) => { + def::DefPrimTy(_) => (), + def::DefVariant(enum_id, variant_id, _) => { self.check_def_id(enum_id); self.check_def_id(variant_id); } @@ -158,7 +158,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[codemap::Spanned]) { - let id = match (*self.tcx.def_map.borrow())[lhs.id] { + let id = match self.tcx.def_map.borrow()[lhs.id].full_def() { def::DefVariant(_, id, _) => id, _ => { match ty::ty_to_def_id(ty::node_id_to_type(self.tcx, diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 355c52b374e01..1a054c0f464aa 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -11,6 +11,7 @@ pub use self::Def::*; pub use self::MethodProvenance::*; +use middle::privacy::LastPrivate; use middle::subst::ParamSpace; use util::nodemap::NodeMap; use syntax::ast; @@ -51,24 +52,43 @@ pub enum Def { DefMethod(ast::DefId /* method */, MethodProvenance), } -/// The result of resolving the prefix of a path to a type: +/// The result of resolving a path. +/// Before type checking completes, `depth` represents the number of +/// trailing segments which are yet unresolved. Afterwards, if there +/// were no errors, all paths should be fully resolved, with `depth` +/// set to `0` and `base_def` representing the final resolution. /// -/// module::Type::AssocA::AssocB::AssocC::MethodOrAssocType -/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~ -/// base_type extra_associated_types +/// module::Type::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_def depth = 3 /// -/// ::AssocA::AssocB::AssocC::MethodOrAssocType -/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~ -/// base_type extra_associated_types -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct PartialDef { - pub base_type: Def, - pub extra_associated_types: u32, +/// ::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_def depth = 2 +#[derive(Copy, Debug)] +pub struct PathResolution { + pub base_def: Def, + pub last_private: LastPrivate, + pub depth: usize +} + +impl PathResolution { + /// Get the definition, if fully resolved, otherwise panic. + pub fn full_def(&self) -> Def { + if self.depth != 0 { + panic!("path not fully resolved: {:?}", self); + } + self.base_def + } + + /// Get the DefId, if fully resolved, otherwise panic. + pub fn def_id(&self) -> ast::DefId { + self.full_def().def_id() + } } // Definition mapping -pub type DefMap = RefCell>; -pub type PartialDefMap = RefCell>; +pub type DefMap = RefCell>; // This is the replacement export map. It maps a module to all of the exports // within. pub type ExportMap = NodeMap>; @@ -119,7 +139,7 @@ impl Def { local_def(id) } - DefPrimTy(_) => panic!() + DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy") } } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 625093e3c5dea..f7c723c68746f 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -1017,7 +1017,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // Each match binding is effectively an assignment to the // binding being produced. - let def = def_map.borrow()[pat.id].clone(); + let def = def_map.borrow()[pat.id].full_def(); match mc.cat_def(pat.id, pat.span, pat_ty, def) { Ok(binding_cmt) => { delegate.mutate(pat.id, pat.span, binding_cmt, Init); @@ -1097,13 +1097,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { match pat.node { ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => { - match def_map.get(&pat.id) { + match def_map.get(&pat.id).map(|d| d.full_def()) { None => { // no definition found: pat is not a // struct or enum pattern. } - Some(&def::DefVariant(enum_did, variant_did, _is_struct)) => { + Some(def::DefVariant(enum_did, variant_did, _is_struct)) => { let downcast_cmt = if ty::enum_is_univariant(tcx, enum_did) { cmt_pat @@ -1119,7 +1119,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { delegate.matched_pat(pat, downcast_cmt, match_mode); } - Some(&def::DefStruct(..)) | Some(&def::DefTy(_, false)) => { + Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => { // A struct (in either the value or type // namespace; we encounter the former on // e.g. patterns for unit structs). @@ -1131,14 +1131,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { delegate.matched_pat(pat, cmt_pat, match_mode); } - Some(&def::DefConst(..)) | - Some(&def::DefLocal(..)) => { + Some(def::DefConst(..)) | + Some(def::DefLocal(..)) => { // This is a leaf (i.e. identifier binding // or constant value to match); thus no // `matched_pat` call. } - Some(def @ &def::DefTy(_, true)) => { + Some(def @ def::DefTy(_, true)) => { // An enum's type -- should never be in a // pattern. diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 4439472ab5671..60b7e1169b49b 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1242,7 +1242,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { "unbound path {}", pprust::path_to_string(path))) } - Some(&d) => d + Some(d) => d.full_def() }; match a_def { def::DefTy(did, _) | def::DefStruct(did) => { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 145fccd7972bb..4685a05f41604 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -446,7 +446,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { match expr.node { // live nodes required for uses or definitions of variables: ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = ir.tcx.def_map.borrow()[expr.id].clone(); + let def = ir.tcx.def_map.borrow()[expr.id].full_def(); debug!("expr {}: path that leads to {:?}", expr.id, def); if let DefLocal(..) = def { ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); @@ -705,8 +705,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { Some(_) => { // Refers to a labeled loop. Use the results of resolve // to find with one - match self.ir.tcx.def_map.borrow().get(&id) { - Some(&DefLabel(loop_id)) => loop_id, + match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) { + Some(DefLabel(loop_id)) => loop_id, _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \ doesn't refer to a loop") } @@ -1300,7 +1300,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint) -> LiveNode { - match self.ir.tcx.def_map.borrow()[expr.id].clone() { + match self.ir.tcx.def_map.borrow()[expr.id].full_def() { DefLocal(nid) => { let ln = self.live_node(expr.id, expr.span); if acc != 0 { @@ -1562,7 +1562,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_lvalue(&mut self, expr: &Expr) { match expr.node { ast::ExprPath(_) | ast::ExprQPath(_) => { - if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() { + if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually // mutable, then check for a reassignment to flag the mutability diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index f8065f81aa8d8..44ab3cf60aaa3 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -530,7 +530,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = (*self.tcx().def_map.borrow())[expr.id]; + let def = self.tcx().def_map.borrow()[expr.id].full_def(); self.cat_def(expr.id, expr.span, expr_ty, def) } @@ -1199,14 +1199,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { (*op)(self, cmt.clone(), pat); - let def_map = self.tcx().def_map.borrow(); - let opt_def = def_map.get(&pat.id); + let opt_def = self.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def()); // Note: This goes up here (rather than within the PatEnum arm // alone) because struct patterns can refer to struct types or // to struct variants within enums. let cmt = match opt_def { - Some(&def::DefVariant(enum_did, variant_did, _)) + Some(def::DefVariant(enum_did, variant_did, _)) // univariant enums do not need downcasts if !ty::enum_is_univariant(self.tcx(), enum_did) => { self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) @@ -1224,7 +1223,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } ast::PatEnum(_, Some(ref subpats)) => { match opt_def { - Some(&def::DefVariant(..)) => { + Some(def::DefVariant(..)) => { // variant(x, y, z) for (i, subpat) in subpats.iter().enumerate() { let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) @@ -1237,7 +1236,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { try!(self.cat_pattern_(subcmt, &**subpat, op)); } } - Some(&def::DefStruct(..)) => { + Some(def::DefStruct(..)) => { for (i, subpat) in subpats.iter().enumerate() { let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) let cmt_field = @@ -1247,7 +1246,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { try!(self.cat_pattern_(cmt_field, &**subpat, op)); } } - Some(&def::DefConst(..)) => { + Some(def::DefConst(..)) => { for subpat in subpats { try!(self.cat_pattern_(cmt.clone(), &**subpat, op)); } diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index a7df2f4a5dafb..c5abff3b96360 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -34,8 +34,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool { ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => { - match dm.borrow().get(&pat.id) { - Some(&DefVariant(..)) => true, + match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefVariant(..)) => true, _ => false } } @@ -49,8 +49,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool { ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => { - match dm.borrow().get(&pat.id) { - Some(&DefVariant(..)) | Some(&DefStruct(..)) => true, + match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefVariant(..)) | Some(DefStruct(..)) => true, _ => false } } @@ -61,8 +61,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool { pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool { match pat.node { ast::PatIdent(_, _, None) | ast::PatEnum(..) => { - match dm.borrow().get(&pat.id) { - Some(&DefConst(..)) => true, + match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => true, _ => false } } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index dd1e32d13a2be..3a253735f925b 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -16,7 +16,7 @@ pub use self::PrivateDep::*; pub use self::ImportUse::*; pub use self::LastPrivate::*; -use util::nodemap::{DefIdSet, NodeMap, NodeSet}; +use util::nodemap::{DefIdSet, NodeSet}; use syntax::ast; @@ -32,9 +32,6 @@ pub type ExternalExports = DefIdSet; /// reexporting a public struct doesn't inline the doc). pub type PublicItems = NodeSet; -// FIXME: dox -pub type LastPrivateMap = NodeMap; - #[derive(Copy, Debug)] pub enum LastPrivate { LastMod(PrivateDep), diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 550f4e39447f8..a140c766758e3 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -96,7 +96,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { match expr.node { ast::ExprPath(_) | ast::ExprQPath(_) => { let def = match self.tcx.def_map.borrow().get(&expr.id) { - Some(&def) => def, + Some(d) => d.full_def(), None => { self.tcx.sess.span_bug(expr.span, "def ID not in def map?!") diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 7b957d6ce8498..9bcda68eb3ad7 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -168,8 +168,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { ast::TyPath(ref path) => { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. - match self.def_map.borrow().get(&ty.id) { - Some(&def::DefTrait(..)) => { + match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) { + Some((def::DefTrait(..), 0)) => { self.with(LateScope(&Vec::new(), self.scope), |_, this| { this.visit_path(path, ty.id); }); diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index cfa5e5fce3879..f67e470ee5491 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -393,12 +393,14 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId, cb: &mut FnMut(ast::DefId, Span, &Option)) { - let did = match tcx.def_map.borrow().get(&id) { - Some(&def::DefPrimTy(..)) => return, - Some(def) => def.def_id(), - None => return - }; - maybe_do_stability_check(tcx, did, path.span, cb) + match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) { + Some(def::DefPrimTy(..)) => {} + Some(def) => { + maybe_do_stability_check(tcx, def.def_id(), path.span, cb); + } + None => {} + } + } fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7dcdeaf16d2e8..7cd047279028c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -46,12 +46,11 @@ use metadata::csearch; use middle; use middle::check_const; use middle::const_eval; -use middle::def::{self, DefMap, ExportMap, PartialDefMap}; +use middle::def::{self, DefMap, ExportMap}; use middle::dependency_format; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem}; use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem}; use middle::mem_categorization as mc; -use middle::privacy::LastPrivateMap; use middle::region; use middle::resolve_lifetime; use middle::infer; @@ -683,8 +682,6 @@ pub struct ctxt<'tcx> { pub sess: Session, pub def_map: DefMap, - pub partial_def_map: PartialDefMap, - pub last_private_map: RefCell, pub named_region_map: resolve_lifetime::NamedRegionMap, @@ -2427,8 +2424,6 @@ impl<'tcx> CommonTypes<'tcx> { pub fn mk_ctxt<'tcx>(s: Session, arenas: &'tcx CtxtArenas<'tcx>, def_map: DefMap, - partial_def_map: PartialDefMap, - last_private_map: LastPrivateMap, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, freevars: RefCell, @@ -2451,8 +2446,6 @@ pub fn mk_ctxt<'tcx>(s: Session, variance_computed: Cell::new(false), sess: s, def_map: def_map, - partial_def_map: partial_def_map, - last_private_map: RefCell::new(last_private_map), region_maps: region_maps, node_types: RefCell::new(FnvHashMap()), item_substs: RefCell::new(NodeMap()), @@ -4509,7 +4502,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>, pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def { match tcx.def_map.borrow().get(&expr.id) { - Some(&def) => def, + Some(def) => def.full_def(), None => { tcx.sess.span_bug(expr.span, &format!( "no def-map entry for expr {}", expr.id)); @@ -4692,11 +4685,10 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { ast::ExprBox(Some(ref place), _) => { // Special case `Box` for now: - let definition = match tcx.def_map.borrow().get(&place.id) { - Some(&def) => def, + let def_id = match tcx.def_map.borrow().get(&place.id) { + Some(def) => def.def_id(), None => panic!("no def for place"), }; - let def_id = definition.def_id(); if tcx.lang_items.exchange_heap() == Some(def_id) { RvalueDatumExpr } else { @@ -5144,10 +5136,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) } pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId { - let def = *tcx.def_map.borrow() - .get(&tr.ref_id) - .expect("no def-map entry for trait"); - def.def_id() + tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id() } pub fn try_add_builtin_trait( diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index aafa4dec0de94..bd911c20afc47 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -567,12 +567,10 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, let resolve::CrateMap { def_map, - partial_def_map, freevars, export_map, trait_map, external_exports, - last_private_map, glob_map, } = time(time_passes, "resolution", (), @@ -608,8 +606,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, let ty_cx = ty::mk_ctxt(sess, arenas, def_map, - partial_def_map, - last_private_map, named_region_map, ast_map, freevars, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 1452c44ca7144..f325a6abede51 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -259,7 +259,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => { let public_ty = match ty.node { ast::TyPath(_) => { - match self.tcx.def_map.borrow()[ty.id].clone() { + match self.tcx.def_map.borrow()[ty.id].full_def() { def::DefPrimTy(..) => true, def => { let did = def.def_id(); @@ -326,7 +326,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { ast::ItemTy(ref ty, _) if public_first => { if let ast::TyPath(_) = ty.node { - match self.tcx.def_map.borrow()[ty.id].clone() { + match self.tcx.def_map.borrow()[ty.id].full_def() { def::DefPrimTy(..) | def::DefTyParam(..) => {}, def => { let did = def.def_id(); @@ -630,7 +630,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { ast::TyPath(_) => {} _ => return Some((err_span, err_msg, None)), }; - let def = self.tcx.def_map.borrow()[ty.id].clone(); + let def = self.tcx.def_map.borrow()[ty.id].full_def(); let did = def.def_id(); assert!(is_local(did)); match self.tcx.map.get(did.node) { @@ -716,19 +716,19 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // Checks that a path is in scope. fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) { debug!("privacy - path {}", self.nodestr(path_id)); - let orig_def = self.tcx.def_map.borrow()[path_id].clone(); + let path_res = self.tcx.def_map.borrow()[path_id]; let ck = |tyname: &str| { let ck_public = |def: ast::DefId| { debug!("privacy - ck_public {:?}", def); let name = token::get_ident(last); - let origdid = orig_def.def_id(); + let origdid = path_res.def_id(); self.ensure_public(span, def, Some(origdid), &format!("{} `{}`", tyname, name)) }; - match self.tcx.last_private_map.borrow()[path_id] { + match path_res.last_private { LastMod(AllPublic) => {}, LastMod(DependsOn(def)) => { self.report_error(ck_public(def)); @@ -792,7 +792,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // def map is not. Therefore the names we work out below will not always // be accurate and we can get slightly wonky error messages (but type // checking is always correct). - match self.tcx.def_map.borrow()[path_id].clone() { + match path_res.full_def() { def::DefFn(..) => ck("function"), def::DefStatic(..) => ck("static"), def::DefConst(..) => ck("const"), @@ -889,7 +889,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } } ty::ty_enum(_, _) => { - match self.tcx.def_map.borrow()[expr.id].clone() { + match self.tcx.def_map.borrow()[expr.id].full_def() { def::DefVariant(_, variant_id, _) => { for field in fields { self.check_field(expr.span, variant_id, @@ -922,8 +922,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { with private fields"); } }; - match self.tcx.def_map.borrow().get(&expr.id) { - Some(&def::DefStruct(did)) => { + match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { + Some(def::DefStruct(did)) => { guard(if is_local(did) { local_def(self.tcx.map.get_parent(did.node)) } else { @@ -962,8 +962,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } } ty::ty_enum(_, _) => { - match self.tcx.def_map.borrow().get(&pattern.id) { - Some(&def::DefVariant(_, variant_id, _)) => { + match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) { + Some(def::DefVariant(_, variant_id, _)) => { for field in fields { self.check_field(pattern.span, variant_id, NamedField(field.node.ident.name)); @@ -1214,7 +1214,7 @@ struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> { impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { fn path_is_private_type(&self, path_id: ast::NodeId) -> bool { - let did = match self.tcx.def_map.borrow().get(&path_id).cloned() { + let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) { // `int` etc. (None doesn't seem to occur.) None | Some(def::DefPrimTy(..)) => return false, Some(def) => def.def_id() diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index a239c73c110db..aebbe14407380 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -68,17 +68,17 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { "unused import".to_string()); } - let (v_priv, t_priv) = match self.last_private.get(&id) { - Some(&LastImport { - value_priv: v, - value_used: _, - type_priv: t, - type_used: _ - }) => (v, t), - Some(_) => { + let mut def_map = self.def_map.borrow_mut(); + let path_res = if let Some(r) = def_map.get_mut(&id) { + r + } else { + return; + }; + let (v_priv, t_priv) = match path_res.last_private { + LastImport { value_priv, type_priv, .. } => (value_priv, type_priv), + _ => { panic!("we should only have LastImport for `use` directives") } - _ => return, }; let mut v_used = if self.used_imports.contains(&(id, ValueNS)) { @@ -100,10 +100,12 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { _ => {}, } - self.last_private.insert(id, LastImport{value_priv: v_priv, - value_used: v_used, - type_priv: t_priv, - type_used: t_used}); + path_res.last_private = LastImport { + value_priv: v_priv, + value_used: v_used, + type_priv: t_priv, + type_used: t_used + }; } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6b05a64874654..265f398d25ca5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -934,13 +934,11 @@ struct Resolver<'a, 'tcx:'a> { primitive_type_table: PrimitiveTypeTable, def_map: DefMap, - partial_def_map: PartialDefMap, freevars: RefCell, freevars_seen: RefCell>, export_map: ExportMap, trait_map: TraitMap, external_exports: ExternalExports, - last_private: LastPrivateMap, // Whether or not to print error messages. Can be set to true // when getting additional info for error message suggestions, @@ -1008,7 +1006,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { primitive_type_table: PrimitiveTypeTable::new(), def_map: RefCell::new(NodeMap()), - partial_def_map: RefCell::new(NodeMap()), freevars: RefCell::new(NodeMap()), freevars_seen: RefCell::new(NodeMap()), export_map: NodeMap(), @@ -1016,7 +1013,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { used_imports: HashSet::new(), used_crates: HashSet::new(), external_exports: DefIdSet(), - last_private: NodeMap(), emit_errors: true, make_glob_map: make_glob_map == MakeGlobMap::Yes, @@ -1574,31 +1570,36 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // record what this import resolves to for later uses in documentation, // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. - let value_private = match import_resolution.value_target { - Some(ref target) => { - let def = target.bindings.def_for_namespace(ValueNS).unwrap(); - self.def_map.borrow_mut().insert(directive.id, def); - let did = def.def_id(); - if value_used_public {Some(lp)} else {Some(DependsOn(did))} - }, - // AllPublic here and below is a dummy value, it should never be used because - // _exists is false. - None => None, - }; - let type_private = match import_resolution.type_target { - Some(ref target) => { - let def = target.bindings.def_for_namespace(TypeNS).unwrap(); - self.def_map.borrow_mut().insert(directive.id, def); - let did = def.def_id(); - if type_used_public {Some(lp)} else {Some(DependsOn(did))} - }, - None => None, + let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| { + let def = target.bindings.def_for_namespace(ValueNS).unwrap(); + (def, if value_used_public { lp } else { DependsOn(def.def_id()) }) + }); + let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| { + let def = target.bindings.def_for_namespace(TypeNS).unwrap(); + (def, if type_used_public { lp } else { DependsOn(def.def_id()) }) + }); + + let import_lp = LastImport { + value_priv: value_def_and_priv.map(|(_, p)| p), + value_used: Used, + type_priv: type_def_and_priv.map(|(_, p)| p), + type_used: Used }; - self.last_private.insert(directive.id, LastImport{value_priv: value_private, - value_used: Used, - type_priv: type_private, - type_used: Used}); + if let Some((def, _)) = value_def_and_priv { + self.def_map.borrow_mut().insert(directive.id, PathResolution { + base_def: def, + last_private: import_lp, + depth: 0 + }); + } + if let Some((def, _)) = type_def_and_priv { + self.def_map.borrow_mut().insert(directive.id, PathResolution { + base_def: def, + last_private: import_lp, + depth: 0 + }); + } debug!("(resolving single import) successfully resolved import"); return Success(()); @@ -1716,12 +1717,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Record the destination of this import - match containing_module.def_id.get() { - Some(did) => { - self.def_map.borrow_mut().insert(id, DefMod(did)); - self.last_private.insert(id, lp); - } - None => {} + if let Some(did) = containing_module.def_id.get() { + self.def_map.borrow_mut().insert(id, PathResolution { + base_def: DefMod(did), + last_private: lp, + depth: 0 + }); } debug!("(resolving glob import) successfully resolved import"); @@ -2846,8 +2847,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ItemUse(ref view_path) => { // check for imports shadowing primitive types if let ast::ViewPathSimple(ident, _) = view_path.node { - match self.def_map.borrow().get(&item.id) { - Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefTrait(..)) | None => { + match self.def_map.borrow().get(&item.id).map(|d| d.full_def()) { + Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => { self.check_if_primitive_type_name(ident.name, item.span); } _ => {} @@ -2959,30 +2960,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { id: NodeId, trait_path: &Path, path_depth: usize) - -> Result<(Def, LastPrivate, usize), ()> { - match self.resolve_path(id, trait_path, path_depth, TypeNS, true) { - Some(def @ (DefTrait(_), _, _)) => { - debug!("(resolving trait) found trait def: {:?}", def); - Ok(def) - } - Some((def, _, _)) => { + -> Result { + if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) { + if let DefTrait(_) = path_res.base_def { + debug!("(resolving trait) found trait def: {:?}", path_res); + Ok(path_res) + } else { self.resolve_error(trait_path.span, &format!("`{}` is not a trait", self.path_names_to_string(trait_path, path_depth))); // If it's a typedef, give a note - if let DefTy(..) = def { + if let DefTy(..) = path_res.base_def { self.session.span_note(trait_path.span, "`type` aliases cannot be used for traits"); } Err(()) } - None => { - let msg = format!("use of undeclared trait name `{}`", - self.path_names_to_string(trait_path, path_depth)); - self.resolve_error(trait_path.span, &msg[]); - Err(()) - } + } else { + let msg = format!("use of undeclared trait name `{}`", + self.path_names_to_string(trait_path, path_depth)); + self.resolve_error(trait_path.span, &msg[]); + Err(()) } } @@ -2995,14 +2994,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &ast::WherePredicate::BoundPredicate(_) | &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { - match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) { - Some(def @ (DefTyParam(..), _, _)) => { - self.record_def(eq_pred.id, def); - } - _ => { - self.resolve_error(eq_pred.path.span, - "undeclared associated type"); - } + let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true); + if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res { + self.record_def(eq_pred.id, path_res.unwrap()); + } else { + self.resolve_error(eq_pred.path.span, "undeclared associated type"); } } } @@ -3028,9 +3024,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut new_val = None; if let Some(ref trait_ref) = *opt_trait_ref { match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) { - Ok(def) => { - self.record_def(trait_ref.ref_id, def); - new_val = Some((def.0.def_id(), trait_ref.clone())); + Ok(path_res) => { + self.record_def(trait_ref.ref_id, path_res); + new_val = Some((path_res.base_def.def_id(), trait_ref.clone())); } Err(_) => { /* error was already reported */ } } @@ -3259,23 +3255,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path.segments.len() }; - let mut result = None; + let mut resolution = None; for depth in 0..max_assoc_types { self.with_no_errors(|this| { - result = this.resolve_path(ty.id, path, depth, TypeNS, true); + resolution = this.resolve_path(ty.id, path, depth, TypeNS, true); }); - if result.is_some() { + if resolution.is_some() { break; } } - if let Some((DefMod(_), _, _)) = result { + if let Some(DefMod(_)) = resolution.map(|r| r.base_def) { // A module is not a valid type. - result = None; + resolution = None; } // This is a path in the type namespace. Walk through scopes // looking for it. - match result { + match resolution { Some(def) => { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ @@ -3338,7 +3334,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "an enum variant"); - self.record_def(pattern.id, (def, lp, 0)); + self.record_def(pattern.id, PathResolution { + base_def: def, + last_private: lp, + depth: 0 + }); } FoundStructOrEnumVariant(..) => { self.resolve_error( @@ -3357,7 +3357,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "a constant"); - self.record_def(pattern.id, (def, lp, 0)); + self.record_def(pattern.id, PathResolution { + base_def: def, + last_private: lp, + depth: 0 + }); } FoundConst(..) => { self.resolve_error(pattern.span, @@ -3374,7 +3378,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // will be able to distinguish variants from // locals in patterns. - self.record_def(pattern.id, (def, LastMod(AllPublic), 0)); + self.record_def(pattern.id, PathResolution { + base_def: def, + last_private: LastMod(AllPublic), + depth: 0 + }); // Add the binding to the local ribs, if it // doesn't already exist in the bindings list. (We @@ -3417,29 +3425,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatEnum(ref path, _) => { // This must be an enum variant, struct or const. - match self.resolve_path(pat_id, path, 0, ValueNS, false) { - Some(def @ (DefVariant(..), _, _)) | - Some(def @ (DefStruct(..), _, _)) | - Some(def @ (DefConst(..), _, _)) => { - self.record_def(pattern.id, def); - } - Some((DefStatic(..), _, _)) => { - self.resolve_error(path.span, - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); - } - Some(_) => { - self.resolve_error(path.span, - &format!("`{}` is not an enum variant, struct or const", - token::get_ident( - path.segments.last().unwrap().identifier))); - } - None => { - self.resolve_error(path.span, - &format!("unresolved enum variant, struct or const `{}`", - token::get_ident(path.segments.last().unwrap().identifier))); + if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) { + match path_res.base_def { + DefVariant(..) | DefStruct(..) | DefConst(..) => { + self.record_def(pattern.id, path_res); + } + DefStatic(..) => { + self.resolve_error(path.span, + "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); + } + _ => { + self.resolve_error(path.span, + &format!("`{}` is not an enum variant, struct or const", + token::get_ident( + path.segments.last().unwrap().identifier))); + } } + } else { + self.resolve_error(path.span, + &format!("unresolved enum variant, struct or const `{}`", + token::get_ident(path.segments.last().unwrap().identifier))); } visit::walk_path(self, path); } @@ -3535,18 +3542,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// If `check_ribs` is true, checks the local definitions first; i.e. /// doesn't skip straight to the containing module. + /// Skips `path_depth` trailing segments, which is also reflected in the + /// returned value. See `middle::def::PathResolution` for more info. fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace, - check_ribs: bool) -> Option<(Def, LastPrivate, usize)> { + check_ribs: bool) -> Option { let span = path.span; let segments = &path.segments[..path.segments.len()-path_depth]; + let mk_res = |(def, lp)| PathResolution { + base_def: def, + last_private: lp, + depth: path_depth + }; + if path.global { let def = self.resolve_crate_relative_path(span, segments, namespace); - return def.map(|(def, lp)| (def, lp, path_depth)); + return def.map(mk_res); } // Try to find a path to an item in a module. @@ -3568,9 +3583,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => () } - def.map(|(def, lp)| (def, lp, path_depth)) + def.map(mk_res) } else { - unqualified_def.map(|(def, lp)| (def, lp, path_depth)) + unqualified_def.map(mk_res) } } @@ -3957,10 +3972,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if allowed == Everything { // Look for a field with the same name in the current self_type. - match self.def_map.borrow().get(&node_id) { - Some(&DefTy(did, _)) - | Some(&DefStruct(did)) - | Some(&DefVariant(_, did, _)) => match self.structs.get(&did) { + match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) { + Some(DefTy(did, _)) | + Some(DefStruct(did)) | + Some(DefVariant(_, did, _)) => match self.structs.get(&did) { None => {} Some(fields) => { if fields.iter().any(|&field_name| name == field_name) { @@ -4060,27 +4075,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path.segments.len() }; - let mut result = self.with_no_errors(|this| { + let mut resolution = self.with_no_errors(|this| { this.resolve_path(expr.id, path, 0, ValueNS, true) }); for depth in 1..max_assoc_types { - if result.is_some() { + if resolution.is_some() { break; } self.with_no_errors(|this| { - result = this.resolve_path(expr.id, path, depth, TypeNS, true); + resolution = this.resolve_path(expr.id, path, depth, TypeNS, true); }); } - if let Some((DefMod(_), _, _)) = result { + if let Some(DefMod(_)) = resolution.map(|r| r.base_def) { // A module is not a valid type or value. - result = None; + resolution = None; } // This is a local path in the value namespace. Walk through // scopes looking for it. - match result { + if let Some(path_res) = resolution { // Check if struct variant - Some((DefVariant(_, _, true), _, 0)) => { + if let DefVariant(_, _, true) = path_res.base_def { let path_name = self.path_names_to_string(path, 0); self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ @@ -4092,95 +4107,93 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &format!("Did you mean to write: \ `{} {{ /* fields */ }}`?", path_name)); - } - Some(def) => { + } else { // Write the result into the def map. debug!("(resolving expr) resolved `{}`", self.path_names_to_string(path, 0)); // Partial resolutions will need the set of traits in scope, // so they can be completed during typeck. - if def.2 != 0 { + if path_res.depth != 0 { let method_name = path.segments.last().unwrap().identifier.name; let traits = self.search_for_traits_containing_method(method_name); self.trait_map.insert(expr.id, traits); } - self.record_def(expr.id, def); + self.record_def(expr.id, path_res); } - None => { - // Be helpful if the name refers to a struct - // (The pattern matching def_tys where the id is in self.structs - // matches on regular structs while excluding tuple- and enum-like - // structs, which wouldn't result in this error.) - let path_name = self.path_names_to_string(path, 0); - match self.with_no_errors(|this| - this.resolve_path(expr.id, path, 0, TypeNS, false)) { - Some((DefTy(struct_id, _), _, 0)) - if self.structs.contains_key(&struct_id) => { - self.resolve_error(expr.span, - &format!("`{}` is a structure name, but \ - this expression \ - uses it like a function name", - path_name)); - - self.session.span_help(expr.span, - &format!("Did you mean to write: \ - `{} {{ /* fields */ }}`?", - path_name)); - - } - _ => { - // Keep reporting some errors even if they're ignored above. - self.resolve_path(expr.id, path, 0, ValueNS, true); - - let mut method_scope = false; - self.value_ribs.iter().rev().all(|rib| { - method_scope = match rib.kind { - MethodRibKind => true, - ItemRibKind | ConstantItemRibKind => false, - _ => return true, // Keep advancing - }; - false // Stop advancing - }); + } else { + // Be helpful if the name refers to a struct + // (The pattern matching def_tys where the id is in self.structs + // matches on regular structs while excluding tuple- and enum-like + // structs, which wouldn't result in this error.) + let path_name = self.path_names_to_string(path, 0); + let type_res = self.with_no_errors(|this| { + this.resolve_path(expr.id, path, 0, TypeNS, false) + }); + match type_res.map(|r| r.base_def) { + Some(DefTy(struct_id, _)) + if self.structs.contains_key(&struct_id) => { + self.resolve_error(expr.span, + &format!("`{}` is a structure name, but \ + this expression \ + uses it like a function name", + path_name)); + + self.session.span_help(expr.span, + &format!("Did you mean to write: \ + `{} {{ /* fields */ }}`?", + path_name)); - if method_scope && &token::get_name(self.self_name)[..] - == path_name { - self.resolve_error( - expr.span, - "`self` is not available \ - in a static method. Maybe a \ - `self` argument is missing?"); - } else { - let last_name = path.segments.last().unwrap().identifier.name; - let mut msg = match self.find_fallback_in_self_type(last_name) { - NoSuggestion => { - // limit search to 5 to reduce the number - // of stupid suggestions - self.find_best_match_for_name(&path_name, 5) - .map_or("".to_string(), - |x| format!("`{}`", x)) - } - Field => - format!("`self.{}`", path_name), - Method - | TraitItem => - format!("to call `self.{}`", path_name), - TraitMethod(path_str) - | StaticMethod(path_str) => - format!("to call `{}::{}`", path_str, path_name) - }; - - if msg.len() > 0 { - msg = format!(". Did you mean {}?", msg) - } + } + _ => { + // Keep reporting some errors even if they're ignored above. + self.resolve_path(expr.id, path, 0, ValueNS, true); + + let mut method_scope = false; + self.value_ribs.iter().rev().all(|rib| { + method_scope = match rib.kind { + MethodRibKind => true, + ItemRibKind | ConstantItemRibKind => false, + _ => return true, // Keep advancing + }; + false // Stop advancing + }); + if method_scope && &token::get_name(self.self_name)[..] + == path_name { self.resolve_error( expr.span, - &format!("unresolved name `{}`{}", - path_name, - msg)); + "`self` is not available \ + in a static method. Maybe a \ + `self` argument is missing?"); + } else { + let last_name = path.segments.last().unwrap().identifier.name; + let mut msg = match self.find_fallback_in_self_type(last_name) { + NoSuggestion => { + // limit search to 5 to reduce the number + // of stupid suggestions + self.find_best_match_for_name(&path_name, 5) + .map_or("".to_string(), + |x| format!("`{}`", x)) + } + Field => format!("`self.{}`", path_name), + Method | + TraitItem => + format!("to call `self.{}`", path_name), + TraitMethod(path_str) | + StaticMethod(path_str) => + format!("to call `{}::{}`", path_str, path_name) + }; + + if msg.len() > 0 { + msg = format!(". Did you mean {}?", msg) } + + self.resolve_error( + expr.span, + &format!("unresolved name `{}`{}", + path_name, msg)); } } } @@ -4231,7 +4244,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. - self.record_def(expr.id, (def, LastMod(AllPublic), 0)) + self.record_def(expr.id, PathResolution { + base_def: def, + last_private: LastMod(AllPublic), + depth: 0 + }) } Some(_) => { self.session.span_bug(expr.span, @@ -4349,33 +4366,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { found_traits } - fn record_def(&mut self, - node_id: NodeId, - (def, lp, depth): (Def, LastPrivate, usize)) { - debug!("(recording def) recording {:?} for {}, last private {:?}", - def, node_id, lp); - assert!(match lp {LastImport{..} => false, _ => true}, + fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { + debug!("(recording def) recording {:?} for {}", resolution, node_id); + assert!(match resolution.last_private {LastImport{..} => false, _ => true}, "Import should only be used for `use` directives"); - self.last_private.insert(node_id, lp); - if depth == 0 { - if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) { - let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); - self.session.span_bug(span, &format!("path resolved multiple times \ - ({:?} before, {:?} now)", - prev_def, def)); - } - } else { - let def = PartialDef { - base_type: def, - extra_associated_types: (depth - 1) as u32 - }; - if let Some(prev_def) = self.partial_def_map.borrow_mut().insert(node_id, def) { - let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); - self.session.span_bug(span, &format!("path resolved multiple times \ - ({:?} before, {:?} now)", - prev_def, def)); - } + if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) { + let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); + self.session.span_bug(span, &format!("path resolved multiple times \ + ({:?} before, {:?} now)", + prev_res, resolution)); } } @@ -4466,12 +4466,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub struct CrateMap { pub def_map: DefMap, - pub partial_def_map: PartialDefMap, pub freevars: RefCell, pub export_map: ExportMap, pub trait_map: TraitMap, pub external_exports: ExternalExports, - pub last_private_map: LastPrivateMap, pub glob_map: Option } @@ -4506,12 +4504,10 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, CrateMap { def_map: resolver.def_map, - partial_def_map: resolver.partial_def_map, freevars: resolver.freevars, export_map: resolver.export_map, trait_map: resolver.trait_map, external_exports: resolver.external_exports, - last_private_map: resolver.last_private, glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 5484e3c7c5fc2..ea346798679c0 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -218,7 +218,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref", ref_id)); } - let def = (*self.analysis.ty_cx.def_map.borrow())[ref_id]; + let def = self.analysis.ty_cx.def_map.borrow()[ref_id].full_def(); match def { def::DefPrimTy(_) => None, _ => Some(def.def_id()), @@ -231,7 +231,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind", ref_id)); } - let def = (*def_map)[ref_id]; + let def = def_map[ref_id].full_def(); match def { def::DefMod(_) | def::DefForeignMod(_) => Some(recorder::ModRef), @@ -792,9 +792,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.sess.span_bug(span, &format!("def_map has no key for {} in visit_expr", id)); } - let def = &(*def_map)[id]; + let def = def_map[id].full_def(); let sub_span = self.span.span_for_last_ident(span); - match *def { + match def { def::DefUpvar(..) | def::DefLocal(..) | def::DefStatic(..) | @@ -866,10 +866,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { &format!("Unexpected def kind while looking \ up path in `{}`: `{:?}`", self.span.snippet(span), - *def)), + def)), } // modules or types in the path prefix - match *def { + match def { def::DefMethod(did, _) => { let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did); if let ty::MethodTraitItem(m) = ti { @@ -1456,8 +1456,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { &format!("def_map has no key for {} in visit_arm", id)); } - let def = &(*def_map)[id]; - match *def { + let def = def_map[id].full_def(); + match def { def::DefLocal(id) => { let value = if *immut { self.span.snippet(p.span).to_string() @@ -1480,7 +1480,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { def::DefStatic(_, _) => {} def::DefConst(..) => {} _ => error!("unexpected definition kind when processing collected paths: {:?}", - *def) + def) } } for &(id, ref path, ref_kind) in &paths_to_process { diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 26e1a981f1bae..3e741640117aa 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -598,7 +598,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => { // This is either an enum variant or a variable binding. - let opt_def = tcx.def_map.borrow().get(&cur.id).cloned(); + let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def()); match opt_def { Some(def::DefVariant(enum_id, var_id, _)) => { let variant = ty::enum_variant_with_id(tcx, enum_id, var_id); @@ -725,14 +725,14 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool { match pat.node { ast::PatTup(_) => true, ast::PatStruct(..) => { - match tcx.def_map.borrow().get(&pat.id) { - Some(&def::DefVariant(..)) => false, + match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(def::DefVariant(..)) => false, _ => true, } } ast::PatEnum(..) | ast::PatIdent(_, _, None) => { - match tcx.def_map.borrow().get(&pat.id) { - Some(&def::DefStruct(..)) => true, + match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(def::DefStruct(..)) => true, _ => false } } @@ -1282,15 +1282,15 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool _ => return false }, ast::ExprField(ref base, field) => { - let vid = match bcx.tcx().def_map.borrow().get(&base.id) { - Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid, + let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) { + Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid, _ => return false }; (vid, Some(mc::NamedField(field.node.name))) }, ast::ExprTupField(ref base, field) => { - let vid = match bcx.tcx().def_map.borrow().get(&base.id) { - Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid, + let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) { + Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid, _ => return false }; (vid, Some(mc::PositionalField(field.node))) @@ -1689,7 +1689,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } ast::PatEnum(_, ref sub_pats) => { - let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).cloned(); + let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def()); match opt_def { Some(def::DefVariant(enum_id, var_id, _)) => { let repr = adt::represent_node(bcx, pat.id); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index a3ba506fc46a2..d8fc6df2685dd 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -603,7 +603,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { pub fn def(&self, nid: ast::NodeId) -> def::Def { match self.tcx().def_map.borrow().get(&nid) { - Some(v) => v.clone(), + Some(v) => v.full_def(), None => { self.tcx().sess.bug(&format!( "no def associated with node id {}", nid)); diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index e321c5f0a13d5..6e1d2da02c101 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -194,7 +194,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Special-case constants to cache a common global for all uses. match expr.node { ast::ExprPath(_) => { - let def = ccx.tcx().def_map.borrow()[expr.id]; + let def = ccx.tcx().def_map.borrow()[expr.id].full_def(); match def { def::DefConst(def_id) => { if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) { @@ -582,7 +582,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => break, } } - let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned(); + let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def()); if let Some(def::DefStatic(def_id, _)) = opt_def { return get_static_val(cx, def_id, ety); } @@ -664,7 +664,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = cx.tcx().def_map.borrow()[e.id]; + let def = cx.tcx().def_map.borrow()[e.id].full_def(); match def { def::DefFn(..) | def::DefMethod(..) => { expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val @@ -701,7 +701,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } ast::ExprCall(ref callee, ref args) => { - let opt_def = cx.tcx().def_map.borrow().get(&callee.id).cloned(); + let opt_def = cx.tcx().def_map.borrow().get(&callee.id).map(|d| d.full_def()); let arg_vals = map_list(&args[..]); match opt_def { Some(def::DefStruct(_)) => { diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 5eebe6a4a05fb..ad96c506c9ddf 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -306,11 +306,10 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let loop_id = match opt_label { None => fcx.top_loop_scope(), Some(_) => { - match bcx.tcx().def_map.borrow().get(&expr.id) { - Some(&def::DefLabel(loop_id)) => loop_id, - ref r => { - bcx.tcx().sess.bug(&format!("{:?} in def-map for label", - r)) + match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def()) { + Some(def::DefLabel(loop_id)) => loop_id, + r => { + bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r)) } } } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 95c5122deacb6..80fe2ed8f3af3 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1363,7 +1363,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, ty.repr(tcx))); } Some(node_id) => { - let def = tcx.def_map.borrow()[node_id].clone(); + let def = tcx.def_map.borrow()[node_id].full_def(); match def { def::DefVariant(enum_id, variant_id, _) => { let variant_info = ty::enum_variant_with_id( diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index adbc4d546f190..982cc1e3792e1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -898,7 +898,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, match ty.node { ast::TyPath(ref path) => { - let def = this.tcx().def_map.borrow().get(&ty.id).cloned(); + let def = this.tcx().def_map.borrow().get(&ty.id).map(|d| d.full_def()); match def { Some(def::DefTrait(trait_def_id)) => { let mut projection_bounds = Vec::new(); @@ -1303,16 +1303,14 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds) } ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { - let result = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { - (d, 0) - } else if let Some(d) = tcx.partial_def_map.borrow().get(&ast_ty.id) { - (d.base_type, (d.extra_associated_types + 1) as usize) + let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { + d } else { tcx.sess.span_bug(ast_ty.span, &format!("unbound path {}", ast_ty.repr(tcx))) }; - let (mut def, max_depth) = result; - let base_ty_end = path.segments.len() - max_depth; + let mut def = path_res.base_def; + let base_ty_end = path.segments.len() - path_res.depth; let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { Some(ast_ty_to_ty(this, rscope, &*qpath.self_type)) } else { @@ -1324,9 +1322,13 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, &path.segments[..base_ty_end], &path.segments[base_ty_end..]); - if max_depth != 0 && ty.sty != ty::ty_err { + if path_res.depth != 0 && ty.sty != ty::ty_err { // Write back the new resolution. - tcx.def_map.borrow_mut().insert(ast_ty.id, def); + tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution { + base_def: def, + last_private: path_res.last_private, + depth: 0 + }); } ty diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index edbda795bde3c..dd2ab6c6b13ca 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -103,7 +103,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, demand::eqtype(fcx, pat.span, expected, lhs_ty); } ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => { - let const_did = tcx.def_map.borrow()[pat.id].clone().def_id(); + let const_did = tcx.def_map.borrow()[pat.id].def_id(); let const_scheme = ty::lookup_item_type(tcx, const_did); assert!(const_scheme.generics.is_empty()); let const_ty = pcx.fcx.instantiate_type_scheme(pat.span, @@ -433,7 +433,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - let def = tcx.def_map.borrow()[pat.id].clone(); + let def = tcx.def_map.borrow()[pat.id].full_def(); let (enum_def_id, variant_def_id) = match def { def::DefTrait(_) => { let name = pprust::path_to_string(path); @@ -502,7 +502,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - let def = tcx.def_map.borrow()[pat.id].clone(); + let def = tcx.def_map.borrow()[pat.id].full_def(); let enum_def = def.variant_def_ids() .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 068e03dab120b..f99e4e4b2ed8a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -91,7 +91,6 @@ use middle::infer; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::pat_util::{self, pat_id_map}; -use middle::privacy::{AllPublic, LastMod}; use middle::region::{self, CodeExtent}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; use middle::traits; @@ -3598,21 +3597,23 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, None }; - // Helpers to avoid keeping the RefCell borrow for too long. - let get_def = || tcx.def_map.borrow().get(&id).cloned(); - let get_partial_def = || tcx.partial_def_map.borrow().get(&id).cloned(); + let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) { + d + } else { + tcx.sess.span_bug(expr.span, + &format!("unbound path {}", expr.repr(tcx))[]) + }; - if let Some(def) = get_def() { + let mut def = path_res.base_def; + if path_res.depth == 0 { let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, def); instantiate_path(fcx, &path.segments, scheme, &predicates, - None, def, expr.span, id); - } else if let Some(partial) = get_partial_def() { - let mut def = partial.base_type; + opt_self_ty, def, expr.span, id); + } else { let ty_segments = path.segments.init(); - let ty_assoc_num = partial.extra_associated_types as usize; - let base_ty_end = ty_segments.len() - ty_assoc_num; + let base_ty_end = path.segments.len() - path_res.depth; let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span, PathParamMode::Optional, &mut def, @@ -3624,13 +3625,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) { Ok((def, lp)) => { // Write back the new resolution. - tcx.def_map.borrow_mut().insert(id, def); - - if let LastMod(AllPublic) = lp { - // Public method, don't change the last private entry. - } else { - tcx.last_private_map.borrow_mut().insert(id, lp); - } + tcx.def_map.borrow_mut().insert(id, def::PathResolution { + base_def: def, + last_private: path_res.last_private.or(lp), + depth: 0 + }); let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, def); @@ -3644,9 +3643,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_error(id); } } - } else { - tcx.sess.span_bug(expr.span, - &format!("unbound path {}", expr.repr(tcx))[]) } // We always require that the type provided as the value for @@ -3882,7 +3878,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprStruct(ref path, ref fields, ref base_expr) => { // Resolve the path. - let def = tcx.def_map.borrow().get(&id).cloned(); + let def = tcx.def_map.borrow().get(&id).map(|d| d.full_def()); let struct_id = match def { Some(def::DefVariant(enum_id, variant_id, true)) => { check_struct_enum_variant(fcx, id, expr.span, enum_id, @@ -5174,8 +5170,8 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { (block_query(b, |e| { match e.node { ast::ExprBreak(Some(_)) => { - match cx.def_map.borrow().get(&e.id) { - Some(&def::DefLabel(loop_id)) if id == loop_id => true, + match cx.def_map.borrow().get(&e.id).map(|d| d.full_def()) { + Some(def::DefLabel(loop_id)) if id == loop_id => true, _ => false, } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 78f13b37a8238..6b1d46aa04df8 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -165,7 +165,7 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, } fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def { match tcx.def_map.borrow().get(&id) { - Some(x) => x.clone(), + Some(x) => x.full_def(), _ => { span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition") } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d1283d6f46bd8..24b9d03400cb3 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -46,7 +46,7 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option) None => return None, }; let def = match tcx.def_map.borrow().get(&id) { - Some(def) => *def, + Some(d) => d.full_def(), None => return None, }; let did = def.def_id(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7a27159bc47a2..0aa1a23ad7e76 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2388,7 +2388,7 @@ fn resolve_type(cx: &DocContext, }; debug!("searching for {} in defmap", id); let def = match tcx.def_map.borrow().get(&id) { - Some(&k) => k, + Some(k) => k.full_def(), None => panic!("unresolved id not in defmap") }; @@ -2454,7 +2454,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option { cx.tcx_opt().and_then(|tcx| { - tcx.def_map.borrow().get(&id).map(|&def| register_def(cx, def)) + tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def())) }) } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 9f5e3be9e3229..3e998166397bc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -196,7 +196,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Some(tcx) => tcx, None => return false }; - let def = (*tcx.def_map.borrow())[id].def_id(); + let def = tcx.def_map.borrow()[id].def_id(); if !ast_util::is_local(def) { return false } let analysis = match self.analysis { Some(analysis) => analysis, None => return false From fdfb532d7829d6e5637ddffa6faff69e4312b0e0 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 17 Feb 2015 17:41:40 +0200 Subject: [PATCH 16/25] tests: remove warnings from and rename const-polymorphic-paths to ufcs-polymorphic-paths. --- ...hic-paths.rs => ufcs-polymorphic-paths.rs} | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) rename src/test/run-pass/{const-polymorphic-paths.rs => ufcs-polymorphic-paths.rs} (62%) diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/ufcs-polymorphic-paths.rs similarity index 62% rename from src/test/run-pass/const-polymorphic-paths.rs rename to src/test/run-pass/ufcs-polymorphic-paths.rs index 23d90c5ee292b..277aaf086f419 100644 --- a/src/test/run-pass/const-polymorphic-paths.rs +++ b/src/test/run-pass/ufcs-polymorphic-paths.rs @@ -27,11 +27,11 @@ struct Newt(T); fn id(x: T) -> T { x } fn eq(a: T, b: T) -> bool { a == b } fn u8_as_i8(x: u8) -> i8 { x as i8 } -fn odd(x: uint) -> bool { x % 2 == 1 } +fn odd(x: usize) -> bool { x % 2 == 1 } fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() } trait Size: Sized { - fn size() -> uint { std::mem::size_of::() } + fn size() -> usize { std::mem::size_of::() } } impl Size for T {} @@ -47,24 +47,24 @@ macro_rules! tests { tests! { // Free function. - id, fn(int) -> int, (5); - id::, fn(int) -> int, (5); + id, fn(i32) -> i32, (5); + id::, fn(i32) -> i32, (5); // Enum variant constructor. - Some, fn(int) -> Option, (5); - Some::, fn(int) -> Option, (5); + Some, fn(i32) -> Option, (5); + Some::, fn(i32) -> Option, (5); // Tuple struct constructor. - Newt, fn(int) -> Newt, (5); - Newt::, fn(int) -> Newt, (5); + Newt, fn(i32) -> Newt, (5); + Newt::, fn(i32) -> Newt, (5); // Inherent static methods. Vec::new, fn() -> Vec<()>, (); Vec::<()>::new, fn() -> Vec<()>, (); - Vec::with_capacity, fn(uint) -> Vec<()>, (5); - Vec::<()>::with_capacity, fn(uint) -> Vec<()>, (5); - BitVec::from_fn, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd); - BitVec::from_fn:: bool>, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd); + Vec::with_capacity, fn(usize) -> Vec<()>, (5); + Vec::<()>::with_capacity, fn(usize) -> Vec<()>, (5); + BitVec::from_fn, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); + BitVec::from_fn:: bool>, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); // Inherent non-static method. Vec::map_in_place, fn(Vec, fn(u8) -> i8) -> Vec, (vec![b'f', b'o', b'o'], u8_as_i8); @@ -77,34 +77,34 @@ tests! { // , (vec![b'f', b'o', b'o'], u8_as_i8); // Trait static methods. - bool::size, fn() -> uint, (); - ::size, fn() -> uint, (); + bool::size, fn() -> usize, (); + ::size, fn() -> usize, (); - Default::default, fn() -> int, (); - int::default, fn() -> int, (); - ::default, fn() -> int, (); + Default::default, fn() -> i32, (); + i32::default, fn() -> i32, (); + ::default, fn() -> i32, (); - Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - int::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - ::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - Rand::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - int::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - ::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); + Rand::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + i32::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + Rand::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + i32::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); // Trait non-static methods. - Clone::clone, fn(&int) -> int, (&5); - int::clone, fn(&int) -> int, (&5); - ::clone, fn(&int) -> int, (&5); + Clone::clone, fn(&i32) -> i32, (&5); + i32::clone, fn(&i32) -> i32, (&5); + ::clone, fn(&i32) -> i32, (&5); - FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); - Vec::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); - as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, + FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + Vec::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); - as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, + as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); - FromIterator::from_iter::>, fn(OptionIter) -> Vec, + FromIterator::from_iter::>, fn(OptionIter) -> Vec, (Some(5).into_iter()); - as FromIterator<_>>::from_iter::>, fn(OptionIter) -> Vec, + as FromIterator<_>>::from_iter::>, fn(OptionIter) -> Vec, (Some(5).into_iter()); Add::add, fn(i32, i32) -> i32, (5, 6); From d31b9ebef5c39de3fff9da02eea880d1838a8a3b Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 17 Feb 2015 19:29:13 +0200 Subject: [PATCH 17/25] Implement `::method` UFCS expression syntax. --- src/librustc/lint/builtin.rs | 6 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/astconv_util.rs | 2 +- src/librustc/middle/cfg/construct.rs | 3 +- src/librustc/middle/check_const.rs | 2 +- src/librustc/middle/check_static_recursion.rs | 4 +- src/librustc/middle/const_eval.rs | 11 +-- src/librustc/middle/effect.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/infer/error_reporting.rs | 11 ++- src/librustc/middle/liveness.rs | 12 ++-- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/middle/ty.rs | 4 +- src/librustc_back/svh.rs | 6 +- src/librustc_privacy/lib.rs | 12 ++-- src/librustc_resolve/lib.rs | 46 +++++++----- src/librustc_trans/save/mod.rs | 6 +- src/librustc_trans/trans/_match.rs | 2 +- src/librustc_trans/trans/callee.rs | 2 +- src/librustc_trans/trans/consts.rs | 4 +- src/librustc_trans/trans/debuginfo.rs | 3 +- src/librustc_trans/trans/expr.rs | 6 +- src/librustc_typeck/astconv.rs | 39 ++++++++--- src/librustc_typeck/check/mod.rs | 22 +++--- src/librustc_typeck/collect.rs | 19 ++--- src/librustdoc/clean/mod.rs | 10 +-- src/libsyntax/ast.rs | 37 +++++----- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/ext/build.rs | 26 +++---- src/libsyntax/ext/concat_idents.rs | 2 +- src/libsyntax/ext/expand.rs | 11 ++- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/fold.rs | 28 +++++--- src/libsyntax/parse/mod.rs | 12 ++-- src/libsyntax/parse/parser.rs | 70 ++++++++++++++----- src/libsyntax/print/pprust.rs | 23 +++--- src/libsyntax/visit.rs | 18 +++-- src/test/run-pass/ufcs-polymorphic-paths.rs | 11 +++ 40 files changed, 286 insertions(+), 200 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 28baeb5dc9e62..3c0d9e93ccb93 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -437,7 +437,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - if let ast::TyPath(_) = ty.node { + if let ast::TyPath(..) = ty.node { self.check_def(ty.span, ty.id); } visit::walk_ty(self, ty); @@ -682,8 +682,8 @@ impl LintPass for PathStatements { match s.node { ast::StmtSemi(ref expr, _) => { match expr.node { - ast::ExprPath(_) => cx.span_lint(PATH_STATEMENTS, s.span, - "path statement with no effect"), + ast::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span, + "path statement with no effect"), _ => () } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 4aea73cfb0ec0..a01b17ac194de 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1221,7 +1221,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_unsafety(rbml_w, unsafety); encode_polarity(rbml_w, polarity); match ty.node { - ast::TyPath(ref path) if path.segments.len() == 1 => { + ast::TyPath(None, ref path) if path.segments.len() == 1 => { let ident = path.segments.last().unwrap().identifier; encode_impl_type_basename(rbml_w, ident); } diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index c9196f0cb2a64..17fd80ceaea42 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -59,7 +59,7 @@ pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>, pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { - if let ast::TyPath(ref path) = ast_ty.node { + if let ast::TyPath(None, ref path) = ast_ty.node { let def = match tcx.def_map.borrow().get(&ast_ty.id) { None => { tcx.sess.span_bug(ast_ty.span, diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index ca9455ac421f2..24c54b53590c0 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -398,8 +398,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { ast::ExprMac(..) | ast::ExprClosure(..) | ast::ExprLit(..) | - ast::ExprPath(..) | - ast::ExprQPath(..) => { + ast::ExprPath(..) => { self.straightline(expr, pred, None::.iter()) } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 57e4d3d2f0203..8401d25024d35 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -439,7 +439,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); match def { Some(def::DefVariant(_, _, _)) => { diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index a4393f4648b1e..b97978fc03fff 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -93,8 +93,8 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { - match self.def_map.borrow().get(&e.id).map(|d| d.full_def()) { + ast::ExprPath(..) => { + match self.def_map.borrow().get(&e.id).map(|d| d.base_def) { Some(DefStatic(def_id, _)) | Some(DefConst(def_id)) if ast_util::is_local(def_id) => { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index d3c6a585fa3fd..f793d3ce2fb45 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -178,7 +178,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P ast::PatVec(pats, None, vec![]) } - ast::ExprPath(ref path) => { + ast::ExprPath(_, ref path) => { let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()); match opt_def { Some(def::DefStruct(..)) => @@ -194,13 +194,6 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P } } - ast::ExprQPath(_) => { - match lookup_const(tcx, expr) { - Some(actual) => return const_expr_to_pat(tcx, actual, span), - _ => unreachable!() - } - } - _ => ast::PatLit(P(expr.clone())) }; P(ast::Pat { id: expr.id, node: pat, span: span }) @@ -388,7 +381,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint))); cast_const(val, ety) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); let (const_expr, const_ty) = match opt_def { Some(def::DefConst(def_id)) => { diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index ba81b2f3899a8..9c85b7748ab0c 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { ast::ExprInlineAsm(..) => { self.require_unsafe(expr.span, "use of inline assembly"); } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) { self.require_unsafe(expr.span, "use of mutable static"); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index f7c723c68746f..a1e38a1c8bda7 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -422,7 +422,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { self.walk_expr(&**subexpr) } - ast::ExprPath(_) | ast::ExprQPath(_) => { } + ast::ExprPath(..) => { } ast::ExprUnary(ast::UnDeref, ref base) => { // *base if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) { diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 60b7e1169b49b..da4df813030c3 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -1233,7 +1233,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } ty_queue.push(&*mut_ty.ty); } - ast::TyPath(ref path) => { + ast::TyPath(ref maybe_qself, ref path) => { let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) { None => { self.tcx @@ -1277,9 +1277,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { region_names: region_names }; let new_path = self.rebuild_path(rebuild_info, lifetime); + let qself = maybe_qself.as_ref().map(|qself| { + ast::QSelf { + ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime, + anon_nums, region_names), + position: qself.position + } + }); let to = ast::Ty { id: cur_ty.id, - node: ast::TyPath(new_path), + node: ast::TyPath(qself, new_path), span: cur_ty.span }; new_ty = self.rebuild_ty(new_ty, P(to)); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 4685a05f41604..2ac019aa964dc 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -445,7 +445,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) { fn visit_expr(ir: &mut IrMaps, expr: &Expr) { match expr.node { // live nodes required for uses or definitions of variables: - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = ir.tcx.def_map.borrow()[expr.id].full_def(); debug!("expr {}: path that leads to {:?}", expr.id, def); if let DefLocal(..) = def { @@ -947,7 +947,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match expr.node { // Interesting cases with control flow or which gen/kill - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { self.access_path(expr, succ, ACC_READ | ACC_USE) } @@ -1275,7 +1275,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // just ignore such cases and treat them as reads. match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => succ, + ast::ExprPath(..) => succ, ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ), ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ), _ => self.propagate_through_expr(expr, succ) @@ -1286,7 +1286,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint) -> LiveNode { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { self.access_path(expr, succ, acc) } @@ -1468,7 +1468,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) | ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) | - ast::ExprRange(..) | ast::ExprQPath(..) => { + ast::ExprRange(..) => { visit::walk_expr(this, expr); } ast::ExprIfLet(..) => { @@ -1561,7 +1561,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_lvalue(&mut self, expr: &Expr) { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 44ab3cf60aaa3..c4446b87855ca 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -529,7 +529,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = self.tcx().def_map.borrow()[expr.id].full_def(); self.cat_def(expr.id, expr.span, expr_ty, def) } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index a140c766758e3..45d565ec69380 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { fn visit_expr(&mut self, expr: &ast::Expr) { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = match self.tcx.def_map.borrow().get(&expr.id) { Some(d) => d.full_def(), None => { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 9bcda68eb3ad7..a8a2887644a9d 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -165,7 +165,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { visit::walk_ty(this, ty); }); } - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7cd047279028c..7b05e51085279 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4550,7 +4550,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { } match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { match resolve_expr(tcx, expr) { def::DefVariant(tid, vid, _) => { let variant_info = enum_variant_with_id(tcx, tid, vid); @@ -5838,7 +5838,7 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { } Err(_) => { let found = match count_expr.node { - ast::ExprPath(ast::Path { + ast::ExprPath(None, ast::Path { global: false, ref segments, .. diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 2fc43ab26b58e..e16df61c25c47 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -244,8 +244,7 @@ mod svh_visitor { SawExprAssignOp(ast::BinOp_), SawExprIndex, SawExprRange, - SawExprPath, - SawExprQPath, + SawExprPath(Option), SawExprAddrOf(ast::Mutability), SawExprRet, SawExprInlineAsm(&'a ast::InlineAsm), @@ -277,8 +276,7 @@ mod svh_visitor { ExprTupField(_, id) => SawExprTupField(id.node), ExprIndex(..) => SawExprIndex, ExprRange(..) => SawExprRange, - ExprPath(..) => SawExprPath, - ExprQPath(..) => SawExprQPath, + ExprPath(ref qself, _) => SawExprPath(qself.as_ref().map(|q| q.position)), ExprAddrOf(m, _) => SawExprAddrOf(m), ExprBreak(id) => SawExprBreak(id.map(content)), ExprAgain(id) => SawExprAgain(id.map(content)), diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f325a6abede51..29448c68c80b9 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -258,7 +258,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // * Private trait impls for private types can be completely ignored ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => { let public_ty = match ty.node { - ast::TyPath(_) => { + ast::TyPath(..) => { match self.tcx.def_map.borrow()[ty.id].full_def() { def::DefPrimTy(..) => true, def => { @@ -325,7 +325,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { } ast::ItemTy(ref ty, _) if public_first => { - if let ast::TyPath(_) = ty.node { + if let ast::TyPath(..) = ty.node { match self.tcx.def_map.borrow()[ty.id].full_def() { def::DefPrimTy(..) | def::DefTyParam(..) => {}, def => { @@ -627,7 +627,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // was private. ast::ItemImpl(_, _, _, _, ref ty, _) => { match ty.node { - ast::TyPath(_) => {} + ast::TyPath(..) => {} _ => return Some((err_span, err_msg, None)), }; let def = self.tcx.def_map.borrow()[ty.id].full_def(); @@ -908,7 +908,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { struct type?!"), } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let guard = |did: ast::DefId| { let fields = ty::lookup_struct_fields(self.tcx, did); let any_priv = fields.iter().any(|f| { @@ -1254,7 +1254,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - if let ast::TyPath(_) = ty.node { + if let ast::TyPath(..) = ty.node { if self.inner.path_is_private_type(ty.id) { self.contains_private = true; // found what we're looking for so let's stop @@ -1460,7 +1460,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_ty(&mut self, t: &ast::Ty) { - if let ast::TyPath(ref p) = t.node { + if let ast::TyPath(_, ref p) = t.node { if !self.tcx.sess.features.borrow().visible_private_types && self.path_is_private_type(t.id) { self.tcx.sess.span_err(p.span, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 265f398d25ca5..cb7224f7cbfe8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -65,7 +65,7 @@ use rustc::util::lev_distance::lev_distance; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall}; -use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; +use syntax::ast::{ExprPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; @@ -75,7 +75,7 @@ use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; use syntax::ast::{PatRange, PatStruct, Path, PrimTy}; use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32}; use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt}; -use syntax::ast::{TyPath, TyPtr, TyQPath}; +use syntax::ast::{TyPath, TyPtr}; use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint}; use syntax::ast::{TypeImplItem}; use syntax::ast; @@ -2821,7 +2821,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { FnSpace, MethodRibKind) } - ast::TypeTraitItem(_) => NoTypeParameters, + ast::TypeTraitItem(ref assoc_ty) => { + let ty_param = &assoc_ty.ty_param; + this.check_if_primitive_type_name(ty_param.ident.name, + ty_param.span); + NoTypeParameters + } }; this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) @@ -3243,14 +3248,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_type(&mut self, ty: &Ty) { match ty.node { - // Like path expressions, the interpretation of path types depends - // on whether the path has multiple elements in it or not. + // `::a::b::c` is resolved by typeck alone. + TyPath(Some(ast::QSelf { position: 0, .. }), _) => {} - TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => { - let max_assoc_types = if let TyQPath(_) = ty.node { + TyPath(ref maybe_qself, ref path) => { + let max_assoc_types = if let Some(ref qself) = *maybe_qself { // Make sure the trait is valid. let _ = self.resolve_trait_reference(ty.id, path, 1); - 1 + path.segments.len() - qself.position } else { path.segments.len() }; @@ -3284,10 +3289,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Keep reporting some errors even if they're ignored above. self.resolve_path(ty.id, path, 0, TypeNS, true); - let kind = match ty.node { - TyQPath(_) => "associated type", - _ => "type name" + let kind = if maybe_qself.is_some() { + "associated type" + } else { + "type name" }; + let msg = format!("use of undeclared {} `{}`", kind, self.path_names_to_string(path, 0)); self.resolve_error(ty.span, &msg[..]); @@ -3905,7 +3912,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) -> Option<(Path, NodeId, FallbackChecks)> { match t.node { - TyPath(ref path) => Some((path.clone(), t.id, allow)), + TyPath(None, ref path) => Some((path.clone(), t.id, allow)), TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics), TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow), // This doesn't handle the remaining `Ty` variants as they are not @@ -4063,14 +4070,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Next, resolve the node. match expr.node { - // The interpretation of paths depends on whether the path has - // multiple elements in it or not. + // `::a::b::c` is resolved by typeck alone. + ExprPath(Some(ast::QSelf { position: 0, .. }), ref path) => { + let method_name = path.segments.last().unwrap().identifier.name; + let traits = self.search_for_traits_containing_method(method_name); + self.trait_map.insert(expr.id, traits); + visit::walk_expr(self, expr); + } - ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => { - let max_assoc_types = if let ExprQPath(_) = expr.node { + ExprPath(ref maybe_qself, ref path) => { + let max_assoc_types = if let Some(ref qself) = *maybe_qself { // Make sure the trait is valid. let _ = self.resolve_trait_reference(expr.id, path, 1); - 1 + path.segments.len() - qself.position } else { path.segments.len() }; diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index ea346798679c0..ab7f3916728c5 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -659,7 +659,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id)); match typ.node { // Common case impl for a struct or something basic. - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { let sub_span = self.span.sub_span_for_type_name(path.span); let self_id = self.lookup_type_ref(typ.id).map(|id| { self.fmt.ref_str(recorder::TypeRef, @@ -1306,7 +1306,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } match t.node { - ast::TyPath(ref path) => { + ast::TyPath(_, ref path) => { match self.lookup_type_ref(t.id) { Some(id) => { let sub_span = self.span.sub_span_for_type_name(t.span); @@ -1338,7 +1338,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { // because just walking the callee path does what we want. visit::walk_expr(self, ex); } - ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => { + ast::ExprPath(_, ref path) => { self.process_path(ex.id, path.span, path, None); visit::walk_expr(self, ex); } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 3e741640117aa..9a121a8830b2b 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -1277,7 +1277,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body` fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool { let (vid, field) = match discr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) { + ast::ExprPath(..) => match bcx.def(discr.id) { def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None), _ => return false }, diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 41e3d4b5bab25..59fcd5492ebde 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -93,7 +93,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) // pick out special kinds of expressions that can be called: match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { return trans_def(bcx, bcx.def(expr.id), expr); } _ => {} diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 6e1d2da02c101..93ab4a96e6f56 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -193,7 +193,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> ValueRef { // Special-case constants to cache a common global for all uses. match expr.node { - ast::ExprPath(_) => { + ast::ExprPath(..) => { let def = ccx.tcx().def_map.borrow()[expr.id].full_def(); match def { def::DefConst(def_id) => { @@ -663,7 +663,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, C_array(llunitty, &vs[..]) } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = cx.tcx().def_map.borrow()[e.id].full_def(); match def { def::DefFn(..) | def::DefMethod(..) => { diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 162881f58c74e..d70a904b81189 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3487,8 +3487,7 @@ fn create_scope_map(cx: &CrateContext, ast::ExprLit(_) | ast::ExprBreak(_) | ast::ExprAgain(_) | - ast::ExprPath(_) | - ast::ExprQPath(_) => {} + ast::ExprPath(..) => {} ast::ExprCast(ref sub_exp, _) | ast::ExprAddrOf(_, ref sub_exp) | diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 80fe2ed8f3af3..5cc1baf66c621 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -143,7 +143,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // it prefers in-place instantiation, likely because it contains // `[x; N]` somewhere within. match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { match bcx.def(expr.id) { def::DefConst(did) => { let expr = consts::get_const_expr(bcx.ccx(), did, expr); @@ -629,7 +629,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprParen(ref e) => { trans(bcx, &**e) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { trans_def(bcx, expr, bcx.def(expr.id)) } ast::ExprField(ref base, ident) => { @@ -1033,7 +1033,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprParen(ref e) => { trans_into(bcx, &**e, dest) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest) } ast::ExprIf(ref cond, ref thn, ref els) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 982cc1e3792e1..602f041222f27 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -52,6 +52,7 @@ use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS}; use middle::const_eval; use middle::def; use middle::resolve_lifetime as rl; +use middle::privacy::{AllPublic, LastMod}; use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; use middle::traits; use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; @@ -897,7 +898,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, */ match ty.node { - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { let def = this.tcx().def_map.borrow().get(&ty.id).map(|d| d.full_def()); match def { Some(def::DefTrait(trait_def_id)) => { @@ -981,7 +982,13 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); let assoc_name = item_segment.identifier.name; - let ty_param_node_id = if let ty::ty_param(_) = ty.sty { + let is_param = match (&ty.sty, ty_path_def) { + (&ty::ty_param(_), def::DefTyParam(..)) | + (&ty::ty_param(_), def::DefSelfTy(_)) => true, + _ => false + }; + + let ty_param_node_id = if is_param { ty_path_def.local_node_id() } else { span_err!(tcx.sess, span, E0223, @@ -1195,9 +1202,14 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, segments.last().unwrap()) } def::DefMod(id) => { - tcx.sess.span_bug(span, - &format!("found module name used as a type: {}", - tcx.map.node_to_string(id.node))); + // Used as sentinel by callers to indicate the `::a::b::c` form. + if segments.is_empty() { + opt_self_ty.expect("missing T in ::a::b::c") + } else { + tcx.sess.span_bug(span, + &format!("found module name used as a type: {}", + tcx.map.node_to_string(id.node))); + } } def::DefPrimTy(prim_ty) => { prim_ty_to_ty(tcx, segments, prim_ty) @@ -1302,20 +1314,25 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds) } - ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { + ast::TyPath(ref maybe_qself, ref path) => { let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { d + } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself { + // Create some fake resolution that can't possibly be a type. + def::PathResolution { + base_def: def::DefMod(ast_util::local_def(ast::CRATE_NODE_ID)), + last_private: LastMod(AllPublic), + depth: path.segments.len() + } } else { tcx.sess.span_bug(ast_ty.span, &format!("unbound path {}", ast_ty.repr(tcx))) }; let mut def = path_res.base_def; let base_ty_end = path.segments.len() - path_res.depth; - let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { - Some(ast_ty_to_ty(this, rscope, &*qpath.self_type)) - } else { - None - }; + let opt_self_ty = maybe_qself.as_ref().map(|qself| { + ast_ty_to_ty(this, rscope, &qself.ty) + }); let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span, PathParamMode::Explicit, &mut def, opt_self_ty, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f99e4e4b2ed8a..f5d6d5baf9380 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -91,6 +91,7 @@ use middle::infer; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::pat_util::{self, pat_id_map}; +use middle::privacy::{AllPublic, LastMod}; use middle::region::{self, CodeExtent}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; use middle::traits; @@ -3397,7 +3398,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let mut checked = false; opt_place.as_ref().map(|place| match place.node { - ast::ExprPath(ref path) => { + ast::ExprPath(None, ref path) => { // FIXME(pcwalton): For now we hardcode the two permissible // places: the exchange heap and the managed heap. let definition = lookup_def(fcx, path.span, place.id); @@ -3590,16 +3591,21 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }; fcx.write_ty(id, oprnd_t); } - ast::ExprPath(ref path) | ast::ExprQPath(ast::QPath { ref path, .. }) => { - let opt_self_ty = if let ast::ExprQPath(ref qpath) = expr.node { - Some(fcx.to_ty(&*qpath.self_type)) - } else { - None - }; + ast::ExprPath(ref maybe_qself, ref path) => { + let opt_self_ty = maybe_qself.as_ref().map(|qself| { + fcx.to_ty(&qself.ty) + }); let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) { d - } else { + } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself { + // Create some fake resolution that can't possibly be a type. + def::PathResolution { + base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)), + last_private: LastMod(AllPublic), + depth: path.segments.len() + } + } else { tcx.sess.span_bug(expr.span, &format!("unbound path {}", expr.repr(tcx))[]) }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 976c794735fbb..7ed372d1b4b03 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1683,20 +1683,15 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, index: u32) -> bool { - match ast_ty.node { - ast::TyPath(_) => { - match ccx.tcx.def_map.borrow()[ast_ty.id] { - def::DefTyParam(s, i, _, _) => { - space == s && index == i - } - _ => { - false - } - } - } - _ => { + if let ast::TyPath(None, _) = ast_ty.node { + let path_res = ccx.tcx.def_map.borrow()[ast_ty.id]; + if let def::DefTyParam(s, i, _, _) = path_res.base_def { + path_res.depth == 0 && space == s && index == i + } else { false } + } else { + false } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0aa1a23ad7e76..b88620d577f37 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1494,15 +1494,15 @@ impl Clean for ast::Ty { TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx), e.span.to_src(cx)), TyTup(ref tys) => Tuple(tys.clean(cx)), - TyPath(ref p) => { + TyPath(None, ref p) => { resolve_type(cx, p.clean(cx), self.id) } - TyQPath(ref qp) => { - let mut trait_path = qp.path.clone(); + TyPath(Some(ref qself), ref p) => { + let mut trait_path = p.clone(); trait_path.segments.pop(); Type::QPath { - name: qp.path.segments.last().unwrap().identifier.clean(cx), - self_type: box qp.self_type.clean(cx), + name: p.segments.last().unwrap().identifier.clean(cx), + self_type: box qself.ty.clean(cx), trait_: box resolve_type(cx, trait_path.clean(cx), self.id) } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 80a5527cb948d..6d6fdffa95095 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -753,11 +753,10 @@ pub enum Expr_ { ExprIndex(P, P), ExprRange(Option>, Option>), - /// Variable reference, possibly containing `::` and/or - /// type parameters, e.g. foo::bar:: - ExprPath(Path), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - ExprQPath(QPath), + /// Variable reference, possibly containing `::` and/or type + /// parameters, e.g. foo::bar::. Optionally "qualified", + /// e.g. ` as SomeTrait>::SomeType`. + ExprPath(Option, Path), ExprAddrOf(Mutability, P), ExprBreak(Option), @@ -778,15 +777,22 @@ pub enum Expr_ { ExprParen(P) } -/// A "qualified path": +/// The explicit Self type in a "qualified path". The actual +/// path, including the trait and the associated item, is stored +/// sepparately. `position` represents the index of the associated +/// item qualified with this Self type. /// -/// as SomeTrait>::SomeAssociatedItem -/// ^~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/// self_type path +/// as a::b::Trait>::AssociatedItem +/// ^~~~~ ~~~~~~~~~~~~~~^ +/// ty position = 3 +/// +/// >::AssociatedItem +/// ^~~~~ ^ +/// ty position = 0 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct QPath { - pub self_type: P, - pub path: Path, +pub struct QSelf { + pub ty: P, + pub position: usize } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -1253,12 +1259,11 @@ pub enum Ty_ { TyBareFn(P), /// A tuple (`(A, B, C, D,...)`) TyTup(Vec> ), - /// A path (`module::module::...::Type`) or primitive + /// A path (`module::module::...::Type`), optionally + /// "qualified", e.g. ` as SomeTrait>::SomeType`. /// /// Type parameters are stored in the Path itself - TyPath(Path), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - TyQPath(QPath), + TyPath(Option, Path), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f207efc5b6c34..79f0433761da5 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -134,7 +134,7 @@ pub fn unop_to_string(op: UnOp) -> &'static str { } pub fn is_path(e: P) -> bool { - return match e.node { ExprPath(_) => true, _ => false }; + match e.node { ExprPath(..) => true, _ => false } } /// Get a string representation of a signed int type, with its value. diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 90842bbab47d2..d916651b05617 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -43,14 +43,14 @@ pub trait AstBuilder { fn qpath(&self, self_type: P, trait_path: ast::Path, ident: ast::Ident) - -> ast::QPath; + -> (ast::QSelf, ast::Path); fn qpath_all(&self, self_type: P, trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, bindings: Vec>) - -> ast::QPath; + -> (ast::QSelf, ast::Path); // types fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; @@ -114,7 +114,7 @@ pub trait AstBuilder { // expressions fn expr(&self, span: Span, node: ast::Expr_) -> P; fn expr_path(&self, path: ast::Path) -> P; - fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P; + fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P; fn expr_ident(&self, span: Span, id: ast::Ident) -> P; fn expr_self(&self, span: Span) -> P; @@ -351,7 +351,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self_type: P, trait_path: ast::Path, ident: ast::Ident) - -> ast::QPath { + -> (ast::QSelf, ast::Path) { self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) } @@ -365,7 +365,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { lifetimes: Vec, types: Vec>, bindings: Vec>) - -> ast::QPath { + -> (ast::QSelf, ast::Path) { let mut path = trait_path; path.segments.push(ast::PathSegment { identifier: ident, @@ -376,10 +376,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }) }); - ast::QPath { - self_type: self_type, - path: path - } + (ast::QSelf { + ty: self_type, + position: path.segments.len() - 1 + }, path) } fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { @@ -398,7 +398,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn ty_path(&self, path: ast::Path) -> P { - self.ty(path.span, ast::TyPath(path)) + self.ty(path.span, ast::TyPath(None, path)) } fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice) -> P { @@ -603,12 +603,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_path(&self, path: ast::Path) -> P { - self.expr(path.span, ast::ExprPath(path)) + self.expr(path.span, ast::ExprPath(None, path)) } /// Constructs a QPath expression. - fn expr_qpath(&self, span: Span, qpath: ast::QPath) -> P { - self.expr(span, ast::ExprQPath(qpath)) + fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P { + self.expr(span, ast::ExprPath(Some(qself), path)) } fn expr_ident(&self, span: Span, id: ast::Ident) -> P { diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 9410a51e7a5f6..2303eb9645b64 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -53,7 +53,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] let e = P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath( + node: ast::ExprPath(None, ast::Path { span: sp, global: false, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index f7014d6cc3c00..b6e7b309f356c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -41,7 +41,7 @@ pub fn expand_type(t: P, debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty); let t = match (t.node.clone(), impl_ty) { // Expand uses of `Self` in impls to the concrete type. - (ast::Ty_::TyPath(ref path), Some(ref impl_ty)) => { + (ast::Ty_::TyPath(None, ref path), Some(ref impl_ty)) => { let path_as_ident = path_to_ident(path); // Note unhygenic comparison here. I think this is correct, since // even though `Self` is almost just a type parameter, the treatment @@ -1594,13 +1594,10 @@ mod test { impl<'v> Visitor<'v> for PathExprFinderContext { fn visit_expr(&mut self, expr: &ast::Expr) { - match expr.node { - ast::ExprPath(ref p) => { - self.path_accumulator.push(p.clone()); - // not calling visit_path, but it should be fine. - } - _ => visit::walk_expr(self, expr) + if let ast::ExprPath(None, ref p) = expr.node { + self.path_accumulator.push(p.clone()); } + visit::walk_expr(self, expr); } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4efae84fea5ae..32fd5b49f9a44 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -549,7 +549,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, t: &ast::Ty) { match t.node { - ast::TyPath(ref p) => { + ast::TyPath(None, ref p) => { match &*p.segments { [ast::PathSegment { identifier, .. }] => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index c706ce9065dd5..a556b2dfd2a99 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -424,12 +424,14 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { } TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), - TyPath(path) => TyPath(fld.fold_path(path)), - TyQPath(qpath) => { - TyQPath(QPath { - self_type: fld.fold_ty(qpath.self_type), - path: fld.fold_path(qpath.path) - }) + TyPath(qself, path) => { + let qself = qself.map(|QSelf { ty, position }| { + QSelf { + ty: fld.fold_ty(ty), + position: position + } + }); + TyPath(qself, fld.fold_path(path)) } TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), @@ -1347,11 +1349,15 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> ExprRange(e1.map(|x| folder.fold_expr(x)), e2.map(|x| folder.fold_expr(x))) } - ExprPath(pth) => ExprPath(folder.fold_path(pth)), - ExprQPath(qpath) => ExprQPath(QPath { - self_type: folder.fold_ty(qpath.self_type), - path: folder.fold_path(qpath.path) - }), + ExprPath(qself, path) => { + let qself = qself.map(|QSelf { ty, position }| { + QSelf { + ty: folder.fold_ty(ty), + position: position + } + }); + ExprPath(qself, folder.fold_path(path)) + } ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index d4c66529e77df..4d099529cb49a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -774,7 +774,7 @@ mod test { assert!(string_to_expr("a".to_string()) == P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 1), global: false, segments: vec!( @@ -792,7 +792,7 @@ mod test { assert!(string_to_expr("::a::b".to_string()) == P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 6), global: true, segments: vec!( @@ -974,7 +974,7 @@ mod test { id: ast::DUMMY_NODE_ID, node:ast::ExprRet(Some(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node:ast::ExprPath(ast::Path{ + node:ast::ExprPath(None, ast::Path{ span: sp(7, 8), global: false, segments: vec!( @@ -995,7 +995,7 @@ mod test { P(Spanned{ node: ast::StmtExpr(P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span:sp(0,1), global:false, segments: vec!( @@ -1041,7 +1041,7 @@ mod test { node: ast::ItemFn(P(ast::FnDecl { inputs: vec!(ast::Arg{ ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, - node: ast::TyPath(ast::Path{ + node: ast::TyPath(None, ast::Path{ span:sp(10,13), global:false, segments: vec!( @@ -1084,7 +1084,7 @@ mod test { stmts: vec!(P(Spanned{ node: ast::StmtSemi(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath( + node: ast::ExprPath(None, ast::Path{ span:sp(17,18), global:false, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ad290da7d0a62..f171e8279f49c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -25,7 +25,7 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex}; use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; -use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath}; +use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; @@ -43,7 +43,7 @@ use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; use ast::{PolyTraitRef}; -use ast::{QPath, RequiredMethod}; +use ast::{QSelf, RequiredMethod}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; use ast::{StructVariantKind, BiSub, StrStyle}; @@ -53,7 +53,7 @@ use ast::{TtDelimited, TtSequence, TtToken}; use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; use ast::{TyFixedLengthVec, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; -use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; +use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef,}; use ast::{UnnamedField, UnsafeBlock}; @@ -143,7 +143,7 @@ macro_rules! maybe_whole_expr { _ => unreachable!() }; let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprPath(pt))) + Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt))) } token::Interpolated(token::NtBlock(_)) => { // FIXME: The following avoids an issue with lexical borrowck scopes, @@ -1076,7 +1076,7 @@ impl<'a> Parser<'a> { } pub fn parse_ty_path(&mut self) -> Ty_ { - TyPath(self.parse_path(LifetimeAndTypesWithoutColons)) + TyPath(None, self.parse_path(LifetimeAndTypesWithoutColons)) } /// parse a TyBareFn type: @@ -1524,15 +1524,36 @@ impl<'a> Parser<'a> { } else if self.eat_lt() { // QUALIFIED PATH `::item` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let mut path = self.parse_path(LifetimeAndTypesWithoutColons); + + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; + self.expect(&token::Gt); self.expect(&token::ModSep); + path.segments.push(ast::PathSegment { identifier: self.parse_ident(), parameters: ast::PathParameters::none() }); - TyQPath(QPath { self_type: self_type, path: path }) + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + + TyPath(Some(qself), path) } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -2173,7 +2194,7 @@ impl<'a> Parser<'a> { }, token::Plain) => { self.bump(); let path = ast_util::ident_to_path(mk_sp(lo, hi), id); - ex = ExprPath(path); + ex = ExprPath(None, path); hi = self.last_span.hi; } token::OpenDelim(token::Bracket) => { @@ -2215,10 +2236,22 @@ impl<'a> Parser<'a> { if self.eat_lt() { // QUALIFIED PATH `::item::<'a, T>` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let mut path = self.parse_path(LifetimeAndTypesWithoutColons); + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; self.expect(&token::Gt); self.expect(&token::ModSep); + let item_name = self.parse_ident(); let parameters = if self.eat(&token::ModSep) { self.expect_lt(); @@ -2237,9 +2270,14 @@ impl<'a> Parser<'a> { identifier: item_name, parameters: parameters }); + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + let hi = self.span.hi; - return self.mk_expr(lo, hi, - ExprQPath(QPath { self_type: self_type, path: path })); + return self.mk_expr(lo, hi, ExprPath(Some(qself), path)); } if self.eat_keyword(keywords::Move) { return self.parse_lambda_expr(CaptureByValue); @@ -2379,7 +2417,7 @@ impl<'a> Parser<'a> { } hi = pth.span.hi; - ex = ExprPath(pth); + ex = ExprPath(None, pth); } else { // other literal expression let lit = self.parse_lit(); @@ -3421,7 +3459,7 @@ impl<'a> Parser<'a> { let end = if self.token.is_ident() || self.token.is_path() { let path = self.parse_path(LifetimeAndTypesWithColons); let hi = self.span.hi; - self.mk_expr(lo, hi, ExprPath(path)) + self.mk_expr(lo, hi, ExprPath(None, path)) } else { self.parse_literal_maybe_minus() }; @@ -4808,7 +4846,7 @@ impl<'a> Parser<'a> { let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. match ty.node { - TyPath(ref path) => { + TyPath(None, ref path) => { Some(TraitRef { path: (*path).clone(), ref_id: ty.id, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 11502c29ebb15..78b9487d1c98b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -729,11 +729,11 @@ impl<'a> State<'a> { &generics, None)); } - ast::TyPath(ref path) => { + ast::TyPath(None, ref path) => { try!(self.print_path(path, false, 0)); } - ast::TyQPath(ref qpath) => { - try!(self.print_qpath(qpath, false)) + ast::TyPath(Some(ref qself), ref path) => { + try!(self.print_qpath(path, qself, false)) } ast::TyObjectSum(ref ty, ref bounds) => { try!(self.print_type(&**ty)); @@ -1852,8 +1852,12 @@ impl<'a> State<'a> { try!(self.print_expr(&**e)); } } - ast::ExprPath(ref path) => try!(self.print_path(path, true, 0)), - ast::ExprQPath(ref qpath) => try!(self.print_qpath(qpath, true)), + ast::ExprPath(None, ref path) => { + try!(self.print_path(path, true, 0)) + } + ast::ExprPath(Some(ref qself), ref path) => { + try!(self.print_qpath(path, qself, true)) + } ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); try!(space(&mut self.s)); @@ -2037,18 +2041,19 @@ impl<'a> State<'a> { } fn print_qpath(&mut self, - qpath: &ast::QPath, + path: &ast::Path, + qself: &ast::QSelf, colons_before_params: bool) -> IoResult<()> { try!(word(&mut self.s, "<")); - try!(self.print_type(&*qpath.self_type)); + try!(self.print_type(&qself.ty)); try!(space(&mut self.s)); try!(self.word_space("as")); - try!(self.print_path(&qpath.path, false, 1)); + try!(self.print_path(&path, false, 1)); try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); - let item_segment = qpath.path.segments.last().unwrap(); + let item_segment = path.segments.last().unwrap(); try!(self.print_ident(item_segment.identifier)); self.print_path_parameters(&item_segment.parameters, colons_before_params) } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 55372585062d8..33d8d56b4b114 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -396,13 +396,12 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_fn_ret_ty(visitor, &function_declaration.decl.output); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyPath(ref path) => { + TyPath(ref maybe_qself, ref path) => { + if let Some(ref qself) = *maybe_qself { + visitor.visit_ty(&qself.ty); + } visitor.visit_path(path, typ.id); } - TyQPath(ref qpath) => { - visitor.visit_ty(&*qpath.self_type); - visitor.visit_path(&qpath.path, typ.id); - } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); walk_ty_param_bounds_helper(visitor, bounds); @@ -859,13 +858,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } - ExprPath(ref path) => { + ExprPath(ref maybe_qself, ref path) => { + if let Some(ref qself) = *maybe_qself { + visitor.visit_ty(&qself.ty); + } visitor.visit_path(path, expression.id) } - ExprQPath(ref qpath) => { - visitor.visit_ty(&*qpath.self_type); - visitor.visit_path(&qpath.path, expression.id); - } ExprBreak(_) | ExprAgain(_) => {} ExprRet(ref optional_expression) => { walk_expr_opt(visitor, optional_expression) diff --git a/src/test/run-pass/ufcs-polymorphic-paths.rs b/src/test/run-pass/ufcs-polymorphic-paths.rs index 277aaf086f419..29b1c8f81d3c6 100644 --- a/src/test/run-pass/ufcs-polymorphic-paths.rs +++ b/src/test/run-pass/ufcs-polymorphic-paths.rs @@ -61,8 +61,10 @@ tests! { // Inherent static methods. Vec::new, fn() -> Vec<()>, (); Vec::<()>::new, fn() -> Vec<()>, (); + >::new, fn() -> Vec<()>, (); Vec::with_capacity, fn(usize) -> Vec<()>, (5); Vec::<()>::with_capacity, fn(usize) -> Vec<()>, (5); + >::with_capacity, fn(usize) -> Vec<()>, (5); BitVec::from_fn, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); BitVec::from_fn:: bool>, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); @@ -78,26 +80,32 @@ tests! { // Trait static methods. bool::size, fn() -> usize, (); + ::size, fn() -> usize, (); ::size, fn() -> usize, (); Default::default, fn() -> i32, (); i32::default, fn() -> i32, (); + ::default, fn() -> i32, (); ::default, fn() -> i32, (); Rand::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); i32::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); Rand::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); i32::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); // Trait non-static methods. Clone::clone, fn(&i32) -> i32, (&5); i32::clone, fn(&i32) -> i32, (&5); + ::clone, fn(&i32) -> i32, (&5); ::clone, fn(&i32) -> i32, (&5); FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); Vec::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + >::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, @@ -109,11 +117,14 @@ tests! { Add::add, fn(i32, i32) -> i32, (5, 6); i32::add, fn(i32, i32) -> i32, (5, 6); + ::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); String::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); + ::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, From 09ad993a259006c41bd63f14ad68b3a99e365e94 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 19 Feb 2015 03:37:25 +0200 Subject: [PATCH 18/25] tests: add two new run-pass tests for method behavior after UFCS. --- .../run-pass/impl-inherent-non-conflict.rs | 31 +++++++++++++++ .../impl-inherent-prefer-over-trait.rs | 38 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/test/run-pass/impl-inherent-non-conflict.rs create mode 100644 src/test/run-pass/impl-inherent-prefer-over-trait.rs diff --git a/src/test/run-pass/impl-inherent-non-conflict.rs b/src/test/run-pass/impl-inherent-non-conflict.rs new file mode 100644 index 0000000000000..663ed24d60e48 --- /dev/null +++ b/src/test/run-pass/impl-inherent-non-conflict.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Ensure that an user-defined type admits multiple inherent methods +// with the same name, which can be called on values that have a +// precise enough type to allow distinguishing between the methods. + +struct Foo(T); + +impl Foo { + fn bar(&self) -> i32 { self.0 as i32 } +} + +impl Foo { + fn bar(&self) -> i32 { -(self.0 as i32) } +} + +fn main() { + let foo_u = Foo::(5); + assert_eq!(foo_u.bar(), 5); + + let foo_i = Foo::(3); + assert_eq!(foo_i.bar(), -3); +} diff --git a/src/test/run-pass/impl-inherent-prefer-over-trait.rs b/src/test/run-pass/impl-inherent-prefer-over-trait.rs new file mode 100644 index 0000000000000..3031228b3ab44 --- /dev/null +++ b/src/test/run-pass/impl-inherent-prefer-over-trait.rs @@ -0,0 +1,38 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo; + +trait Trait { + fn bar(&self); +} + +// Inherent impls should be preferred over trait ones. +impl Foo { + fn bar(&self) {} +} + +impl Trait { + fn baz(_: &Foo) {} +} + +impl Trait for Foo { + fn bar(&self) { panic!("wrong method called!") } +} + +fn main() { + Foo.bar(); + Foo::bar(&Foo); + ::bar(&Foo); + + // Should work even if Trait::baz doesn't exist. + // N.B: `::bar` would be ambiguous. + ::baz(&Foo); +} From 923616e1882bdec30f491306d80f5db4162a03d7 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 20 Feb 2015 08:06:10 +0200 Subject: [PATCH 19/25] Fix @nikomatsakis' nits in typeck. --- src/librustc_typeck/astconv.rs | 14 ++++++++---- src/librustc_typeck/check/mod.rs | 39 ++++++++++++-------------------- src/librustc_typeck/lib.rs | 10 +++----- 3 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 602f041222f27..9e50fdb4c4815 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -622,7 +622,7 @@ pub fn instantiate_trait_ref<'tcx>( -> Rc> { let path = &trait_ref.path; - match ::lookup_def_tcx(this.tcx(), path.span, trait_ref.ref_id) { + match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) { def::DefTrait(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, @@ -899,7 +899,10 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, match ty.node { ast::TyPath(None, ref path) => { - let def = this.tcx().def_map.borrow().get(&ty.id).map(|d| d.full_def()); + let def = match this.tcx().def_map.borrow().get(&ty.id) { + Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def), + _ => None + }; match def { Some(def::DefTrait(trait_def_id)) => { let mut projection_bounds = Vec::new(); @@ -1202,7 +1205,10 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, segments.last().unwrap()) } def::DefMod(id) => { - // Used as sentinel by callers to indicate the `::a::b::c` form. + // Used as sentinel by callers to indicate the `::A::B::C` form. + // FIXME(#22519) This part of the resolution logic should be + // avoided entirely for that form, once we stop needed a Def + // for `associated_path_def_to_ty`. if segments.is_empty() { opt_self_ty.expect("missing T in ::a::b::c") } else { @@ -1890,7 +1896,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, for ast_bound in ast_bounds { match *ast_bound { ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => { - match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { + match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { def::DefTrait(trait_did) => { match trait_def_ids.get(&trait_did) { // Already seen this trait. We forbid diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f5d6d5baf9380..f56df4570b364 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -103,7 +103,7 @@ use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap}; use middle::ty_fold::{TypeFolder, TypeFoldable}; use rscope::RegionScope; use session::Session; -use {CrateCtxt, lookup_def_ccx, require_same_types}; +use {CrateCtxt, lookup_full_def, require_same_types}; use TypeAndSubsts; use lint; use util::common::{block_query, indenter, loop_query}; @@ -3401,7 +3401,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ast::ExprPath(None, ref path) => { // FIXME(pcwalton): For now we hardcode the two permissible // places: the exchange heap and the managed heap. - let definition = lookup_def(fcx, path.span, place.id); + let definition = lookup_full_def(tcx, path.span, place.id); let def_id = definition.def_id(); let referent_ty = fcx.expr_ty(&**subexpr); if tcx.lang_items.exchange_heap() == Some(def_id) { @@ -3884,14 +3884,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprStruct(ref path, ref fields, ref base_expr) => { // Resolve the path. - let def = tcx.def_map.borrow().get(&id).map(|d| d.full_def()); + let def = lookup_full_def(tcx, path.span, id); let struct_id = match def { - Some(def::DefVariant(enum_id, variant_id, true)) => { + def::DefVariant(enum_id, variant_id, true) => { check_struct_enum_variant(fcx, id, expr.span, enum_id, variant_id, &fields[..]); enum_id } - Some(def::DefTrait(def_id)) => { + def::DefTrait(def_id) => { span_err!(tcx.sess, path.span, E0159, "use of trait `{}` as a struct constructor", pprust::path_to_string(path)); @@ -3901,7 +3901,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, base_expr); def_id }, - Some(def) => { + def => { // Verify that this was actually a struct. let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id()); match typ.ty.sty { @@ -3926,10 +3926,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, def.def_id() } - _ => { - tcx.sess.span_bug(path.span, - "structure constructor wasn't resolved") - } }; // Turn the path into a type and verify that that type unifies with @@ -4643,10 +4639,6 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, check_instantiable(ccx.tcx, sp, id); } -pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def { - lookup_def_ccx(fcx.ccx, sp, id) -} - // Returns the type parameter count and the type for the given definition. fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, @@ -5171,18 +5163,15 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { _ => false } })) || - // Second: is there a labeled break with label - // nested anywhere inside the loop? + // Second: is there a labeled break with label + // nested anywhere inside the loop? (block_query(b, |e| { - match e.node { - ast::ExprBreak(Some(_)) => { - match cx.def_map.borrow().get(&e.id).map(|d| d.full_def()) { - Some(def::DefLabel(loop_id)) if id == loop_id => true, - _ => false, - } - } - _ => false - }})) + if let ast::ExprBreak(Some(_)) = e.node { + lookup_full_def(cx, e.span, e.id) == def::DefLabel(id) + } else { + false + } + })) } pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 6b1d46aa04df8..78dd66c8e7dbb 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -163,20 +163,16 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, tcx.item_substs.borrow_mut().insert(node_id, item_substs); } } -fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def { + +fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def { match tcx.def_map.borrow().get(&id) { Some(x) => x.full_def(), - _ => { + None => { span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition") } } } -fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId) - -> def::Def { - lookup_def_tcx(ccx.tcx, sp, id) -} - fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>, maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>, t1_is_expected: bool, From 866a5ee2999ae7cb96de58a77647509d090456ee Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 19 Feb 2015 22:28:20 +0200 Subject: [PATCH 20/25] Fix fallout from correct stability handling in UFCS. --- src/libcollections/slice.rs | 2 +- src/librustc_privacy/lib.rs | 1 - src/test/compile-fail/lint-stability.rs | 151 ++++++++++++++++++++++-- 3 files changed, 145 insertions(+), 9 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 776b8b3af147c..4b2b125fc99f2 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -790,7 +790,7 @@ pub trait SliceExt { fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; /// Convert `self` into a vector without clones or allocation. - #[unstable(feature = "collections")] + #[stable(feature = "rust1", since = "1.0.0")] fn into_vec(self: Box) -> Vec; } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 29448c68c80b9..436a826687e13 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -17,7 +17,6 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(core)] #![feature(int_uint)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 88f2cbdea6d7b..9079284885572 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -29,45 +29,104 @@ mod cross_crate { use lint_stability::*; fn test() { + type Foo = MethodTester; let foo = MethodTester; deprecated(); //~ ERROR use of deprecated item foo.method_deprecated(); //~ ERROR use of deprecated item + Foo::method_deprecated(&foo); //~ ERROR use of deprecated item + ::method_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item deprecated_text(); //~ ERROR use of deprecated item: text foo.method_deprecated_text(); //~ ERROR use of deprecated item: text + Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text deprecated_unstable(); //~ ERROR use of deprecated item //~^ WARNING use of unstable library feature foo.method_deprecated_unstable(); //~ ERROR use of deprecated item //~^ WARNING use of unstable library feature + Foo::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature + ::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item //~^ WARNING use of unstable library feature + Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature deprecated_unstable_text(); //~ ERROR use of deprecated item: text //~^ WARNING use of unstable library feature foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text //~^ WARNING use of unstable library feature + Foo::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature + ::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text //~^ WARNING use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature unstable(); //~ WARNING use of unstable library feature foo.method_unstable(); //~ WARNING use of unstable library feature + Foo::method_unstable(&foo); //~ WARNING use of unstable library feature + ::method_unstable(&foo); //~ WARNING use of unstable library feature foo.trait_unstable(); //~ WARNING use of unstable library feature + Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature + ::trait_unstable(&foo); //~ WARNING use of unstable library feature + ::trait_unstable(&foo); //~ WARNING use of unstable library feature - unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text - foo.method_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text - foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text + unstable_text(); + //~^ WARNING use of unstable library feature 'test_feature': text + foo.method_unstable_text(); + //~^ WARNING use of unstable library feature 'test_feature': text + Foo::method_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text + ::method_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text + foo.trait_unstable_text(); + //~^ WARNING use of unstable library feature 'test_feature': text + Trait::trait_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text stable(); foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); stable_text(); foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item let _ = DeprecatedUnstableStruct { i: 0 }; //~ ERROR use of deprecated item @@ -104,16 +163,47 @@ mod cross_crate { macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text } - fn test_method_param(foo: F) { + fn test_method_param(foo: Foo) { foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item //~^ WARNING use of unstable library feature + Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ WARNING use of unstable library feature foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text //~^ WARNING use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ WARNING use of unstable library feature foo.trait_unstable(); //~ WARNING use of unstable library feature - foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text + Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature + ::trait_unstable(&foo); //~ WARNING use of unstable library feature + ::trait_unstable(&foo); //~ WARNING use of unstable library feature + foo.trait_unstable_text(); + //~^ WARNING use of unstable library feature 'test_feature': text + Trait::trait_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ WARNING use of unstable library feature 'test_feature': text foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); } fn test_method_object(foo: &Trait) { @@ -124,7 +214,8 @@ mod cross_crate { foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text //~^ WARNING use of unstable library feature foo.trait_unstable(); //~ WARNING use of unstable library feature - foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text + foo.trait_unstable_text(); + //~^ WARNING use of unstable library feature 'test_feature': text foo.trait_stable(); } @@ -264,31 +355,62 @@ mod this_crate { // errors, because other stability attributes now have meaning // only *across* crates, not within a single crate. + type Foo = MethodTester; let foo = MethodTester; deprecated(); //~ ERROR use of deprecated item foo.method_deprecated(); //~ ERROR use of deprecated item + Foo::method_deprecated(&foo); //~ ERROR use of deprecated item + ::method_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item deprecated_text(); //~ ERROR use of deprecated item: text foo.method_deprecated_text(); //~ ERROR use of deprecated item: text + Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text unstable(); foo.method_unstable(); + Foo::method_unstable(&foo); + ::method_unstable(&foo); foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); unstable_text(); foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + ::method_unstable_text(&foo); foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); stable(); foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); stable_text(); foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item let _ = UnstableStruct { i: 0 }; @@ -307,12 +429,27 @@ mod this_crate { let _ = StableTupleStruct (1); } - fn test_method_param(foo: F) { + fn test_method_param(foo: Foo) { foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); } fn test_method_object(foo: &Trait) { From 9ac073604c6689a773eb19bcc375234384326682 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 20 Feb 2015 11:36:31 +0200 Subject: [PATCH 21/25] Fix fallout from allowing impls outside of the type's definition module. --- src/librustc_typeck/coherence/orphan.rs | 1 - src/test/{compile-fail => run-pass}/issue-12729.rs | 4 +--- src/test/{compile-fail => run-pass}/issue-7607-2.rs | 4 +--- src/test/run-pass/trait-impl-2.rs | 4 ++-- 4 files changed, 4 insertions(+), 9 deletions(-) rename src/test/{compile-fail => run-pass}/issue-12729.rs (80%) rename src/test/{compile-fail => run-pass}/issue-7607-2.rs (81%) diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 34fadc70af8b7..465b3c8e3ac1e 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -15,7 +15,6 @@ use middle::traits; use middle::ty; use syntax::ast::{Item, ItemImpl}; use syntax::ast; -use syntax::ast_map; use syntax::ast_util; use syntax::visit; use util::ppaux::{Repr, UserString}; diff --git a/src/test/compile-fail/issue-12729.rs b/src/test/run-pass/issue-12729.rs similarity index 80% rename from src/test/compile-fail/issue-12729.rs rename to src/test/run-pass/issue-12729.rs index ae033bbf38d14..09c0c8604adc2 100644 --- a/src/test/compile-fail/issue-12729.rs +++ b/src/test/run-pass/issue-12729.rs @@ -8,14 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - pub struct Foo; mod bar { use Foo; - impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module + impl Foo { fn baz(&self) {} } } diff --git a/src/test/compile-fail/issue-7607-2.rs b/src/test/run-pass/issue-7607-2.rs similarity index 81% rename from src/test/compile-fail/issue-7607-2.rs rename to src/test/run-pass/issue-7607-2.rs index 9541899b46913..c52051fab96e3 100644 --- a/src/test/compile-fail/issue-7607-2.rs +++ b/src/test/run-pass/issue-7607-2.rs @@ -8,15 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - pub mod a { pub struct Foo { a: usize } } pub mod b { use a::Foo; - impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module + impl Foo { fn bar(&self) { } } } diff --git a/src/test/run-pass/trait-impl-2.rs b/src/test/run-pass/trait-impl-2.rs index 727c33d6ce56f..abc35bcc29d41 100644 --- a/src/test/run-pass/trait-impl-2.rs +++ b/src/test/run-pass/trait-impl-2.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -mod Foo { - trait Trait { +pub mod Foo { + pub trait Trait { fn foo(&self); } } From f0efa2d84347ed0081476f04f42efe4be85ae4d6 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 20 Feb 2015 18:33:29 +0200 Subject: [PATCH 22/25] Update trans/save's span hacks for fully qualified UFCS paths. --- src/librustc_trans/save/span_utils.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index a5bebaa257ca0..8de046fa6ebb6 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -238,6 +238,7 @@ impl<'a> SpanUtils<'a> { let mut toks = self.retokenise_span(span); // We keep track of how many brackets we're nested in let mut bracket_count = 0; + let mut found_ufcs_sep = false; loop { let ts = toks.real_token(); if ts.tok == token::Eof { @@ -254,13 +255,20 @@ impl<'a> SpanUtils<'a> { } bracket_count += match ts.tok { token::Lt => 1, - token::Gt => -1, + token::Gt => { + // Ignore the `>::` in `::AssocTy`. + if !found_ufcs_sep && bracket_count == 0 { + found_ufcs_sep = true; + 0 + } else { + -1 + } + } token::BinOp(token::Shl) => 2, token::BinOp(token::Shr) => -2, _ => 0 }; - if ts.tok.is_ident() && - bracket_count == nesting { + if ts.tok.is_ident() && bracket_count == nesting { result.push(self.make_sub_span(span, Some(ts.sp)).unwrap()); } } From 8501c9dee53b78f5027ca215cd8b6711184fe9c3 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 23 Feb 2015 23:24:41 +0200 Subject: [PATCH 23/25] rustc_typeck: unify the impl type with the UFCS path prefix type. --- src/librustc_typeck/check/mod.rs | 39 ++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f56df4570b364..d7a11b8a5152f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4748,9 +4748,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, assert!(segments.len() >= 1); - // In `>::method`, `A` and `B` are mandatory. - let mut require_type_space = opt_self_ty.is_some(); - + let mut ufcs_method = None; let mut segment_spaces: Vec<_>; match def { // Case 1 and 1b. Reference to a *type* or *enum variant*. @@ -4777,8 +4775,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } // Case 3. Reference to a method. - def::DefMethod(_, providence) => { - match providence { + def::DefMethod(_, provenance) => { + match provenance { def::FromTrait(trait_did) => { callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did) } @@ -4791,9 +4789,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, segment_spaces.push(Some(subst::FnSpace)); } else { // `::method` will end up here, and so can `T::method`. - assert!(opt_self_ty.is_some()); - require_type_space = false; + let self_ty = opt_self_ty.expect("UFCS sugared method missing Self"); segment_spaces = vec![Some(subst::FnSpace)]; + ufcs_method = Some((provenance, self_ty)); } } @@ -4812,6 +4810,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } assert_eq!(segment_spaces.len(), segments.len()); + // In `>::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_method.is_none(); + debug!("segment_spaces={:?}", segment_spaces); // Next, examine the definition, and determine how many type @@ -4879,6 +4882,28 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // the referenced item. let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty); + + if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method { + // In the case of `Foo::method` and `>::method`, if `method` + // is inherent, there is no `Self` parameter, instead, the impl needs + // type parameters, which we can infer by unifying the provided `Self` + // with the substituted impl type. + let impl_scheme = ty::lookup_item_type(fcx.tcx(), 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 = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty); + if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() { + fcx.tcx().sess.span_bug(span, + &format!( + "instantiate_path: (UFCS) {} was a subtype of {} but now is not?", + self_ty.repr(fcx.tcx()), + impl_ty.repr(fcx.tcx()))); + } + } + fcx.write_ty(node_id, ty_substituted); fcx.write_substs(node_id, ty::ItemSubsts { substs: substs }); return; From 72d5f39be7e7fe59f827345fce423535a343c432 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 24 Feb 2015 08:28:11 +0200 Subject: [PATCH 24/25] Fix fallout from rebasing. --- src/librustc/metadata/encoder.rs | 4 ++-- src/librustc/middle/ty.rs | 15 ++++++--------- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 8 ++++---- src/librustc_trans/save/mod.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 4 ++-- src/librustc_typeck/collect.rs | 8 ++++++-- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a01b17ac194de..ee2745ca66bc5 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1193,7 +1193,7 @@ fn encode_info_for_item(ecx: &EncodeContext, None => {} } } - ast::ItemDefaultImpl(unsafety, ref ast_trait_ref) => { + ast::ItemDefaultImpl(unsafety, _) => { add_to_index(item, rbml_w, index); rbml_w.start_tag(tag_items_data_item); encode_def_id(rbml_w, def_id); @@ -1201,7 +1201,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(rbml_w, item.ident.name); encode_unsafety(rbml_w, unsafety); - let trait_ref = ty::node_id_to_trait_ref(tcx, ast_trait_ref.ref_id); + let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id); encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref); rbml_w.end_tag(); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7b05e51085279..9131363339710 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5116,15 +5116,12 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) if id.krate == ast::LOCAL_CRATE { debug!("(impl_trait_ref) searching for trait impl {:?}", id); if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) { - if let ast::ItemImpl(_, _, _, ref opt_trait, _, _) = item.node { - opt_trait.as_ref().map(|_| { - ty::impl_id_to_trait_ref(cx, id.node) - }) - } else { - None - ast::ItemDefaultImpl(_, ref ast_trait_ref) => { - Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id)) - } + match item.node { + ast::ItemImpl(_, _, _, Some(_), _, _) | + ast::ItemDefaultImpl(..) => { + Some(ty::impl_id_to_trait_ref(cx, id.node)) + } + _ => None } } else { None diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e4612d6c8b9b3..67e2b409c8e22 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -504,8 +504,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { parent.clone() } - ItemImpl(..) => parent.clone(), ItemDefaultImpl(_, _) | + ItemImpl(..) => parent.clone(), ItemTrait(_, _, _, ref items) => { let name_bindings = diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index cb7224f7cbfe8..95523be68c3bf 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2772,7 +2772,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } ItemDefaultImpl(_, ref trait_ref) => { - self.resolve_trait_reference(item.id, trait_ref, TraitImplementation); + self.with_optional_trait_ref(Some(trait_ref), |_| {}); } ItemImpl(_, _, ref generics, @@ -3022,12 +3022,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn with_optional_trait_ref(&mut self, - opt_trait_ref: &Option, + opt_trait_ref: Option<&TraitRef>, f: F) -> T where F: FnOnce(&mut Resolver) -> T, { let mut new_val = None; - if let Some(ref trait_ref) = *opt_trait_ref { + if let Some(trait_ref) = opt_trait_ref { match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) { Ok(path_res) => { self.record_def(trait_ref.ref_id, path_res); @@ -3057,7 +3057,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { this.visit_generics(generics); // Resolve the trait reference, if necessary. - this.with_optional_trait_ref(opt_trait_reference, |this| { + this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this| { // Resolve the self type. this.visit_ty(self_type); diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index ab7f3916728c5..371b9268fba0d 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1004,7 +1004,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef)); visit::walk_path(self, path); - let def = self.analysis.ty_cx.def_map.borrow()[p.id]; + let def = self.analysis.ty_cx.def_map.borrow()[p.id].full_def(); let struct_def = match def { def::DefConst(..) => None, def::DefVariant(_, variant_id, _) => Some(variant_id), diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 465b3c8e3ac1e..95dafccd866bf 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -93,10 +93,10 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { } } } - ast::ItemDefaultImpl(_, ref ast_trait_ref) => { + ast::ItemDefaultImpl(..) => { // "Trait" impl debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx)); - let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id); + let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap(); if trait_ref.def_id.krate != ast::LOCAL_CRATE { span_err!(self.tcx.sess, item.span, E0318, "cannot create default implementations for traits outside the \ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7ed372d1b4b03..bc0c61ad7ad52 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -649,8 +649,12 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { &enum_definition.variants); }, ast::ItemDefaultImpl(_, ref ast_trait_ref) => { - let trait_ref = astconv::instantiate_trait_ref(ccx, &ExplicitRscope, - ast_trait_ref, None, None); + let trait_ref = astconv::instantiate_trait_ref(ccx, + &ExplicitRscope, + ast_trait_ref, + Some(it.id), + None, + None); ty::record_default_trait_implementation(tcx, trait_ref.def_id, local_def(it.id)) } From 0c6d1f3b3d22f45c53c8be0a799a6cc42bc752d5 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 24 Feb 2015 12:12:14 +0200 Subject: [PATCH 25/25] syntax: update pretty-printer for the `::method` shorthand. --- src/libsyntax/print/pprust.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 78b9487d1c98b..af16e19c9f034 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2048,9 +2048,12 @@ impl<'a> State<'a> { { try!(word(&mut self.s, "<")); try!(self.print_type(&qself.ty)); - try!(space(&mut self.s)); - try!(self.word_space("as")); - try!(self.print_path(&path, false, 1)); + if qself.position > 0 { + try!(space(&mut self.s)); + try!(self.word_space("as")); + let depth = path.segments.len() - qself.position; + try!(self.print_path(&path, false, depth)); + } try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); let item_segment = path.segments.last().unwrap();