mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #73563 - Manishearth:rollup-oowgwwm, r=Manishearth
Rollup of 9 pull requests
Successful merges:
- #72456 (Try to suggest dereferences on trait selection failed)
- #72788 (Projection bound validation)
- #72790 (core/time: Add Duration methods for zero)
- #73227 (Allow multiple `asm!` options groups and report an error on duplicate options)
- #73287 (lint: normalize projections using opaque types)
- #73291 (Pre-compute `LocalDefId` <-> `HirId` mappings and remove `NodeId` <-> `HirId` conversion APIs)
- #73378 (Remove use of specialization from librustc_arena)
- #73411 (Update bootstrap to rustc 1.45.0-beta.2 (1dc0f6d8e
2020-06-15))
- #73443 (ci: allow gating GHA on everything but macOS)
Failed merges:
r? @ghost
This commit is contained in:
commit
7058471ade
158
.github/workflows/ci.yml
vendored
158
.github/workflows/ci.yml
vendored
@ -369,35 +369,6 @@ jobs:
|
||||
env:
|
||||
DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
|
||||
os: ubuntu-latest-xl
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: macos-latest
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
os: macos-latest
|
||||
- name: x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py test"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.8
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
os: macos-latest
|
||||
- name: x86_64-msvc-1
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
|
||||
@ -580,6 +551,135 @@ jobs:
|
||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
||||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
|
||||
auto-fallible:
|
||||
name: auto-fallible
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
SCCACHE_BUCKET: rust-lang-gha-caches
|
||||
DEPLOY_BUCKET: rust-lang-gha
|
||||
TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate"
|
||||
TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues"
|
||||
TOOLSTATE_PUBLISH: 1
|
||||
CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5
|
||||
ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF
|
||||
CACHE_DOMAIN: ci-caches-gha.rust-lang.org
|
||||
if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: macos-latest
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
os: macos-latest
|
||||
- name: x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py test"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.8
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
os: macos-latest
|
||||
timeout-minutes: 600
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- name: disable git crlf conversion
|
||||
run: git config --global core.autocrlf false
|
||||
shell: bash
|
||||
- name: checkout the source code
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: configure GitHub Actions to kill the build when outdated
|
||||
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
|
||||
with:
|
||||
github_token: "${{ secrets.github_token }}"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||
- name: add extra environment variables
|
||||
run: src/ci/scripts/setup-environment.sh
|
||||
env:
|
||||
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: decide whether to skip this job
|
||||
run: src/ci/scripts/should-skip-this.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: collect CPU statistics
|
||||
run: src/ci/scripts/collect-cpu-stats.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: show the current environment
|
||||
run: src/ci/scripts/dump-environment.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install awscli
|
||||
run: src/ci/scripts/install-awscli.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install sccache
|
||||
run: src/ci/scripts/install-sccache.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install clang
|
||||
run: src/ci/scripts/install-clang.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install WIX
|
||||
run: src/ci/scripts/install-wix.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install InnoSetup
|
||||
run: src/ci/scripts/install-innosetup.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: ensure the build happens on a partition with enough space
|
||||
run: src/ci/scripts/symlink-build-dir.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: disable git crlf conversion
|
||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install MSYS2
|
||||
run: src/ci/scripts/install-msys2.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install MinGW
|
||||
run: src/ci/scripts/install-mingw.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install ninja
|
||||
run: src/ci/scripts/install-ninja.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: enable ipv6 on Docker
|
||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: disable git crlf conversion
|
||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: checkout submodules
|
||||
run: src/ci/scripts/checkout-submodules.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: ensure line endings are correct
|
||||
run: src/ci/scripts/verify-line-endings.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: run the build
|
||||
run: src/ci/scripts/run-build-from-ci.sh
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
|
||||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
|
||||
TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: upload artifacts to S3
|
||||
run: src/ci/scripts/upload-artifacts.sh
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
||||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
|
||||
master:
|
||||
name: master
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -414,42 +414,6 @@ jobs:
|
||||
DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
|
||||
<<: *job-linux-xl
|
||||
|
||||
####################
|
||||
# macOS Builders #
|
||||
####################
|
||||
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: ./x.py dist
|
||||
RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
<<: *job-macos-xl
|
||||
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: ./x.py dist
|
||||
RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
<<: *job-macos-xl
|
||||
|
||||
- name: x86_64-apple
|
||||
env:
|
||||
SCRIPT: ./x.py test
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.8
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
<<: *job-macos-xl
|
||||
|
||||
######################
|
||||
# Windows Builders #
|
||||
######################
|
||||
@ -595,6 +559,51 @@ jobs:
|
||||
SCRIPT: python x.py dist
|
||||
<<: *job-windows-xl
|
||||
|
||||
auto-fallible:
|
||||
<<: *base-ci-job
|
||||
name: auto-fallible
|
||||
env:
|
||||
<<: [*shared-ci-variables, *prod-variables]
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
####################
|
||||
# macOS Builders #
|
||||
####################
|
||||
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: ./x.py dist
|
||||
RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
<<: *job-macos-xl
|
||||
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: ./x.py dist
|
||||
RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
<<: *job-macos-xl
|
||||
|
||||
- name: x86_64-apple
|
||||
env:
|
||||
SCRIPT: ./x.py test
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.8
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
<<: *job-macos-xl
|
||||
|
||||
master:
|
||||
name: master
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -1155,6 +1155,7 @@ impl<T: Deref, E> Result<T, E> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(inner_deref)]
|
||||
/// let x: Result<String, u32> = Ok("hello".to_string());
|
||||
/// let y: Result<&str, &u32> = Ok("hello");
|
||||
/// assert_eq!(x.as_deref(), y);
|
||||
@ -1189,12 +1190,15 @@ impl<T: DerefMut, E> Result<T, E> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(inner_deref)]
|
||||
/// let mut s = "HELLO".to_string();
|
||||
/// let mut x: Result<String, u32> = Ok("hello".to_string());
|
||||
/// let y: Result<&mut str, &mut u32> = Ok("HELLO");
|
||||
/// let y: Result<&mut str, &mut u32> = Ok(&mut s);
|
||||
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
|
||||
///
|
||||
/// let mut i = 42;
|
||||
/// let mut x: Result<String, u32> = Err(42);
|
||||
/// let y: Result<&mut str, &mut u32> = Err(&42);
|
||||
/// let y: Result<&mut str, &mut u32> = Err(&mut i);
|
||||
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
|
||||
/// ```
|
||||
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {
|
||||
|
@ -31,7 +31,7 @@ const MICROS_PER_SEC: u64 = 1_000_000;
|
||||
/// the number of nanoseconds.
|
||||
///
|
||||
/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other
|
||||
/// [`ops`] traits.
|
||||
/// [`ops`] traits. It implements `Default` by returning a zero-length `Duration`.
|
||||
///
|
||||
/// [`Add`]: ../../std/ops/trait.Add.html
|
||||
/// [`Sub`]: ../../std/ops/trait.Sub.html
|
||||
@ -138,6 +138,24 @@ impl Duration {
|
||||
Duration { secs, nanos }
|
||||
}
|
||||
|
||||
/// Creates a new `Duration` that spans no time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_zero)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let duration = Duration::zero();
|
||||
/// assert!(duration.is_zero());
|
||||
/// assert_eq!(duration.as_nanos(), 0);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_zero", issue = "73544")]
|
||||
#[inline]
|
||||
pub const fn zero() -> Duration {
|
||||
Duration { secs: 0, nanos: 0 }
|
||||
}
|
||||
|
||||
/// Creates a new `Duration` from the specified number of whole seconds.
|
||||
///
|
||||
/// # Examples
|
||||
@ -223,6 +241,29 @@ impl Duration {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this `Duration` spans no time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration_zero)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// assert!(Duration::zero().is_zero());
|
||||
/// assert!(Duration::new(0, 0).is_zero());
|
||||
/// assert!(Duration::from_nanos(0).is_zero());
|
||||
/// assert!(Duration::from_secs(0).is_zero());
|
||||
///
|
||||
/// assert!(!Duration::new(1, 1).is_zero());
|
||||
/// assert!(!Duration::from_nanos(1).is_zero());
|
||||
/// assert!(!Duration::from_secs(1).is_zero());
|
||||
/// ```
|
||||
#[unstable(feature = "duration_zero", issue = "73544")]
|
||||
#[inline]
|
||||
pub const fn is_zero(&self) -> bool {
|
||||
self.secs == 0 && self.nanos == 0
|
||||
}
|
||||
|
||||
/// Returns the number of _whole_ seconds contained by this `Duration`.
|
||||
///
|
||||
/// The returned value does not include the fractional (nanosecond) part of the
|
||||
|
@ -611,7 +611,11 @@ macro_rules! which_arena_for_type {
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! declare_arena {
|
||||
([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
|
||||
// This macro has to take the same input as
|
||||
// `impl_arena_allocatable_decoders` which requires a second version of
|
||||
// each type. We ignore that type until we can fix
|
||||
// `impl_arena_allocatable_decoders`.
|
||||
([], [$($a:tt $name:ident: $ty:ty, $_gen_ty:ty;)*], $tcx:lifetime) => {
|
||||
#[derive(Default)]
|
||||
pub struct Arena<$tcx> {
|
||||
pub dropless: $crate::DroplessArena,
|
||||
@ -619,39 +623,56 @@ macro_rules! declare_arena {
|
||||
$($name: $crate::arena_for_type!($a[$ty]),)*
|
||||
}
|
||||
|
||||
#[marker]
|
||||
pub trait ArenaAllocatable<'tcx> {}
|
||||
|
||||
impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {}
|
||||
|
||||
unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> {
|
||||
/// Returns a specific arena to allocate from.
|
||||
/// If `None` is returned, the `DropArena` will be used.
|
||||
fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>>;
|
||||
pub trait ArenaAllocatable<'tcx, T = Self>: Sized {
|
||||
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self;
|
||||
fn allocate_from_iter<'a>(
|
||||
arena: &'a Arena<'tcx>,
|
||||
iter: impl ::std::iter::IntoIterator<Item = Self>,
|
||||
) -> &'a mut [Self];
|
||||
}
|
||||
|
||||
unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T {
|
||||
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
|
||||
#[inline]
|
||||
default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>> {
|
||||
panic!()
|
||||
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
|
||||
arena.dropless.alloc(self)
|
||||
}
|
||||
#[inline]
|
||||
fn allocate_from_iter<'a>(
|
||||
arena: &'a Arena<'tcx>,
|
||||
iter: impl ::std::iter::IntoIterator<Item = Self>,
|
||||
) -> &'a mut [Self] {
|
||||
arena.dropless.alloc_from_iter(iter)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$(
|
||||
#[allow(unused_lifetimes)]
|
||||
impl<$tcx> ArenaAllocatable<$tcx> for $ty {}
|
||||
unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> {
|
||||
impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty {
|
||||
#[inline]
|
||||
fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena<Self>> {
|
||||
// SAFETY: We only implement `ArenaAllocatable<$tcx>` for
|
||||
// `$ty`, so `$ty` and Self are the same type
|
||||
unsafe {
|
||||
::std::mem::transmute::<
|
||||
Option<&'a $crate::TypedArena<$ty>>,
|
||||
Option<&'a $crate::TypedArena<Self>>,
|
||||
>(
|
||||
$crate::which_arena_for_type!($a[&_arena.$name])
|
||||
)
|
||||
fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self {
|
||||
if !::std::mem::needs_drop::<Self>() {
|
||||
return arena.dropless.alloc(self);
|
||||
}
|
||||
match $crate::which_arena_for_type!($a[&arena.$name]) {
|
||||
::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
|
||||
ty_arena.alloc(self)
|
||||
}
|
||||
::std::option::Option::None => unsafe { arena.drop.alloc(self) },
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn allocate_from_iter<'a>(
|
||||
arena: &'a Arena<$tcx>,
|
||||
iter: impl ::std::iter::IntoIterator<Item = Self>,
|
||||
) -> &'a mut [Self] {
|
||||
if !::std::mem::needs_drop::<Self>() {
|
||||
return arena.dropless.alloc_from_iter(iter);
|
||||
}
|
||||
match $crate::which_arena_for_type!($a[&arena.$name]) {
|
||||
::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
|
||||
ty_arena.alloc_from_iter(iter)
|
||||
}
|
||||
::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) },
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -659,14 +680,8 @@ macro_rules! declare_arena {
|
||||
|
||||
impl<'tcx> Arena<'tcx> {
|
||||
#[inline]
|
||||
pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
|
||||
if !::std::mem::needs_drop::<T>() {
|
||||
return self.dropless.alloc(value);
|
||||
}
|
||||
match <T as ArenaField<'tcx>>::arena(self) {
|
||||
::std::option::Option::Some(arena) => arena.alloc(value),
|
||||
::std::option::Option::None => unsafe { self.drop.alloc(value) },
|
||||
}
|
||||
pub fn alloc<T: ArenaAllocatable<'tcx, U>, U>(&self, value: T) -> &mut T {
|
||||
value.allocate_on(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -677,17 +692,11 @@ macro_rules! declare_arena {
|
||||
self.dropless.alloc_slice(value)
|
||||
}
|
||||
|
||||
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>(
|
||||
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>(
|
||||
&'a self,
|
||||
iter: impl ::std::iter::IntoIterator<Item = T>,
|
||||
) -> &'a mut [T] {
|
||||
if !::std::mem::needs_drop::<T>() {
|
||||
return self.dropless.alloc_from_iter(iter);
|
||||
}
|
||||
match <T as ArenaField<'tcx>>::arena(self) {
|
||||
::std::option::Option::Some(arena) => arena.alloc_from_iter(iter),
|
||||
::std::option::Option::None => unsafe { self.drop.alloc_from_iter(iter) },
|
||||
}
|
||||
T::allocate_from_iter(self, iter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,6 @@
|
||||
|
||||
#![feature(array_value_iter)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(marker_trait_attr)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(or_patterns)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
@ -205,6 +203,8 @@ pub trait Resolver {
|
||||
fn lint_buffer(&mut self) -> &mut LintBuffer;
|
||||
|
||||
fn next_node_id(&mut self) -> NodeId;
|
||||
|
||||
fn trait_map(&self) -> &NodeMap<Vec<hir::TraitCandidate>>;
|
||||
}
|
||||
|
||||
type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
|
||||
@ -557,6 +557,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let proc_macros =
|
||||
c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect();
|
||||
|
||||
let trait_map = self
|
||||
.resolver
|
||||
.trait_map()
|
||||
.iter()
|
||||
.map(|(&k, v)| (self.node_id_to_hir_id[k].unwrap(), v.clone()))
|
||||
.collect();
|
||||
|
||||
self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
|
||||
|
||||
hir::Crate {
|
||||
@ -571,6 +578,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
trait_impls: self.trait_impls,
|
||||
modules: self.modules,
|
||||
proc_macros,
|
||||
trait_map,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ struct AsmArgs {
|
||||
named_args: FxHashMap<Symbol, usize>,
|
||||
reg_args: FxHashSet<usize>,
|
||||
options: ast::InlineAsmOptions,
|
||||
options_span: Option<Span>,
|
||||
options_spans: Vec<Span>,
|
||||
}
|
||||
|
||||
fn parse_args<'a>(
|
||||
@ -59,7 +59,7 @@ fn parse_args<'a>(
|
||||
named_args: FxHashMap::default(),
|
||||
reg_args: FxHashSet::default(),
|
||||
options: ast::InlineAsmOptions::empty(),
|
||||
options_span: None,
|
||||
options_spans: vec![],
|
||||
};
|
||||
|
||||
let mut allow_templates = true;
|
||||
@ -174,9 +174,9 @@ fn parse_args<'a>(
|
||||
|
||||
// Validate the order of named, positional & explicit register operands and options. We do
|
||||
// this at the end once we have the full span of the argument available.
|
||||
if let Some(options_span) = args.options_span {
|
||||
if !args.options_spans.is_empty() {
|
||||
ecx.struct_span_err(span, "arguments are not allowed after options")
|
||||
.span_label(options_span, "previous options")
|
||||
.span_labels(args.options_spans.clone(), "previous options")
|
||||
.span_label(span, "argument")
|
||||
.emit();
|
||||
}
|
||||
@ -227,23 +227,23 @@ fn parse_args<'a>(
|
||||
if args.options.contains(ast::InlineAsmOptions::NOMEM)
|
||||
&& args.options.contains(ast::InlineAsmOptions::READONLY)
|
||||
{
|
||||
let span = args.options_span.unwrap();
|
||||
ecx.struct_span_err(span, "the `nomem` and `readonly` options are mutually exclusive")
|
||||
let spans = args.options_spans.clone();
|
||||
ecx.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive")
|
||||
.emit();
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE)
|
||||
&& args.options.contains(ast::InlineAsmOptions::NORETURN)
|
||||
{
|
||||
let span = args.options_span.unwrap();
|
||||
ecx.struct_span_err(span, "the `pure` and `noreturn` options are mutually exclusive")
|
||||
let spans = args.options_spans.clone();
|
||||
ecx.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive")
|
||||
.emit();
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE)
|
||||
&& !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
|
||||
{
|
||||
let span = args.options_span.unwrap();
|
||||
let spans = args.options_spans.clone();
|
||||
ecx.struct_span_err(
|
||||
span,
|
||||
spans,
|
||||
"the `pure` option must be combined with either `nomem` or `readonly`",
|
||||
)
|
||||
.emit();
|
||||
@ -267,7 +267,7 @@ fn parse_args<'a>(
|
||||
}
|
||||
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
|
||||
ecx.struct_span_err(
|
||||
args.options_span.unwrap(),
|
||||
args.options_spans.clone(),
|
||||
"asm with `pure` option must have at least one output",
|
||||
)
|
||||
.emit();
|
||||
@ -283,6 +283,50 @@ fn parse_args<'a>(
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
/// Report a duplicate option error.
|
||||
///
|
||||
/// This function must be called immediately after the option token is parsed.
|
||||
/// Otherwise, the suggestion will be incorrect.
|
||||
fn err_duplicate_option<'a>(p: &mut Parser<'a>, symbol: Symbol, span: Span) {
|
||||
let mut err = p
|
||||
.sess
|
||||
.span_diagnostic
|
||||
.struct_span_err(span, &format!("the `{}` option was already provided", symbol));
|
||||
err.span_label(span, "this option was already provided");
|
||||
|
||||
// Tool-only output
|
||||
let mut full_span = span;
|
||||
if p.token.kind == token::Comma {
|
||||
full_span = full_span.to(p.token.span);
|
||||
}
|
||||
err.tool_only_span_suggestion(
|
||||
full_span,
|
||||
"remove this option",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
/// Try to set the provided option in the provided `AsmArgs`.
|
||||
/// If it is already set, report a duplicate option error.
|
||||
///
|
||||
/// This function must be called immediately after the option token is parsed.
|
||||
/// Otherwise, the error will not point to the correct spot.
|
||||
fn try_set_option<'a>(
|
||||
p: &mut Parser<'a>,
|
||||
args: &mut AsmArgs,
|
||||
symbol: Symbol,
|
||||
option: ast::InlineAsmOptions,
|
||||
) {
|
||||
if !args.options.contains(option) {
|
||||
args.options |= option;
|
||||
} else {
|
||||
err_duplicate_option(p, symbol, p.prev_token.span);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_options<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> Result<(), DiagnosticBuilder<'a>> {
|
||||
let span_start = p.prev_token.span;
|
||||
|
||||
@ -290,20 +334,20 @@ fn parse_options<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> Result<(), Diagn
|
||||
|
||||
while !p.eat(&token::CloseDelim(token::DelimToken::Paren)) {
|
||||
if p.eat(&token::Ident(sym::pure, false)) {
|
||||
args.options |= ast::InlineAsmOptions::PURE;
|
||||
try_set_option(p, args, sym::pure, ast::InlineAsmOptions::PURE);
|
||||
} else if p.eat(&token::Ident(sym::nomem, false)) {
|
||||
args.options |= ast::InlineAsmOptions::NOMEM;
|
||||
try_set_option(p, args, sym::nomem, ast::InlineAsmOptions::NOMEM);
|
||||
} else if p.eat(&token::Ident(sym::readonly, false)) {
|
||||
args.options |= ast::InlineAsmOptions::READONLY;
|
||||
try_set_option(p, args, sym::readonly, ast::InlineAsmOptions::READONLY);
|
||||
} else if p.eat(&token::Ident(sym::preserves_flags, false)) {
|
||||
args.options |= ast::InlineAsmOptions::PRESERVES_FLAGS;
|
||||
try_set_option(p, args, sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS);
|
||||
} else if p.eat(&token::Ident(sym::noreturn, false)) {
|
||||
args.options |= ast::InlineAsmOptions::NORETURN;
|
||||
try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN);
|
||||
} else if p.eat(&token::Ident(sym::nostack, false)) {
|
||||
args.options |= ast::InlineAsmOptions::NOSTACK;
|
||||
try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
|
||||
} else {
|
||||
p.expect(&token::Ident(sym::att_syntax, false))?;
|
||||
args.options |= ast::InlineAsmOptions::ATT_SYNTAX;
|
||||
try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
|
||||
}
|
||||
|
||||
// Allow trailing commas
|
||||
@ -314,14 +358,7 @@ fn parse_options<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> Result<(), Diagn
|
||||
}
|
||||
|
||||
let new_span = span_start.to(p.prev_token.span);
|
||||
if let Some(options_span) = args.options_span {
|
||||
p.struct_span_err(new_span, "asm options cannot be specified multiple times")
|
||||
.span_label(options_span, "previously here")
|
||||
.span_label(new_span, "duplicate options")
|
||||
.emit();
|
||||
} else {
|
||||
args.options_span = Some(new_span);
|
||||
}
|
||||
args.options_spans.push(new_span);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -81,14 +81,13 @@ pub struct Definitions {
|
||||
|
||||
def_id_to_span: IndexVec<LocalDefId, Span>,
|
||||
|
||||
// FIXME(eddyb) don't go through `ast::NodeId` to convert between `HirId`
|
||||
// and `LocalDefId` - ideally all `LocalDefId`s would be HIR owners.
|
||||
node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
|
||||
def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
|
||||
|
||||
pub(super) node_id_to_hir_id: IndexVec<ast::NodeId, Option<hir::HirId>>,
|
||||
/// The reverse mapping of `node_id_to_hir_id`.
|
||||
pub(super) hir_id_to_node_id: FxHashMap<hir::HirId, ast::NodeId>,
|
||||
// FIXME(eddyb) ideally all `LocalDefId`s would be HIR owners.
|
||||
pub(super) def_id_to_hir_id: IndexVec<LocalDefId, Option<hir::HirId>>,
|
||||
/// The reverse mapping of `def_id_to_hir_id`.
|
||||
pub(super) hir_id_to_def_id: FxHashMap<hir::HirId, LocalDefId>,
|
||||
|
||||
/// If `ExpnId` is an ID of some macro expansion,
|
||||
/// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
|
||||
@ -327,9 +326,7 @@ impl Definitions {
|
||||
|
||||
#[inline]
|
||||
pub fn local_def_id(&self, node: ast::NodeId) -> LocalDefId {
|
||||
self.opt_local_def_id(node).unwrap_or_else(|| {
|
||||
panic!("no entry for node id: `{:?}` / `{:?}`", node, self.opt_node_id_to_hir_id(node))
|
||||
})
|
||||
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -337,37 +334,19 @@ impl Definitions {
|
||||
self.local_def_id_to_hir_id(def_id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hir_id_to_node_id(&self, hir_id: hir::HirId) -> ast::NodeId {
|
||||
self.hir_id_to_node_id[&hir_id]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn node_id_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
|
||||
self.node_id_to_hir_id[node_id].unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn opt_node_id_to_hir_id(&self, node_id: ast::NodeId) -> Option<hir::HirId> {
|
||||
self.node_id_to_hir_id[node_id]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId {
|
||||
let node_id = self.def_id_to_node_id[id];
|
||||
self.node_id_to_hir_id[node_id].unwrap()
|
||||
self.def_id_to_hir_id[id].unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn opt_local_def_id_to_hir_id(&self, id: LocalDefId) -> Option<hir::HirId> {
|
||||
let node_id = self.def_id_to_node_id[id];
|
||||
self.node_id_to_hir_id[node_id]
|
||||
self.def_id_to_hir_id[id]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefId> {
|
||||
let node_id = self.hir_id_to_node_id(hir_id);
|
||||
self.opt_local_def_id(node_id)
|
||||
self.hir_id_to_def_id.get(&hir_id).copied()
|
||||
}
|
||||
|
||||
/// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
|
||||
@ -477,16 +456,24 @@ impl Definitions {
|
||||
mapping: IndexVec<ast::NodeId, Option<hir::HirId>>,
|
||||
) {
|
||||
assert!(
|
||||
self.node_id_to_hir_id.is_empty(),
|
||||
"trying to initialize `NodeId` -> `HirId` mapping twice"
|
||||
self.def_id_to_hir_id.is_empty(),
|
||||
"trying to initialize `LocalDefId` <-> `HirId` mappings twice"
|
||||
);
|
||||
self.node_id_to_hir_id = mapping;
|
||||
|
||||
// Build the reverse mapping of `node_id_to_hir_id`.
|
||||
self.hir_id_to_node_id = self
|
||||
.node_id_to_hir_id
|
||||
.iter_enumerated()
|
||||
.filter_map(|(node_id, &hir_id)| hir_id.map(|hir_id| (hir_id, node_id)))
|
||||
self.def_id_to_hir_id = self
|
||||
.def_id_to_node_id
|
||||
.iter()
|
||||
.map(|&node_id| mapping.get(node_id).and_then(|&hir_id| hir_id))
|
||||
.collect();
|
||||
|
||||
// Build the reverse mapping of `def_id_to_hir_id`.
|
||||
self.hir_id_to_def_id = mapping
|
||||
.into_iter_enumerated()
|
||||
.filter_map(|(node_id, hir_id)| {
|
||||
hir_id.and_then(|hir_id| {
|
||||
self.node_id_to_def_id.get(&node_id).map(|&def_id| (hir_id, def_id))
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
|
@ -639,6 +639,8 @@ pub struct Crate<'hir> {
|
||||
/// A list of proc macro HirIds, written out in the order in which
|
||||
/// they are declared in the static array generated by proc_macro_harness.
|
||||
pub proc_macros: Vec<HirId>,
|
||||
|
||||
pub trait_map: BTreeMap<HirId, Vec<TraitCandidate>>,
|
||||
}
|
||||
|
||||
impl Crate<'hir> {
|
||||
@ -2651,7 +2653,7 @@ pub type CaptureModeMap = NodeMap<CaptureBy>;
|
||||
// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
|
||||
// has length > 0 if the trait is found through an chain of imports, starting with the
|
||||
// import/use statement in the scope where the trait is used.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
|
||||
pub struct TraitCandidate {
|
||||
pub def_id: DefId,
|
||||
pub import_ids: SmallVec<[LocalDefId; 1]>,
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::infer::outlives::env::RegionBoundPairs;
|
||||
use crate::infer::{GenericKind, VerifyBound};
|
||||
use crate::traits;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
|
||||
@ -311,18 +310,14 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||
fn region_bounds_declared_on_associated_item(
|
||||
&self,
|
||||
assoc_item_def_id: DefId,
|
||||
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
|
||||
) -> impl Iterator<Item = ty::Region<'tcx>> {
|
||||
let tcx = self.tcx;
|
||||
let assoc_item = tcx.associated_item(assoc_item_def_id);
|
||||
let trait_def_id = assoc_item.container.assert_trait();
|
||||
let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p);
|
||||
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
|
||||
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
|
||||
self.collect_outlives_from_predicate_list(
|
||||
move |ty| ty == identity_proj,
|
||||
traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate),
|
||||
)
|
||||
.map(|b| b.1)
|
||||
let predicates = tcx.projection_predicates(assoc_item_def_id);
|
||||
predicates
|
||||
.into_iter()
|
||||
.filter_map(|p| p.to_opt_type_outlives())
|
||||
.filter_map(|p| p.no_bound_vars())
|
||||
.map(|b| b.1)
|
||||
}
|
||||
|
||||
/// Searches through a predicate list for a predicate `T: 'a`.
|
||||
|
@ -25,8 +25,6 @@ pub use self::project::{
|
||||
Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
|
||||
ProjectionCacheStorage, Reveal,
|
||||
};
|
||||
crate use self::util::elaborate_predicates;
|
||||
|
||||
pub use rustc_middle::traits::*;
|
||||
|
||||
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
|
||||
|
@ -895,22 +895,33 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
|
||||
struct ProhibitOpaqueTypes<'tcx> {
|
||||
struct ProhibitOpaqueTypes<'a, 'tcx> {
|
||||
cx: &'a LateContext<'a, 'tcx>,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
};
|
||||
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> {
|
||||
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
if let ty::Opaque(..) = ty.kind {
|
||||
self.ty = Some(ty);
|
||||
true
|
||||
} else {
|
||||
ty.super_visit_with(self)
|
||||
match ty.kind {
|
||||
ty::Opaque(..) => {
|
||||
self.ty = Some(ty);
|
||||
true
|
||||
}
|
||||
// Consider opaque types within projections FFI-safe if they do not normalize
|
||||
// to more opaque types.
|
||||
ty::Projection(..) => {
|
||||
let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
|
||||
|
||||
// If `ty` is a opaque type directly then `super_visit_with` won't invoke
|
||||
// this function again.
|
||||
if ty.has_opaque_types() { self.visit_ty(ty) } else { false }
|
||||
}
|
||||
_ => ty.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = ProhibitOpaqueTypes { ty: None };
|
||||
let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None };
|
||||
ty.visit_with(&mut visitor);
|
||||
if let Some(ty) = visitor.ty {
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None);
|
||||
|
@ -117,6 +117,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
body_ids: _,
|
||||
modules: _,
|
||||
proc_macros: _,
|
||||
trait_map: _,
|
||||
} = *krate;
|
||||
|
||||
hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes)
|
||||
@ -241,11 +242,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
// Make sure that the DepNode of some node coincides with the HirId
|
||||
// owner of that node.
|
||||
if cfg!(debug_assertions) {
|
||||
let node_id = self.definitions.hir_id_to_node_id(hir_id);
|
||||
assert_eq!(self.definitions.node_id_to_hir_id(node_id), hir_id);
|
||||
|
||||
if hir_id.owner != self.current_dep_node_owner {
|
||||
let node_str = match self.definitions.opt_local_def_id(node_id) {
|
||||
let node_str = match self.definitions.opt_hir_id_to_local_def_id(hir_id) {
|
||||
Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate(),
|
||||
None => format!("{:?}", node),
|
||||
};
|
||||
@ -335,9 +333,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
debug!("visit_item: {:?}", i);
|
||||
debug_assert_eq!(
|
||||
i.hir_id.owner,
|
||||
self.definitions
|
||||
.opt_local_def_id(self.definitions.hir_id_to_node_id(i.hir_id))
|
||||
.unwrap()
|
||||
self.definitions.opt_hir_id_to_local_def_id(i.hir_id).unwrap()
|
||||
);
|
||||
self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| {
|
||||
this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash);
|
||||
@ -369,9 +365,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
|
||||
debug_assert_eq!(
|
||||
ti.hir_id.owner,
|
||||
self.definitions
|
||||
.opt_local_def_id(self.definitions.hir_id_to_node_id(ti.hir_id))
|
||||
.unwrap()
|
||||
self.definitions.opt_hir_id_to_local_def_id(ti.hir_id).unwrap()
|
||||
);
|
||||
self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| {
|
||||
this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash);
|
||||
@ -385,9 +379,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
|
||||
debug_assert_eq!(
|
||||
ii.hir_id.owner,
|
||||
self.definitions
|
||||
.opt_local_def_id(self.definitions.hir_id_to_node_id(ii.hir_id))
|
||||
.unwrap()
|
||||
self.definitions.opt_hir_id_to_local_def_id(ii.hir_id).unwrap()
|
||||
);
|
||||
self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| {
|
||||
this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash);
|
||||
|
@ -36,7 +36,6 @@
|
||||
#![feature(drain_filter)]
|
||||
#![feature(never_type)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(marker_trait_attr)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(nll)]
|
||||
#![feature(option_expect_none)]
|
||||
|
@ -133,6 +133,23 @@ rustc_queries! {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
|
||||
/// Returns the list of predicates that can be used for
|
||||
/// `SelectionCandidate::ProjectionCandidate` and
|
||||
/// `ProjectionTyCandidate::TraitDef`.
|
||||
/// Specifically this is the bounds (equivalent to) those
|
||||
/// written on the trait's type definition, or those
|
||||
/// after the `impl` keyword
|
||||
///
|
||||
/// type X: Bound + 'lt
|
||||
/// ^^^^^^^^^^^
|
||||
/// impl Debug + Display
|
||||
/// ^^^^^^^^^^^^^^^
|
||||
///
|
||||
/// `key` is the `DefId` of the associated type or opaque type.
|
||||
query projection_predicates(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
|
||||
desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
|
||||
desc { "looking up the native libraries of a linked crate" }
|
||||
}
|
||||
|
@ -1101,9 +1101,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
};
|
||||
|
||||
let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
|
||||
for (hir_id, v) in resolutions.trait_map.into_iter() {
|
||||
for (hir_id, v) in krate.trait_map.iter() {
|
||||
let map = trait_map.entry(hir_id.owner).or_default();
|
||||
map.insert(hir_id.local_id, StableVec::new(v));
|
||||
map.insert(hir_id.local_id, StableVec::new(v.to_vec()));
|
||||
}
|
||||
|
||||
GlobalCtxt {
|
||||
|
@ -93,7 +93,6 @@ impl FlagComputation {
|
||||
|
||||
&ty::Bound(debruijn, _) => {
|
||||
self.add_binder(debruijn);
|
||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||
}
|
||||
|
||||
&ty::Placeholder(..) => {
|
||||
@ -216,7 +215,6 @@ impl FlagComputation {
|
||||
}
|
||||
ty::ConstKind::Bound(debruijn, _) => {
|
||||
self.add_binder(debruijn);
|
||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||
}
|
||||
ty::ConstKind::Param(_) => {
|
||||
self.add_flags(TypeFlags::HAS_CT_PARAM);
|
||||
|
@ -121,7 +121,6 @@ pub struct ResolverOutputs {
|
||||
pub definitions: rustc_hir::definitions::Definitions,
|
||||
pub cstore: Box<CrateStoreDyn>,
|
||||
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
|
||||
pub trait_map: FxHashMap<hir::HirId, Vec<hir::TraitCandidate>>,
|
||||
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
|
||||
pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
|
||||
pub export_map: ExportMap<LocalDefId>,
|
||||
|
@ -1589,19 +1589,16 @@ impl RegionKind {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_RE_INFER;
|
||||
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
|
||||
}
|
||||
ty::RePlaceholder(..) => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
|
||||
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
|
||||
}
|
||||
ty::ReEarlyBound(..) => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_RE_PARAM;
|
||||
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
|
||||
}
|
||||
ty::ReFree { .. } => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
|
@ -333,6 +333,17 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
|
||||
/// in a different item, with `target_substs` as the base for
|
||||
/// the target impl/trait, with the source child-specific
|
||||
/// parameters (e.g., method parameters) on top of that base.
|
||||
///
|
||||
/// For example given:
|
||||
///
|
||||
/// trait X<S> { fn f<T>(); }
|
||||
/// impl<U> X<U> for U { fn f<V>() {} }
|
||||
///
|
||||
/// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait.
|
||||
/// * If `source_ancestor` is the def_id of the trait.
|
||||
/// * If `target_substs` is `[U]`, the substs for the impl.
|
||||
/// * Then we will return `[U, T]`, the subst for `f` in the impl that
|
||||
/// are needed for it to match the trait.
|
||||
pub fn rebase_onto(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -883,7 +883,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
})
|
||||
.collect();
|
||||
if !lifetimes.is_empty() {
|
||||
self.trait_ref_hack = true;
|
||||
let next_early_index = self.next_early_index();
|
||||
let scope = Scope::Binder {
|
||||
lifetimes,
|
||||
@ -895,9 +894,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
let result = self.with(scope, |old_scope, this| {
|
||||
this.check_lifetime_params(old_scope, &bound_generic_params);
|
||||
this.visit_ty(&bounded_ty);
|
||||
this.trait_ref_hack = true;
|
||||
walk_list!(this, visit_param_bound, bounds);
|
||||
this.trait_ref_hack = false;
|
||||
});
|
||||
self.trait_ref_hack = false;
|
||||
result
|
||||
} else {
|
||||
self.visit_ty(&bounded_ty);
|
||||
@ -932,13 +932,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
|
||||
|
||||
let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref);
|
||||
if !self.trait_ref_hack
|
||||
|
||||
let trait_ref_hack = take(&mut self.trait_ref_hack);
|
||||
if !trait_ref_hack
|
||||
|| trait_ref.bound_generic_params.iter().any(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => true,
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
if self.trait_ref_hack {
|
||||
if trait_ref_hack {
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
trait_ref.span,
|
||||
@ -968,10 +970,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
|
||||
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
|
||||
this.visit_trait_ref(&trait_ref.trait_ref);
|
||||
})
|
||||
});
|
||||
} else {
|
||||
self.visit_trait_ref(&trait_ref.trait_ref);
|
||||
}
|
||||
self.trait_ref_hack = trait_ref_hack;
|
||||
if should_pop_missing_lt {
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
|
@ -1109,6 +1109,10 @@ impl rustc_ast_lowering::Resolver for Resolver<'_> {
|
||||
fn next_node_id(&mut self) -> NodeId {
|
||||
self.next_node_id()
|
||||
}
|
||||
|
||||
fn trait_map(&self) -> &NodeMap<Vec<TraitCandidate>> {
|
||||
&self.trait_map
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
@ -1284,11 +1288,6 @@ impl<'a> Resolver<'a> {
|
||||
let definitions = self.definitions;
|
||||
let extern_crate_map = self.extern_crate_map;
|
||||
let export_map = self.export_map;
|
||||
let trait_map = self
|
||||
.trait_map
|
||||
.into_iter()
|
||||
.map(|(k, v)| (definitions.node_id_to_hir_id(k), v))
|
||||
.collect();
|
||||
let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
|
||||
let maybe_unused_extern_crates = self.maybe_unused_extern_crates;
|
||||
let glob_map = self.glob_map;
|
||||
@ -1297,7 +1296,6 @@ impl<'a> Resolver<'a> {
|
||||
cstore: Box::new(self.crate_loader.into_cstore()),
|
||||
extern_crate_map,
|
||||
export_map,
|
||||
trait_map,
|
||||
glob_map,
|
||||
maybe_unused_trait_imports,
|
||||
maybe_unused_extern_crates,
|
||||
@ -1315,11 +1313,6 @@ impl<'a> Resolver<'a> {
|
||||
cstore: Box::new(self.cstore().clone()),
|
||||
extern_crate_map: self.extern_crate_map.clone(),
|
||||
export_map: self.export_map.clone(),
|
||||
trait_map: self
|
||||
.trait_map
|
||||
.iter()
|
||||
.map(|(&k, v)| (self.definitions.node_id_to_hir_id(k), v.clone()))
|
||||
.collect(),
|
||||
glob_map: self.glob_map.clone(),
|
||||
maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(),
|
||||
maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(),
|
||||
|
229
src/librustc_trait_selection/autoderef.rs
Normal file
229
src/librustc_trait_selection/autoderef.rs
Normal file
@ -0,0 +1,229 @@
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::{self, TraitEngine};
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
|
||||
use rustc_middle::ty::{ToPredicate, TypeFoldable};
|
||||
use rustc_session::DiagnosticMessageId;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AutoderefKind {
|
||||
Builtin,
|
||||
Overloaded,
|
||||
}
|
||||
|
||||
struct AutoderefSnapshot<'tcx> {
|
||||
at_start: bool,
|
||||
reached_recursion_limit: bool,
|
||||
steps: Vec<(Ty<'tcx>, AutoderefKind)>,
|
||||
cur_ty: Ty<'tcx>,
|
||||
obligations: Vec<traits::PredicateObligation<'tcx>>,
|
||||
}
|
||||
|
||||
pub struct Autoderef<'a, 'tcx> {
|
||||
// Meta infos:
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
||||
// Current state:
|
||||
state: AutoderefSnapshot<'tcx>,
|
||||
|
||||
// Configurations:
|
||||
include_raw_pointers: bool,
|
||||
silence_errors: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
||||
type Item = (Ty<'tcx>, usize);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
debug!("autoderef: steps={:?}, cur_ty={:?}", self.state.steps, self.state.cur_ty);
|
||||
if self.state.at_start {
|
||||
self.state.at_start = false;
|
||||
debug!("autoderef stage #0 is {:?}", self.state.cur_ty);
|
||||
return Some((self.state.cur_ty, 0));
|
||||
}
|
||||
|
||||
// If we have reached the recursion limit, error gracefully.
|
||||
if !tcx.sess.recursion_limit().value_within_limit(self.state.steps.len()) {
|
||||
if !self.silence_errors {
|
||||
report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty);
|
||||
}
|
||||
self.state.reached_recursion_limit = true;
|
||||
return None;
|
||||
}
|
||||
|
||||
if self.state.cur_ty.is_ty_var() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Otherwise, deref if type is derefable:
|
||||
let (kind, new_ty) =
|
||||
if let Some(mt) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
|
||||
(AutoderefKind::Builtin, mt.ty)
|
||||
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
|
||||
(AutoderefKind::Overloaded, ty)
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if new_ty.references_error() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.state.steps.push((self.state.cur_ty, kind));
|
||||
debug!(
|
||||
"autoderef stage #{:?} is {:?} from {:?}",
|
||||
self.step_count(),
|
||||
new_ty,
|
||||
(self.state.cur_ty, kind)
|
||||
);
|
||||
self.state.cur_ty = new_ty;
|
||||
|
||||
Some((self.state.cur_ty, self.step_count()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
pub fn new(
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef {
|
||||
infcx,
|
||||
span,
|
||||
body_id,
|
||||
param_env,
|
||||
state: AutoderefSnapshot {
|
||||
steps: vec![],
|
||||
cur_ty: infcx.resolve_vars_if_possible(&base_ty),
|
||||
obligations: vec![],
|
||||
at_start: true,
|
||||
reached_recursion_limit: false,
|
||||
},
|
||||
include_raw_pointers: false,
|
||||
silence_errors: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||
debug!("overloaded_deref_ty({:?})", ty);
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
// <ty as Deref>
|
||||
let trait_ref = TraitRef {
|
||||
def_id: tcx.lang_items().deref_trait()?,
|
||||
substs: tcx.mk_substs_trait(ty, &[]),
|
||||
};
|
||||
|
||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||
|
||||
let obligation = traits::Obligation::new(
|
||||
cause.clone(),
|
||||
self.param_env,
|
||||
trait_ref.without_const().to_predicate(tcx),
|
||||
);
|
||||
if !self.infcx.predicate_may_hold(&obligation) {
|
||||
debug!("overloaded_deref_ty: cannot match obligation");
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot();
|
||||
let normalized_ty = fulfillcx.normalize_projection_type(
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, Ident::from_str("Target")),
|
||||
cause,
|
||||
);
|
||||
if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
|
||||
// This shouldn't happen, except for evaluate/fulfill mismatches,
|
||||
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
||||
// by design).
|
||||
debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e);
|
||||
return None;
|
||||
}
|
||||
let obligations = fulfillcx.pending_obligations();
|
||||
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
|
||||
self.state.obligations.extend(obligations);
|
||||
|
||||
Some(self.infcx.resolve_vars_if_possible(&normalized_ty))
|
||||
}
|
||||
|
||||
/// Returns the final type we ended up with, which may be an inference
|
||||
/// variable (we will resolve it first, if we want).
|
||||
pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> {
|
||||
if resolve {
|
||||
self.infcx.resolve_vars_if_possible(&self.state.cur_ty)
|
||||
} else {
|
||||
self.state.cur_ty
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step_count(&self) -> usize {
|
||||
self.state.steps.len()
|
||||
}
|
||||
|
||||
pub fn into_obligations(self) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
self.state.obligations
|
||||
}
|
||||
|
||||
pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] {
|
||||
&self.state.steps
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span.clone()
|
||||
}
|
||||
|
||||
pub fn reached_recursion_limit(&self) -> bool {
|
||||
self.state.reached_recursion_limit
|
||||
}
|
||||
|
||||
/// also dereference through raw pointer types
|
||||
/// e.g., assuming ptr_to_Foo is the type `*const Foo`
|
||||
/// fcx.autoderef(span, ptr_to_Foo) => [*const Foo]
|
||||
/// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo]
|
||||
pub fn include_raw_pointers(mut self) -> Self {
|
||||
self.include_raw_pointers = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn silence_errors(mut self) -> Self {
|
||||
self.silence_errors = true;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
|
||||
// We've reached the recursion limit, error gracefully.
|
||||
let suggested_limit = tcx.sess.recursion_limit() * 2;
|
||||
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
|
||||
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
|
||||
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
if fresh {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0055,
|
||||
"reached the recursion limit while auto-dereferencing `{:?}`",
|
||||
ty
|
||||
)
|
||||
.span_label(span, "deref recursion limit reached")
|
||||
.help(&format!(
|
||||
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
|
||||
suggested_limit, tcx.crate_name,
|
||||
))
|
||||
.emit();
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ extern crate log;
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
|
||||
pub mod autoderef;
|
||||
pub mod infer;
|
||||
pub mod opaque_types;
|
||||
pub mod traits;
|
||||
|
@ -402,6 +402,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
err.span_label(enclosing_scope_span, s.as_str());
|
||||
}
|
||||
|
||||
self.suggest_dereferences(&obligation, &mut err, &trait_ref, points_at_arg);
|
||||
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
|
||||
self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
|
||||
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
|
||||
|
@ -3,6 +3,7 @@ use super::{
|
||||
SelectionContext,
|
||||
};
|
||||
|
||||
use crate::autoderef::Autoderef;
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::traits::normalize_projection_type;
|
||||
|
||||
@ -13,11 +14,11 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items;
|
||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
|
||||
use rustc_middle::ty::TypeckTables;
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty,
|
||||
TyCtxt, TypeFoldable, WithConstness,
|
||||
};
|
||||
use rustc_middle::ty::{TypeAndMut, TypeckTables};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{MultiSpan, Span, DUMMY_SP};
|
||||
use std::fmt;
|
||||
@ -48,6 +49,14 @@ pub trait InferCtxtExt<'tcx> {
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
);
|
||||
|
||||
fn suggest_dereferences(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'tcx>,
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
points_at_arg: bool,
|
||||
);
|
||||
|
||||
fn get_closure_name(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
@ -450,6 +459,62 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// When after several dereferencing, the reference satisfies the trait
|
||||
/// binding. This function provides dereference suggestion for this
|
||||
/// specific situation.
|
||||
fn suggest_dereferences(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'tcx>,
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
points_at_arg: bool,
|
||||
) {
|
||||
// It only make sense when suggesting dereferences for arguments
|
||||
if !points_at_arg {
|
||||
return;
|
||||
}
|
||||
let param_env = obligation.param_env;
|
||||
let body_id = obligation.cause.body_id;
|
||||
let span = obligation.cause.span;
|
||||
let real_trait_ref = match &obligation.cause.code {
|
||||
ObligationCauseCode::ImplDerivedObligation(cause)
|
||||
| ObligationCauseCode::DerivedObligation(cause)
|
||||
| ObligationCauseCode::BuiltinDerivedObligation(cause) => &cause.parent_trait_ref,
|
||||
_ => trait_ref,
|
||||
};
|
||||
let real_ty = match real_trait_ref.self_ty().no_bound_vars() {
|
||||
Some(ty) => ty,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if let ty::Ref(region, base_ty, mutbl) = real_ty.kind {
|
||||
let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty);
|
||||
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
|
||||
// Re-add the `&`
|
||||
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
|
||||
let obligation =
|
||||
self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_ref, ty);
|
||||
Some(steps).filter(|_| self.predicate_may_hold(&obligation))
|
||||
}) {
|
||||
if steps > 0 {
|
||||
if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
// Don't care about `&mut` because `DerefMut` is used less
|
||||
// often and user will not expect autoderef happens.
|
||||
if src.starts_with("&") && !src.starts_with("&mut ") {
|
||||
let derefs = "*".repeat(steps);
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider adding dereference here",
|
||||
format!("&{}{}", derefs, &src[1..]),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
|
||||
/// suggestion to borrow the initializer in order to use have a slice instead.
|
||||
fn suggest_borrow_on_unsized_slice(
|
||||
|
@ -896,9 +896,12 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||
|
||||
let tcx = selcx.tcx();
|
||||
// Check whether the self-type is itself a projection.
|
||||
let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
|
||||
ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
|
||||
ty::Opaque(def_id, substs) => (def_id, substs),
|
||||
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||
let bounds = match obligation_trait_ref.self_ty().kind {
|
||||
ty::Projection(ref data) => {
|
||||
tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
|
||||
}
|
||||
ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
// If the self-type is an inference variable, then it MAY wind up
|
||||
// being a projected type, so induce an ambiguity.
|
||||
@ -908,17 +911,13 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||
_ => return,
|
||||
};
|
||||
|
||||
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||
let trait_predicates = tcx.predicates_of(def_id);
|
||||
let bounds = trait_predicates.instantiate(tcx, substs);
|
||||
let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate);
|
||||
assemble_candidates_from_predicates(
|
||||
selcx,
|
||||
obligation,
|
||||
obligation_trait_ref,
|
||||
candidate_set,
|
||||
ProjectionTyCandidate::TraitDef,
|
||||
bounds,
|
||||
bounds.iter(),
|
||||
)
|
||||
}
|
||||
|
||||
@ -1484,6 +1483,12 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||
);
|
||||
return Progress { ty: tcx.ty_error(), obligations: nested };
|
||||
}
|
||||
// If we're trying to normalize `<Vec<u32> as X>::A<S>` using
|
||||
//`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
|
||||
//
|
||||
// * `obligation.predicate.substs` is `[Vec<u32>, S]`
|
||||
// * `substs` is `[u32]`
|
||||
// * `substs` ends up as `[u32, S]`
|
||||
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
|
||||
let substs =
|
||||
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
|
||||
|
@ -1273,9 +1273,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
placeholder_trait_predicate,
|
||||
);
|
||||
|
||||
let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind {
|
||||
ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
|
||||
ty::Opaque(def_id, substs) => (def_id, substs),
|
||||
let tcx = self.infcx.tcx;
|
||||
let predicates = match placeholder_trait_predicate.trait_ref.self_ty().kind {
|
||||
ty::Projection(ref data) => {
|
||||
tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
|
||||
}
|
||||
ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
|
||||
_ => {
|
||||
span_bug!(
|
||||
obligation.cause.span,
|
||||
@ -1285,32 +1288,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
);
|
||||
}
|
||||
};
|
||||
debug!(
|
||||
"match_projection_obligation_against_definition_bounds: \
|
||||
def_id={:?}, substs={:?}",
|
||||
def_id, substs
|
||||
);
|
||||
|
||||
let predicates_of = self.tcx().predicates_of(def_id);
|
||||
let bounds = predicates_of.instantiate(self.tcx(), substs);
|
||||
debug!(
|
||||
"match_projection_obligation_against_definition_bounds: \
|
||||
bounds={:?}",
|
||||
bounds
|
||||
);
|
||||
|
||||
let elaborated_predicates =
|
||||
util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter());
|
||||
let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
|
||||
self.infcx.probe(|_| {
|
||||
self.match_projection(
|
||||
obligation,
|
||||
*bound,
|
||||
placeholder_trait_predicate.trait_ref,
|
||||
&placeholder_map,
|
||||
snapshot,
|
||||
)
|
||||
})
|
||||
let matching_bound = predicates.iter().find_map(|bound| {
|
||||
if let ty::PredicateKind::Trait(bound, _) = bound.kind() {
|
||||
let bound = bound.to_poly_trait_ref();
|
||||
if self.infcx.probe(|_| {
|
||||
self.match_projection(
|
||||
obligation,
|
||||
bound,
|
||||
placeholder_trait_predicate.trait_ref,
|
||||
&placeholder_map,
|
||||
snapshot,
|
||||
)
|
||||
}) {
|
||||
return Some(bound);
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
debug!(
|
||||
|
@ -1,8 +1,10 @@
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::hir::map as hir_map;
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
|
||||
use rustc_session::CrateDisambiguator;
|
||||
use rustc_span::symbol::Symbol;
|
||||
@ -365,6 +367,133 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
|
||||
fn_like.asyncness()
|
||||
}
|
||||
|
||||
/// For associated types we allow bounds written on the associated type
|
||||
/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
|
||||
/// when desugared as bounds on the trait `where Self::X: Trait`.
|
||||
///
|
||||
/// Note that this filtering is done with the items identity substs to
|
||||
/// simplify checking that these bounds are met in impls. This means that
|
||||
/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
|
||||
/// `hr-associated-type-bound-1.rs`.
|
||||
fn associated_type_projection_predicates(
|
||||
tcx: TyCtxt<'_>,
|
||||
assoc_item_def_id: DefId,
|
||||
) -> &'_ ty::List<ty::Predicate<'_>> {
|
||||
let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id);
|
||||
// We include predicates from the trait as well to handle
|
||||
// `where Self::X: Trait`.
|
||||
let item_bounds = generic_trait_bounds.instantiate_identity(tcx);
|
||||
let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter());
|
||||
|
||||
let assoc_item_ty = ty::ProjectionTy {
|
||||
item_def_id: assoc_item_def_id,
|
||||
substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
|
||||
};
|
||||
|
||||
let predicates = item_predicates.filter_map(|obligation| {
|
||||
let pred = obligation.predicate;
|
||||
match pred.kind() {
|
||||
ty::PredicateKind::Trait(tr, _) => {
|
||||
if let ty::Projection(p) = tr.skip_binder().self_ty().kind {
|
||||
if p == assoc_item_ty {
|
||||
return Some(pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Projection(proj) => {
|
||||
if let ty::Projection(p) = proj.skip_binder().projection_ty.self_ty().kind {
|
||||
if p == assoc_item_ty {
|
||||
return Some(pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::TypeOutlives(outlives) => {
|
||||
if let ty::Projection(p) = outlives.skip_binder().0.kind {
|
||||
if p == assoc_item_ty {
|
||||
return Some(pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
let result = tcx.mk_predicates(predicates);
|
||||
debug!(
|
||||
"associated_type_projection_predicates({}) = {:?}",
|
||||
tcx.def_path_str(assoc_item_def_id),
|
||||
result
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
/// Opaque types don't have the same issues as associated types: the only
|
||||
/// predicates on an opaque type (excluding those it inherits from its parent
|
||||
/// item) should be of the form we're expecting.
|
||||
fn opaque_type_projection_predicates(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> &'_ ty::List<ty::Predicate<'_>> {
|
||||
let substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
|
||||
let bounds = tcx.predicates_of(def_id);
|
||||
let predicates =
|
||||
util::elaborate_predicates(tcx, bounds.predicates.into_iter().map(|&(pred, _)| pred));
|
||||
|
||||
let filtered_predicates = predicates.filter_map(|obligation| {
|
||||
let pred = obligation.predicate;
|
||||
match pred.kind() {
|
||||
ty::PredicateKind::Trait(tr, _) => {
|
||||
if let ty::Opaque(opaque_def_id, opaque_substs) = tr.skip_binder().self_ty().kind {
|
||||
if opaque_def_id == def_id && opaque_substs == substs {
|
||||
return Some(pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Projection(proj) => {
|
||||
if let ty::Opaque(opaque_def_id, opaque_substs) =
|
||||
proj.skip_binder().projection_ty.self_ty().kind
|
||||
{
|
||||
if opaque_def_id == def_id && opaque_substs == substs {
|
||||
return Some(pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::TypeOutlives(outlives) => {
|
||||
if let ty::Opaque(opaque_def_id, opaque_substs) = outlives.skip_binder().0.kind {
|
||||
if opaque_def_id == def_id && opaque_substs == substs {
|
||||
return Some(pred);
|
||||
}
|
||||
} else {
|
||||
// These can come from elaborating other predicates
|
||||
return None;
|
||||
}
|
||||
}
|
||||
// These can come from elaborating other predicates
|
||||
ty::PredicateKind::RegionOutlives(_) => return None,
|
||||
_ => {}
|
||||
}
|
||||
tcx.sess.delay_span_bug(
|
||||
obligation.cause.span(tcx),
|
||||
&format!("unexpected predicate {:?} on opaque type", pred),
|
||||
);
|
||||
None
|
||||
});
|
||||
|
||||
let result = tcx.mk_predicates(filtered_predicates);
|
||||
debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result);
|
||||
result
|
||||
}
|
||||
|
||||
fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id),
|
||||
DefKind::OpaqueTy => opaque_type_projection_predicates(tcx, def_id),
|
||||
k => bug!("projection_predicates called on {}", k.descr(def_id)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut ty::query::Providers<'_>) {
|
||||
*providers = ty::query::Providers {
|
||||
asyncness,
|
||||
@ -381,6 +510,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
|
||||
instance_def_size_estimate,
|
||||
issue33140_self_ty,
|
||||
impl_defaultness,
|
||||
projection_predicates,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
@ -1,191 +1,46 @@
|
||||
//! Some helper functions for `AutoDeref`
|
||||
use super::method::MethodCallee;
|
||||
use super::{FnCtxt, PlaceOp};
|
||||
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::{InferCtxt, InferOk};
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
|
||||
use rustc_middle::ty::{ToPredicate, TypeFoldable};
|
||||
use rustc_session::DiagnosticMessageId;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, TraitEngine};
|
||||
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
|
||||
|
||||
use std::iter;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum AutoderefKind {
|
||||
Builtin,
|
||||
Overloaded,
|
||||
}
|
||||
|
||||
pub struct Autoderef<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
steps: Vec<(Ty<'tcx>, AutoderefKind)>,
|
||||
cur_ty: Ty<'tcx>,
|
||||
obligations: Vec<traits::PredicateObligation<'tcx>>,
|
||||
at_start: bool,
|
||||
include_raw_pointers: bool,
|
||||
span: Span,
|
||||
silence_errors: bool,
|
||||
reached_recursion_limit: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
||||
type Item = (Ty<'tcx>, usize);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
debug!("autoderef: steps={:?}, cur_ty={:?}", self.steps, self.cur_ty);
|
||||
if self.at_start {
|
||||
self.at_start = false;
|
||||
debug!("autoderef stage #0 is {:?}", self.cur_ty);
|
||||
return Some((self.cur_ty, 0));
|
||||
}
|
||||
|
||||
if !tcx.sess.recursion_limit().value_within_limit(self.steps.len()) {
|
||||
if !self.silence_errors {
|
||||
report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty);
|
||||
}
|
||||
self.reached_recursion_limit = true;
|
||||
return None;
|
||||
}
|
||||
|
||||
if self.cur_ty.is_ty_var() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Otherwise, deref if type is derefable:
|
||||
let (kind, new_ty) = if let Some(mt) = self.cur_ty.builtin_deref(self.include_raw_pointers)
|
||||
{
|
||||
(AutoderefKind::Builtin, mt.ty)
|
||||
} else {
|
||||
let ty = self.overloaded_deref_ty(self.cur_ty)?;
|
||||
(AutoderefKind::Overloaded, ty)
|
||||
};
|
||||
|
||||
if new_ty.references_error() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.steps.push((self.cur_ty, kind));
|
||||
debug!(
|
||||
"autoderef stage #{:?} is {:?} from {:?}",
|
||||
self.steps.len(),
|
||||
new_ty,
|
||||
(self.cur_ty, kind)
|
||||
);
|
||||
self.cur_ty = new_ty;
|
||||
|
||||
Some((self.cur_ty, self.steps.len()))
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
pub fn new(
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
body_id: hir::HirId,
|
||||
pub fn try_overloaded_deref(
|
||||
&self,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef {
|
||||
infcx,
|
||||
body_id,
|
||||
param_env,
|
||||
steps: vec![],
|
||||
cur_ty: infcx.resolve_vars_if_possible(&base_ty),
|
||||
obligations: vec![],
|
||||
at_start: true,
|
||||
include_raw_pointers: false,
|
||||
silence_errors: false,
|
||||
reached_recursion_limit: false,
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||
debug!("overloaded_deref_ty({:?})", ty);
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
// <ty as Deref>
|
||||
let trait_ref = TraitRef {
|
||||
def_id: tcx.lang_items().deref_trait()?,
|
||||
substs: tcx.mk_substs_trait(ty, &[]),
|
||||
};
|
||||
|
||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||
|
||||
let obligation = traits::Obligation::new(
|
||||
cause.clone(),
|
||||
self.param_env,
|
||||
trait_ref.without_const().to_predicate(tcx),
|
||||
);
|
||||
if !self.infcx.predicate_may_hold(&obligation) {
|
||||
debug!("overloaded_deref_ty: cannot match obligation");
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot();
|
||||
let normalized_ty = fulfillcx.normalize_projection_type(
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, Ident::from_str("Target")),
|
||||
cause,
|
||||
);
|
||||
if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
|
||||
// This shouldn't happen, except for evaluate/fulfill mismatches,
|
||||
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
||||
// by design).
|
||||
debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e);
|
||||
return None;
|
||||
}
|
||||
let obligations = fulfillcx.pending_obligations();
|
||||
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
|
||||
self.obligations.extend(obligations);
|
||||
|
||||
Some(self.infcx.resolve_vars_if_possible(&normalized_ty))
|
||||
}
|
||||
|
||||
/// Returns the final type, generating an error if it is an
|
||||
/// unresolved inference variable.
|
||||
pub fn unambiguous_final_ty(&self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
|
||||
fcx.structurally_resolved_type(self.span, self.cur_ty)
|
||||
}
|
||||
|
||||
/// Returns the final type we ended up with, which may well be an
|
||||
/// inference variable (we will resolve it first, if possible).
|
||||
pub fn maybe_ambiguous_final_ty(&self) -> Ty<'tcx> {
|
||||
self.infcx.resolve_vars_if_possible(&self.cur_ty)
|
||||
}
|
||||
|
||||
pub fn step_count(&self) -> usize {
|
||||
self.steps.len()
|
||||
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
|
||||
self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
|
||||
}
|
||||
|
||||
/// Returns the adjustment steps.
|
||||
pub fn adjust_steps(&self, fcx: &FnCtxt<'a, 'tcx>) -> Vec<Adjustment<'tcx>> {
|
||||
fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(fcx))
|
||||
pub fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec<Adjustment<'tcx>> {
|
||||
self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef))
|
||||
}
|
||||
|
||||
pub fn adjust_steps_as_infer_ok(
|
||||
&self,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
autoderef: &Autoderef<'a, 'tcx>,
|
||||
) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
|
||||
let mut obligations = vec![];
|
||||
let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(self.cur_ty));
|
||||
let steps: Vec<_> = self
|
||||
.steps
|
||||
let steps = autoderef.steps();
|
||||
let targets =
|
||||
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
|
||||
let steps: Vec<_> = steps
|
||||
.iter()
|
||||
.map(|&(source, kind)| {
|
||||
if let AutoderefKind::Overloaded = kind {
|
||||
fcx.try_overloaded_deref(self.span, source).and_then(
|
||||
self.try_overloaded_deref(autoderef.span(), source).and_then(
|
||||
|InferOk { value: method, obligations: o }| {
|
||||
obligations.extend(o);
|
||||
if let ty::Ref(region, _, mutbl) = method.sig.output().kind {
|
||||
@ -205,67 +60,4 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
|
||||
InferOk { obligations, value: steps }
|
||||
}
|
||||
|
||||
/// also dereference through raw pointer types
|
||||
/// e.g., assuming ptr_to_Foo is the type `*const Foo`
|
||||
/// fcx.autoderef(span, ptr_to_Foo) => [*const Foo]
|
||||
/// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo]
|
||||
pub fn include_raw_pointers(mut self) -> Self {
|
||||
self.include_raw_pointers = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn silence_errors(mut self) -> Self {
|
||||
self.silence_errors = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn reached_recursion_limit(&self) -> bool {
|
||||
self.reached_recursion_limit
|
||||
}
|
||||
|
||||
pub fn finalize(self, fcx: &FnCtxt<'a, 'tcx>) {
|
||||
fcx.register_predicates(self.into_obligations());
|
||||
}
|
||||
|
||||
pub fn into_obligations(self) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
self.obligations
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
|
||||
// We've reached the recursion limit, error gracefully.
|
||||
let suggested_limit = tcx.sess.recursion_limit() * 2;
|
||||
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
|
||||
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
|
||||
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
if fresh {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0055,
|
||||
"reached the recursion limit while auto-dereferencing `{:?}`",
|
||||
ty
|
||||
)
|
||||
.span_label(span, "deref recursion limit reached")
|
||||
.help(&format!(
|
||||
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
|
||||
suggested_limit, tcx.crate_name,
|
||||
))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
|
||||
}
|
||||
|
||||
pub fn try_overloaded_deref(
|
||||
&self,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
|
||||
self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
use super::autoderef::Autoderef;
|
||||
use super::method::MethodCallee;
|
||||
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
||||
use crate::type_error_struct;
|
||||
@ -17,6 +16,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
|
||||
/// Checks that it is legal to call methods of the trait corresponding
|
||||
/// to `trait_id` (this only cares about the trait, not the specific
|
||||
@ -72,7 +72,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
while result.is_none() && autoderef.next().is_some() {
|
||||
result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
|
||||
}
|
||||
autoderef.finalize(self);
|
||||
self.register_predicates(autoderef.into_obligations());
|
||||
|
||||
let output = match result {
|
||||
None => {
|
||||
@ -106,7 +106,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
||||
autoderef: &Autoderef<'a, 'tcx>,
|
||||
) -> Option<CallStep<'tcx>> {
|
||||
let adjusted_ty = autoderef.unambiguous_final_ty(self);
|
||||
let adjusted_ty =
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
debug!(
|
||||
"try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
|
||||
call_expr, adjusted_ty
|
||||
@ -115,7 +116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// If the callee is a bare function or a closure, then we're all set.
|
||||
match adjusted_ty.kind {
|
||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||
let adjustments = autoderef.adjust_steps(self);
|
||||
let adjustments = self.adjust_steps(autoderef);
|
||||
self.apply_adjustments(callee_expr, adjustments);
|
||||
return Some(CallStep::Builtin(adjusted_ty));
|
||||
}
|
||||
@ -135,7 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&closure_sig,
|
||||
)
|
||||
.0;
|
||||
let adjustments = autoderef.adjust_steps(self);
|
||||
let adjustments = self.adjust_steps(autoderef);
|
||||
self.record_deferred_call_resolution(
|
||||
def_id,
|
||||
DeferredCallResolution {
|
||||
@ -176,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs))
|
||||
.or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None))
|
||||
.map(|(autoref, method)| {
|
||||
let mut adjustments = autoderef.adjust_steps(self);
|
||||
let mut adjustments = self.adjust_steps(autoderef);
|
||||
adjustments.extend(autoref);
|
||||
self.apply_adjustments(callee_expr, adjustments);
|
||||
CallStep::Overloaded(method)
|
||||
|
@ -409,7 +409,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
}
|
||||
|
||||
let InferOk { value: mut adjustments, obligations: o } =
|
||||
autoderef.adjust_steps_as_infer_ok(self);
|
||||
self.adjust_steps_as_infer_ok(&autoderef);
|
||||
obligations.extend(o);
|
||||
obligations.extend(autoderef.into_obligations());
|
||||
|
||||
|
@ -4,15 +4,17 @@ use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
|
||||
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||
use rustc_middle::ty::util::ExplicitSelf;
|
||||
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
|
||||
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
||||
|
||||
use super::{potentially_plural_count, FnCtxt, Inherited};
|
||||
use std::iter;
|
||||
|
||||
/// Checks that a method from an impl conforms to the signature of
|
||||
/// the same method as declared in the trait.
|
||||
@ -1057,13 +1059,15 @@ crate fn compare_ty_impl<'tcx>(
|
||||
let _: Result<(), ErrorReported> = (|| {
|
||||
compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
|
||||
|
||||
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
|
||||
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
|
||||
|
||||
compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
|
||||
})();
|
||||
}
|
||||
|
||||
/// The equivalent of [compare_predicate_entailment], but for associated types
|
||||
/// instead of associated functions.
|
||||
fn compare_type_predicate_entailment(
|
||||
fn compare_type_predicate_entailment<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_ty: &ty::AssocItem,
|
||||
impl_ty_span: Span,
|
||||
@ -1165,6 +1169,145 @@ fn compare_type_predicate_entailment(
|
||||
})
|
||||
}
|
||||
|
||||
/// Validate that `ProjectionCandidate`s created for this associated type will
|
||||
/// be valid.
|
||||
///
|
||||
/// Usually given
|
||||
///
|
||||
/// trait X { type Y: Copy } impl X for T { type Y = S; }
|
||||
///
|
||||
/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
|
||||
/// impl is well-formed we have to prove `S: Copy`.
|
||||
///
|
||||
/// For default associated types the normalization is not possible (the value
|
||||
/// from the impl could be overridden). We also can't normalize generic
|
||||
/// associated types (yet) because they contain bound parameters.
|
||||
fn compare_projection_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ty: &ty::AssocItem,
|
||||
impl_ty: &ty::AssocItem,
|
||||
impl_ty_span: Span,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> Result<(), ErrorReported> {
|
||||
let have_gats = tcx.features().generic_associated_types;
|
||||
if impl_ty.defaultness.is_final() && !have_gats {
|
||||
// For "final", non-generic associate type implementations, we
|
||||
// don't need this as described above.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let param_env = tcx.param_env(impl_ty.def_id);
|
||||
|
||||
// Given
|
||||
//
|
||||
// impl<A, B> Foo<u32> for (A, B) {
|
||||
// type Bar<C> =...
|
||||
// }
|
||||
//
|
||||
// - `impl_substs` would be `[A, B, C]`
|
||||
// - `rebased_substs` would be `[(A, B), u32, C]`, combining the substs from
|
||||
// the *trait* with the generic associated type parameters.
|
||||
let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
|
||||
let rebased_substs =
|
||||
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
|
||||
let impl_ty_value = tcx.type_of(impl_ty.def_id);
|
||||
|
||||
// Map the predicate from the trait to the corresponding one for the impl.
|
||||
// For example:
|
||||
//
|
||||
// trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; }
|
||||
// impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; }
|
||||
//
|
||||
// For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this
|
||||
// function would translate and partially normalize
|
||||
// `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
|
||||
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
|
||||
tcx.mk_substs(
|
||||
iter::once(impl_ty_value.into())
|
||||
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, rebased_substs))),
|
||||
)
|
||||
};
|
||||
|
||||
tcx.infer_ctxt().enter(move |infcx| {
|
||||
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
|
||||
let infcx = &inh.infcx;
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
|
||||
let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
|
||||
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
|
||||
let cause = ObligationCause::new(
|
||||
impl_ty_span,
|
||||
impl_ty_hir_id,
|
||||
ObligationCauseCode::ItemObligation(trait_ty.def_id),
|
||||
);
|
||||
|
||||
let predicates = tcx.projection_predicates(trait_ty.def_id);
|
||||
|
||||
debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
|
||||
|
||||
for predicate in predicates {
|
||||
let concrete_ty_predicate = match predicate.kind() {
|
||||
ty::PredicateKind::Trait(poly_tr, c) => poly_tr
|
||||
.map_bound(|tr| {
|
||||
let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
|
||||
ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
|
||||
})
|
||||
.with_constness(*c)
|
||||
.to_predicate(tcx),
|
||||
ty::PredicateKind::Projection(poly_projection) => poly_projection
|
||||
.map_bound(|projection| {
|
||||
let projection_substs =
|
||||
translate_predicate_substs(projection.projection_ty.substs);
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy {
|
||||
substs: projection_substs,
|
||||
item_def_id: projection.projection_ty.item_def_id,
|
||||
},
|
||||
ty: projection.ty.subst(tcx, rebased_substs),
|
||||
}
|
||||
})
|
||||
.to_predicate(tcx),
|
||||
ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives
|
||||
.map_bound(|outlives| {
|
||||
ty::OutlivesPredicate(impl_ty_value, outlives.1.subst(tcx, rebased_substs))
|
||||
})
|
||||
.to_predicate(tcx),
|
||||
_ => bug!("unexepected projection predicate kind: `{:?}`", predicate),
|
||||
};
|
||||
|
||||
let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
|
||||
&mut selcx,
|
||||
param_env,
|
||||
normalize_cause.clone(),
|
||||
&concrete_ty_predicate,
|
||||
);
|
||||
|
||||
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
|
||||
|
||||
inh.register_predicates(obligations);
|
||||
inh.register_predicate(traits::Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
normalized_predicate,
|
||||
));
|
||||
}
|
||||
|
||||
// Check that all obligations are satisfied by the implementation's
|
||||
// version.
|
||||
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
|
||||
infcx.report_fulfillment_errors(errors, None, false);
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
|
||||
fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
|
||||
match impl_item.kind {
|
||||
ty::AssocKind::Const => "const",
|
||||
|
@ -1447,9 +1447,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// of error recovery.
|
||||
self.write_field_index(expr.hir_id, index);
|
||||
if field.vis.is_accessible_from(def_scope, self.tcx) {
|
||||
let adjustments = autoderef.adjust_steps(self);
|
||||
let adjustments = self.adjust_steps(&autoderef);
|
||||
self.apply_adjustments(base, adjustments);
|
||||
autoderef.finalize(self);
|
||||
self.register_predicates(autoderef.into_obligations());
|
||||
|
||||
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span);
|
||||
return field_ty;
|
||||
@ -1462,9 +1462,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let Ok(index) = fstr.parse::<usize>() {
|
||||
if fstr == index.to_string() {
|
||||
if let Some(field_ty) = tys.get(index) {
|
||||
let adjustments = autoderef.adjust_steps(self);
|
||||
let adjustments = self.adjust_steps(&autoderef);
|
||||
self.apply_adjustments(base, adjustments);
|
||||
autoderef.finalize(self);
|
||||
self.register_predicates(autoderef.into_obligations());
|
||||
|
||||
self.write_field_index(expr.hir_id, index);
|
||||
return field_ty.expect_ty();
|
||||
@ -1475,7 +1475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
autoderef.unambiguous_final_ty(self);
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
|
||||
if let Some((did, field_ty)) = private_candidate {
|
||||
self.ban_private_field_access(expr, expr_t, field, did);
|
||||
|
@ -144,9 +144,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
};
|
||||
assert_eq!(n, pick.autoderefs);
|
||||
|
||||
let mut adjustments = autoderef.adjust_steps(self);
|
||||
let mut adjustments = self.adjust_steps(&autoderef);
|
||||
|
||||
let mut target = autoderef.unambiguous_final_ty(self);
|
||||
let mut target =
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
|
||||
if let Some(mutbl) = pick.autoref {
|
||||
let region = self.next_region_var(infer::Autoref(self.span));
|
||||
@ -176,7 +177,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
assert!(pick.unsize.is_none());
|
||||
}
|
||||
|
||||
autoderef.finalize(self);
|
||||
self.register_predicates(autoderef.into_obligations());
|
||||
|
||||
// Write out the final adjustments.
|
||||
self.apply_adjustments(self.self_expr, adjustments);
|
||||
|
@ -3,7 +3,6 @@ use super::MethodError;
|
||||
use super::NoMatchData;
|
||||
use super::{CandidateSource, ImplSource, TraitSource};
|
||||
|
||||
use crate::check::autoderef::{self, Autoderef};
|
||||
use crate::check::FnCtxt;
|
||||
use crate::hir::def::DefKind;
|
||||
use crate::hir::def_id::DefId;
|
||||
@ -30,6 +29,7 @@ use rustc_session::config::nightly_options;
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
|
||||
use rustc_trait_selection::autoderef::{self, Autoderef};
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
|
||||
use rustc_trait_selection::traits::query::method_autoderef::{
|
||||
@ -477,7 +477,7 @@ fn method_autoderef_steps<'tcx>(
|
||||
})
|
||||
.collect();
|
||||
|
||||
let final_ty = autoderef.maybe_ambiguous_final_ty();
|
||||
let final_ty = autoderef.final_ty(true);
|
||||
let opt_bad_ty = match final_ty.kind {
|
||||
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
|
||||
reached_raw_pointer,
|
||||
|
@ -2281,7 +2281,7 @@ fn check_impl_items_against_trait<'tcx>(
|
||||
&ty_trait_item,
|
||||
impl_trait_ref,
|
||||
opt_trait_span,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::check::autoderef::Autoderef;
|
||||
use crate::check::method::MethodCallee;
|
||||
use crate::check::{FnCtxt, PlaceOp};
|
||||
use rustc_hir as hir;
|
||||
@ -9,6 +8,7 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
|
||||
@ -57,7 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
while result.is_none() && autoderef.next().is_some() {
|
||||
result = self.try_index_step(expr, base_expr, &autoderef, idx_ty);
|
||||
}
|
||||
autoderef.finalize(self);
|
||||
self.register_predicates(autoderef.into_obligations());
|
||||
result
|
||||
}
|
||||
|
||||
@ -73,7 +73,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
autoderef: &Autoderef<'a, 'tcx>,
|
||||
index_ty: Ty<'tcx>,
|
||||
) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> {
|
||||
let adjusted_ty = autoderef.unambiguous_final_ty(self);
|
||||
let adjusted_ty =
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
debug!(
|
||||
"try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
|
||||
index_ty={:?})",
|
||||
@ -105,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
debug!("try_index_step: success, using overloaded indexing");
|
||||
let method = self.register_infer_ok_obligations(ok);
|
||||
|
||||
let mut adjustments = autoderef.adjust_steps(self);
|
||||
let mut adjustments = self.adjust_steps(autoderef);
|
||||
if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind {
|
||||
adjustments.push(Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, AutoBorrowMutability::Not)),
|
||||
|
@ -1118,7 +1118,7 @@ fn receiver_is_valid<'fcx, 'tcx>(
|
||||
);
|
||||
|
||||
if can_eq_self(potential_self_ty) {
|
||||
autoderef.finalize(fcx);
|
||||
fcx.register_predicates(autoderef.into_obligations());
|
||||
|
||||
if let Some(mut err) =
|
||||
fcx.demand_eqtype_with_origin(&cause, self_ty, potential_self_ty)
|
||||
|
@ -35,7 +35,7 @@ use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc_middle::mir::mono::Linkage;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::Discr;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
|
||||
@ -1692,6 +1692,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
||||
|
||||
let mut is_trait = None;
|
||||
let mut is_default_impl_trait = None;
|
||||
let mut is_trait_associated_type = None;
|
||||
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let constness = icx.default_constness_for_trait_bounds();
|
||||
@ -1701,7 +1702,12 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
||||
let mut predicates = UniquePredicates::new();
|
||||
|
||||
let ast_generics = match node {
|
||||
Node::TraitItem(item) => &item.generics,
|
||||
Node::TraitItem(item) => {
|
||||
if let hir::TraitItemKind::Type(bounds, _) = item.kind {
|
||||
is_trait_associated_type = Some((bounds, item.span));
|
||||
}
|
||||
&item.generics
|
||||
}
|
||||
|
||||
Node::ImplItem(item) => &item.generics,
|
||||
|
||||
@ -1925,10 +1931,21 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
||||
}
|
||||
}
|
||||
|
||||
// Add predicates from associated type bounds.
|
||||
if let Some((self_trait_ref, trait_items)) = is_trait {
|
||||
// Add predicates from associated type bounds (`type X: Bound`)
|
||||
if tcx.features().generic_associated_types {
|
||||
// New behavior: bounds declared on associate type are predicates of that
|
||||
// associated type. Not the default because it needs more testing.
|
||||
if let Some((bounds, span)) = is_trait_associated_type {
|
||||
let projection_ty =
|
||||
tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id));
|
||||
|
||||
predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span))
|
||||
}
|
||||
} else if let Some((self_trait_ref, trait_items)) = is_trait {
|
||||
// Current behavior: bounds declared on associate type are predicates
|
||||
// of its parent trait.
|
||||
predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
|
||||
associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
|
||||
trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
|
||||
}))
|
||||
}
|
||||
|
||||
@ -1958,7 +1975,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
||||
result
|
||||
}
|
||||
|
||||
fn associated_item_predicates(
|
||||
fn trait_associated_item_predicates(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
self_trait_ref: ty::TraitRef<'tcx>,
|
||||
@ -1971,92 +1988,40 @@ fn associated_item_predicates(
|
||||
_ => return Vec::new(),
|
||||
};
|
||||
|
||||
let is_gat = !tcx.generics_of(item_def_id).params.is_empty();
|
||||
if !tcx.generics_of(item_def_id).params.is_empty() {
|
||||
// For GATs the substs provided to the mk_projection call below are
|
||||
// wrong. We should emit a feature gate error if we get here so skip
|
||||
// this type.
|
||||
tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate");
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut had_error = false;
|
||||
|
||||
let mut unimplemented_error = |arg_kind: &str| {
|
||||
if !had_error {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
trait_item.span,
|
||||
&format!("{}-generic associated types are not yet implemented", arg_kind),
|
||||
)
|
||||
.note(
|
||||
"for more information, see issue #44265 \
|
||||
<https://github.com/rust-lang/rust/issues/44265> for more information",
|
||||
)
|
||||
.emit();
|
||||
had_error = true;
|
||||
}
|
||||
};
|
||||
|
||||
let mk_bound_param = |param: &ty::GenericParamDef, _: &_| {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => tcx
|
||||
.mk_region(ty::RegionKind::ReLateBound(
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion::BrNamed(param.def_id, param.name),
|
||||
))
|
||||
.into(),
|
||||
// FIXME(generic_associated_types): Use bound types and constants
|
||||
// once they are handled by the trait system.
|
||||
ty::GenericParamDefKind::Type { .. } => {
|
||||
unimplemented_error("type");
|
||||
tcx.ty_error().into()
|
||||
}
|
||||
ty::GenericParamDefKind::Const => {
|
||||
unimplemented_error("const");
|
||||
tcx.const_error(tcx.type_of(param.def_id)).into()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let bound_substs = if is_gat {
|
||||
// Given:
|
||||
//
|
||||
// trait X<'a, B, const C: usize> {
|
||||
// type T<'d, E, const F: usize>: Default;
|
||||
// }
|
||||
//
|
||||
// We need to create predicates on the trait:
|
||||
//
|
||||
// for<'d, E, const F: usize>
|
||||
// <Self as X<'a, B, const C: usize>>::T<'d, E, const F: usize>: Sized + Default
|
||||
//
|
||||
// We substitute escaping bound parameters for the generic
|
||||
// arguments to the associated type which are then bound by
|
||||
// the `Binder` around the the predicate.
|
||||
//
|
||||
// FIXME(generic_associated_types): Currently only lifetimes are handled.
|
||||
self_trait_ref.substs.extend_to(tcx, item_def_id.to_def_id(), mk_bound_param)
|
||||
} else {
|
||||
self_trait_ref.substs
|
||||
};
|
||||
|
||||
let assoc_ty =
|
||||
tcx.mk_projection(tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), bound_substs);
|
||||
|
||||
let bounds = AstConv::compute_bounds(
|
||||
&ItemCtxt::new(tcx, def_id),
|
||||
assoc_ty,
|
||||
bounds,
|
||||
SizedByDefault::Yes,
|
||||
trait_item.span,
|
||||
let assoc_ty = tcx.mk_projection(
|
||||
tcx.hir().local_def_id(trait_item.hir_id).to_def_id(),
|
||||
self_trait_ref.substs,
|
||||
);
|
||||
|
||||
let predicates = bounds.predicates(tcx, assoc_ty);
|
||||
associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span)
|
||||
}
|
||||
|
||||
if is_gat {
|
||||
// We use shifts to get the regions that we're substituting to
|
||||
// be bound by the binders in the `Predicate`s rather that
|
||||
// escaping.
|
||||
let shifted_in = ty::fold::shift_vars(tcx, &predicates, 1);
|
||||
let substituted = shifted_in.subst(tcx, bound_substs);
|
||||
ty::fold::shift_out_vars(tcx, &substituted, 1)
|
||||
} else {
|
||||
predicates
|
||||
}
|
||||
fn associated_item_bounds(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
projection_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> Vec<(ty::Predicate<'tcx>, Span)> {
|
||||
let bounds = AstConv::compute_bounds(
|
||||
&ItemCtxt::new(tcx, def_id),
|
||||
projection_ty,
|
||||
bounds,
|
||||
SizedByDefault::Yes,
|
||||
span,
|
||||
);
|
||||
|
||||
let predicates = bounds.predicates(tcx, projection_ty);
|
||||
|
||||
predicates
|
||||
}
|
||||
|
||||
/// Converts a specific `GenericBound` from the AST into a set of
|
||||
|
@ -12,7 +12,7 @@
|
||||
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
|
||||
# `0.(x+1).0` for Cargo where they were released on `date`.
|
||||
|
||||
date: 2020-06-03
|
||||
date: 2020-06-16
|
||||
rustc: beta
|
||||
cargo: beta
|
||||
|
||||
|
53
src/test/codegen/asm-multiple-options.rs
Normal file
53
src/test/codegen/asm-multiple-options.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// compile-flags: -O
|
||||
// only-x86_64
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(asm)]
|
||||
|
||||
// CHECK-LABEL: @pure
|
||||
// CHECK-NOT: asm
|
||||
// CHECK: ret void
|
||||
#[no_mangle]
|
||||
pub unsafe fn pure(x: i32) {
|
||||
let y: i32;
|
||||
asm!("", out("ax") y, in("bx") x, options(pure), options(nomem));
|
||||
}
|
||||
|
||||
pub static mut VAR: i32 = 0;
|
||||
pub static mut DUMMY_OUTPUT: i32 = 0;
|
||||
|
||||
// CHECK-LABEL: @readonly
|
||||
// CHECK: call i32 asm
|
||||
// CHECK: ret i32 1
|
||||
#[no_mangle]
|
||||
pub unsafe fn readonly() -> i32 {
|
||||
VAR = 1;
|
||||
asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly));
|
||||
VAR
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @nomem
|
||||
// CHECK-NOT: store
|
||||
// CHECK: call i32 asm
|
||||
// CHECK: store
|
||||
// CHECK: ret i32 2
|
||||
#[no_mangle]
|
||||
pub unsafe fn nomem() -> i32 {
|
||||
VAR = 1;
|
||||
asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(nomem));
|
||||
VAR = 2;
|
||||
VAR
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @not_nomem
|
||||
// CHECK: store
|
||||
// CHECK: call i32 asm
|
||||
// CHECK: store
|
||||
// CHECK: ret i32 2
|
||||
#[no_mangle]
|
||||
pub unsafe fn not_nomem() -> i32 {
|
||||
VAR = 1;
|
||||
asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly));
|
||||
VAR = 2;
|
||||
VAR
|
||||
}
|
26
src/test/ui/asm/duplicate-options.fixed
Normal file
26
src/test/ui/asm/duplicate-options.fixed
Normal file
@ -0,0 +1,26 @@
|
||||
// only-x86_64
|
||||
// run-rustfix
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
asm!("", options(nomem, ));
|
||||
//~^ ERROR the `nomem` option was already provided
|
||||
asm!("", options(att_syntax, ));
|
||||
//~^ ERROR the `att_syntax` option was already provided
|
||||
asm!("", options(nostack, att_syntax), options());
|
||||
//~^ ERROR the `nostack` option was already provided
|
||||
asm!("", options(nostack, ), options(), options());
|
||||
//~^ ERROR the `nostack` option was already provided
|
||||
//~| ERROR the `nostack` option was already provided
|
||||
//~| ERROR the `nostack` option was already provided
|
||||
asm!(
|
||||
"",
|
||||
options(nomem, noreturn),
|
||||
options(att_syntax, ), //~ ERROR the `noreturn` option was already provided
|
||||
options( nostack), //~ ERROR the `nomem` option was already provided
|
||||
options(), //~ ERROR the `noreturn` option was already provided
|
||||
);
|
||||
}
|
||||
}
|
26
src/test/ui/asm/duplicate-options.rs
Normal file
26
src/test/ui/asm/duplicate-options.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// only-x86_64
|
||||
// run-rustfix
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
asm!("", options(nomem, nomem));
|
||||
//~^ ERROR the `nomem` option was already provided
|
||||
asm!("", options(att_syntax, att_syntax));
|
||||
//~^ ERROR the `att_syntax` option was already provided
|
||||
asm!("", options(nostack, att_syntax), options(nostack));
|
||||
//~^ ERROR the `nostack` option was already provided
|
||||
asm!("", options(nostack, nostack), options(nostack), options(nostack));
|
||||
//~^ ERROR the `nostack` option was already provided
|
||||
//~| ERROR the `nostack` option was already provided
|
||||
//~| ERROR the `nostack` option was already provided
|
||||
asm!(
|
||||
"",
|
||||
options(nomem, noreturn),
|
||||
options(att_syntax, noreturn), //~ ERROR the `noreturn` option was already provided
|
||||
options(nomem, nostack), //~ ERROR the `nomem` option was already provided
|
||||
options(noreturn), //~ ERROR the `noreturn` option was already provided
|
||||
);
|
||||
}
|
||||
}
|
56
src/test/ui/asm/duplicate-options.stderr
Normal file
56
src/test/ui/asm/duplicate-options.stderr
Normal file
@ -0,0 +1,56 @@
|
||||
error: the `nomem` option was already provided
|
||||
--> $DIR/duplicate-options.rs:8:33
|
||||
|
|
||||
LL | asm!("", options(nomem, nomem));
|
||||
| ^^^^^ this option was already provided
|
||||
|
||||
error: the `att_syntax` option was already provided
|
||||
--> $DIR/duplicate-options.rs:10:38
|
||||
|
|
||||
LL | asm!("", options(att_syntax, att_syntax));
|
||||
| ^^^^^^^^^^ this option was already provided
|
||||
|
||||
error: the `nostack` option was already provided
|
||||
--> $DIR/duplicate-options.rs:12:56
|
||||
|
|
||||
LL | asm!("", options(nostack, att_syntax), options(nostack));
|
||||
| ^^^^^^^ this option was already provided
|
||||
|
||||
error: the `nostack` option was already provided
|
||||
--> $DIR/duplicate-options.rs:14:35
|
||||
|
|
||||
LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
|
||||
| ^^^^^^^ this option was already provided
|
||||
|
||||
error: the `nostack` option was already provided
|
||||
--> $DIR/duplicate-options.rs:14:53
|
||||
|
|
||||
LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
|
||||
| ^^^^^^^ this option was already provided
|
||||
|
||||
error: the `nostack` option was already provided
|
||||
--> $DIR/duplicate-options.rs:14:71
|
||||
|
|
||||
LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
|
||||
| ^^^^^^^ this option was already provided
|
||||
|
||||
error: the `noreturn` option was already provided
|
||||
--> $DIR/duplicate-options.rs:21:33
|
||||
|
|
||||
LL | options(att_syntax, noreturn),
|
||||
| ^^^^^^^^ this option was already provided
|
||||
|
||||
error: the `nomem` option was already provided
|
||||
--> $DIR/duplicate-options.rs:22:21
|
||||
|
|
||||
LL | options(nomem, nostack),
|
||||
| ^^^^^ this option was already provided
|
||||
|
||||
error: the `noreturn` option was already provided
|
||||
--> $DIR/duplicate-options.rs:23:21
|
||||
|
|
||||
LL | options(noreturn),
|
||||
| ^^^^^^^^ this option was already provided
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
@ -34,11 +34,6 @@ fn main() {
|
||||
//~^ ERROR expected one of
|
||||
asm!("", options(nomem, foo));
|
||||
//~^ ERROR expected one of
|
||||
asm!("", options(), options());
|
||||
//~^ ERROR asm options cannot be specified multiple times
|
||||
asm!("", options(), options(), options());
|
||||
//~^ ERROR asm options cannot be specified multiple times
|
||||
//~^^ ERROR asm options cannot be specified multiple times
|
||||
asm!("{}", options(), const foo);
|
||||
//~^ ERROR arguments are not allowed after options
|
||||
asm!("{a}", a = const foo, a = const bar);
|
||||
|
@ -82,32 +82,8 @@ error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `prese
|
||||
LL | asm!("", options(nomem, foo));
|
||||
| ^^^ expected one of 8 possible tokens
|
||||
|
||||
error: asm options cannot be specified multiple times
|
||||
--> $DIR/parse-error.rs:37:29
|
||||
|
|
||||
LL | asm!("", options(), options());
|
||||
| --------- ^^^^^^^^^ duplicate options
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: asm options cannot be specified multiple times
|
||||
--> $DIR/parse-error.rs:39:29
|
||||
|
|
||||
LL | asm!("", options(), options(), options());
|
||||
| --------- ^^^^^^^^^ duplicate options
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: asm options cannot be specified multiple times
|
||||
--> $DIR/parse-error.rs:39:40
|
||||
|
|
||||
LL | asm!("", options(), options(), options());
|
||||
| --------- ^^^^^^^^^ duplicate options
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: arguments are not allowed after options
|
||||
--> $DIR/parse-error.rs:42:31
|
||||
--> $DIR/parse-error.rs:37:31
|
||||
|
|
||||
LL | asm!("{}", options(), const foo);
|
||||
| --------- ^^^^^^^^^ argument
|
||||
@ -115,7 +91,7 @@ LL | asm!("{}", options(), const foo);
|
||||
| previous options
|
||||
|
||||
error: duplicate argument named `a`
|
||||
--> $DIR/parse-error.rs:44:36
|
||||
--> $DIR/parse-error.rs:39:36
|
||||
|
|
||||
LL | asm!("{a}", a = const foo, a = const bar);
|
||||
| ------------- ^^^^^^^^^^^^^ duplicate argument
|
||||
@ -123,7 +99,7 @@ LL | asm!("{a}", a = const foo, a = const bar);
|
||||
| previously here
|
||||
|
||||
error: argument never used
|
||||
--> $DIR/parse-error.rs:44:36
|
||||
--> $DIR/parse-error.rs:39:36
|
||||
|
|
||||
LL | asm!("{a}", a = const foo, a = const bar);
|
||||
| ^^^^^^^^^^^^^ argument never used
|
||||
@ -131,13 +107,13 @@ LL | asm!("{a}", a = const foo, a = const bar);
|
||||
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
|
||||
|
||||
error: explicit register arguments cannot have names
|
||||
--> $DIR/parse-error.rs:47:18
|
||||
--> $DIR/parse-error.rs:42:18
|
||||
|
|
||||
LL | asm!("", a = in("eax") foo);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: named arguments cannot follow explicit register arguments
|
||||
--> $DIR/parse-error.rs:49:36
|
||||
--> $DIR/parse-error.rs:44:36
|
||||
|
|
||||
LL | asm!("{a}", in("eax") foo, a = const bar);
|
||||
| ------------- ^^^^^^^^^^^^^ named argument
|
||||
@ -145,7 +121,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
|
||||
| explicit register argument
|
||||
|
||||
error: named arguments cannot follow explicit register arguments
|
||||
--> $DIR/parse-error.rs:51:36
|
||||
--> $DIR/parse-error.rs:46:36
|
||||
|
|
||||
LL | asm!("{a}", in("eax") foo, a = const bar);
|
||||
| ------------- ^^^^^^^^^^^^^ named argument
|
||||
@ -153,7 +129,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
|
||||
| explicit register argument
|
||||
|
||||
error: positional arguments cannot follow named arguments or explicit register arguments
|
||||
--> $DIR/parse-error.rs:53:36
|
||||
--> $DIR/parse-error.rs:48:36
|
||||
|
|
||||
LL | asm!("{1}", in("eax") foo, const bar);
|
||||
| ------------- ^^^^^^^^^ positional argument
|
||||
@ -161,19 +137,19 @@ LL | asm!("{1}", in("eax") foo, const bar);
|
||||
| explicit register argument
|
||||
|
||||
error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
|
||||
--> $DIR/parse-error.rs:55:29
|
||||
--> $DIR/parse-error.rs:50:29
|
||||
|
|
||||
LL | asm!("", options(), "");
|
||||
| ^^ expected one of 8 possible tokens
|
||||
|
||||
error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
|
||||
--> $DIR/parse-error.rs:57:33
|
||||
--> $DIR/parse-error.rs:52:33
|
||||
|
|
||||
LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
|
||||
| ^^^^ expected one of 8 possible tokens
|
||||
|
||||
error: asm template must be a string literal
|
||||
--> $DIR/parse-error.rs:59:14
|
||||
--> $DIR/parse-error.rs:54:14
|
||||
|
|
||||
LL | asm!(format!("{{{}}}", 0), in(reg) foo);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -181,12 +157,12 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo);
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: asm template must be a string literal
|
||||
--> $DIR/parse-error.rs:61:21
|
||||
--> $DIR/parse-error.rs:56:21
|
||||
|
|
||||
LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
|
18
src/test/ui/associated-types/hr-associated-type-bound-1.rs
Normal file
18
src/test/ui/associated-types/hr-associated-type-bound-1.rs
Normal file
@ -0,0 +1,18 @@
|
||||
trait X<'a>
|
||||
where
|
||||
for<'b> <Self as X<'b>>::U: Clone,
|
||||
{
|
||||
type U: ?Sized;
|
||||
fn f(&self, x: &Self::U) {
|
||||
<Self::U>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl X<'_> for i32 {
|
||||
type U = str;
|
||||
//~^ ERROR the trait bound `for<'b> <i32 as X<'b>>::U: std::clone::Clone`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
1i32.f("abc");
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
error[E0277]: the trait bound `for<'b> <i32 as X<'b>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-1.rs:12:14
|
||||
|
|
||||
LL | trait X<'a>
|
||||
| - required by a bound in this
|
||||
LL | where
|
||||
LL | for<'b> <Self as X<'b>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<i32 as X<'b>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
21
src/test/ui/associated-types/hr-associated-type-bound-2.rs
Normal file
21
src/test/ui/associated-types/hr-associated-type-bound-2.rs
Normal file
@ -0,0 +1,21 @@
|
||||
trait X<'a>
|
||||
where
|
||||
for<'b> <Self as X<'b>>::U: Clone,
|
||||
{
|
||||
type U: ?Sized;
|
||||
fn f(&self, x: &Self::U) {
|
||||
<Self::U>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl X<'_> for u32
|
||||
where
|
||||
for<'b> <Self as X<'b>>::U: Clone,
|
||||
{
|
||||
type U = str;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
1u32.f("abc");
|
||||
//~^ ERROR no method named `f` found for type `u32` in the current scope
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
error[E0599]: no method named `f` found for type `u32` in the current scope
|
||||
--> $DIR/hr-associated-type-bound-2.rs:19:10
|
||||
|
|
||||
LL | 1u32.f("abc");
|
||||
| ^ method not found in `u32`
|
||||
|
|
||||
= note: the method `f` exists but the following trait bounds were not satisfied:
|
||||
`<u32 as X<'b>>::U: std::clone::Clone`
|
||||
which is required by `u32: X`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
@ -0,0 +1,14 @@
|
||||
trait X<'a>
|
||||
where
|
||||
for<'b> <Self as X<'b>>::U: Clone,
|
||||
{
|
||||
type U: ?Sized;
|
||||
}
|
||||
fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
|
||||
//~^ ERROR the trait bound `for<'b> <T as X<'b>>::U: std::clone::Clone` is not satisfied
|
||||
<<T as X<'_>>::U>::clone(x);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
f::<dyn X<'_, U = str>>("abc");
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
error[E0277]: the trait bound `for<'b> <T as X<'b>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-object.rs:7:13
|
||||
|
|
||||
LL | trait X<'a>
|
||||
| - required by a bound in this
|
||||
LL | where
|
||||
LL | for<'b> <Self as X<'b>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
|
||||
| ^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<T as X<'b>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,20 @@
|
||||
trait Y<'a, T: ?Sized>
|
||||
where
|
||||
T: Y<'a, Self>,
|
||||
for<'b> <Self as Y<'b, T>>::V: Clone,
|
||||
for<'b> <T as Y<'b, Self>>::V: Clone,
|
||||
{
|
||||
type V: ?Sized;
|
||||
fn g(&self, x: &Self::V) {
|
||||
<Self::V>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Y<'a, u8> for u8 {
|
||||
type V = str;
|
||||
//~^ ERROR the trait bound `for<'b> <u8 as Y<'b, u8>>::V: std::clone::Clone` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {
|
||||
1u8.g("abc");
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
error[E0277]: the trait bound `for<'b> <u8 as Y<'b, u8>>::V: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-1.rs:14:14
|
||||
|
|
||||
LL | trait Y<'a, T: ?Sized>
|
||||
| - required by a bound in this
|
||||
...
|
||||
LL | for<'b> <Self as Y<'b, T>>::V: Clone,
|
||||
| ----- required by this bound in `Y`
|
||||
...
|
||||
LL | type V = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u8 as Y<'b, u8>>::V`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
trait Z<'a, T: ?Sized>
|
||||
where
|
||||
T: Z<'a, u16>,
|
||||
//~^ the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
|
||||
//~| the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
|
||||
for<'b> <T as Z<'b, u16>>::W: Clone,
|
||||
{
|
||||
type W: ?Sized;
|
||||
fn h(&self, x: &T::W) {
|
||||
<T::W>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Z<'a, u16> for u16 {
|
||||
type W = str;
|
||||
//~^ ERROR the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone
|
||||
}
|
||||
|
||||
fn main() {
|
||||
1u16.h("abc");
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-2.rs:3:8
|
||||
|
|
||||
LL | trait Z<'a, T: ?Sized>
|
||||
| - required by a bound in this
|
||||
LL | where
|
||||
LL | T: Z<'a, u16>,
|
||||
| ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
|
||||
...
|
||||
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
|
||||
| ----- required by this bound in `Z`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-2.rs:15:14
|
||||
|
|
||||
LL | trait Z<'a, T: ?Sized>
|
||||
| - required by a bound in this
|
||||
...
|
||||
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
|
||||
| ----- required by this bound in `Z`
|
||||
...
|
||||
LL | type W = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-2.rs:3:8
|
||||
|
|
||||
LL | trait Z<'a, T: ?Sized>
|
||||
| - required by a bound in this
|
||||
LL | where
|
||||
LL | T: Z<'a, u16>,
|
||||
| ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
|
||||
...
|
||||
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
|
||||
| ----- required by this bound in `Z`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
trait X<'a, T>
|
||||
where
|
||||
for<'b> T: X<'b, T>,
|
||||
for<'b> <T as X<'b, T>>::U: Clone,
|
||||
{
|
||||
type U: ?Sized;
|
||||
fn f(x: &<T as X<'_, T>>::U) {
|
||||
<<T as X<'_, T>>::U>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T> X<'_, (T,)> for (S,) {
|
||||
type U = str;
|
||||
//~^ ERROR the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<(i32,) as X<(i32,)>>::f("abc");
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
error[E0277]: the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-3.rs:15:14
|
||||
|
|
||||
LL | trait X<'a, T>
|
||||
| - required by a bound in this
|
||||
...
|
||||
LL | for<'b> <T as X<'b, T>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, (T,)>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,19 @@
|
||||
trait X<'a, T>
|
||||
where
|
||||
for<'b> (T,): X<'b, T>,
|
||||
for<'b> <(T,) as X<'b, T>>::U: Clone,
|
||||
{
|
||||
type U: ?Sized;
|
||||
fn f(x: &<(T,) as X<'_, T>>::U) {
|
||||
<<(T,) as X<'_, T>>::U>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T> X<'_, T> for (S,) {
|
||||
type U = str;
|
||||
//~^ ERROR the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<(i32,) as X<i32>>::f("abc");
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
error[E0277]: the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-4.rs:13:14
|
||||
|
|
||||
LL | trait X<'a, T>
|
||||
| - required by a bound in this
|
||||
...
|
||||
LL | for<'b> <(T,) as X<'b, T>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, T>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,41 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
trait Cycle: Sized {
|
||||
type Next: Cycle<Next = Self>;
|
||||
}
|
||||
|
||||
impl<T> Cycle for Box<T> {
|
||||
type Next = Vec<T>;
|
||||
}
|
||||
|
||||
impl<T> Cycle for Vec<T> {
|
||||
type Next = Box<T>;
|
||||
}
|
||||
|
||||
trait X<'a, T: Cycle + for<'b> X<'b, T>>
|
||||
where
|
||||
for<'b> <T as X<'b, T>>::U: Clone,
|
||||
for<'b> T::Next: X<'b, T::Next>,
|
||||
for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
|
||||
{
|
||||
type U: ?Sized;
|
||||
fn f(x: &<T as X<'_, T>>::U) {
|
||||
<<T as X<'_, T>>::U>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T> X<'_, Vec<T>> for S {
|
||||
type U = str;
|
||||
//~^ ERROR the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
|
||||
//~| ERROR the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
|
||||
}
|
||||
|
||||
impl<S, T> X<'_, Box<T>> for S {
|
||||
type U = str;
|
||||
//~^ ERROR the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
|
||||
//~| ERROR the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<i32 as X<Box<i32>>>::f("abc");
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
error[E0277]: the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-5.rs:28:14
|
||||
|
|
||||
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
|
||||
| - required by a bound in this
|
||||
...
|
||||
LL | for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error[E0277]: the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-5.rs:28:14
|
||||
|
|
||||
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
|
||||
| - required by a bound in this
|
||||
LL | where
|
||||
LL | for<'b> <T as X<'b, T>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error[E0277]: the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-5.rs:34:14
|
||||
|
|
||||
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
|
||||
| - required by a bound in this
|
||||
...
|
||||
LL | for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error[E0277]: the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-5.rs:34:14
|
||||
|
|
||||
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
|
||||
| - required by a bound in this
|
||||
LL | where
|
||||
LL | for<'b> <T as X<'b, T>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,20 @@
|
||||
trait X<'a, T>
|
||||
where
|
||||
for<'b> T: X<'b, T>,
|
||||
for<'b> <T as X<'b, T>>::U: Clone,
|
||||
{
|
||||
type U: ?Sized;
|
||||
fn f(x: &<T as X<'_, T>>::U) {
|
||||
<<T as X<'_, T>>::U>::clone(x);
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T> X<'_, T> for (S,) {
|
||||
//~^ ERROR the trait bound `for<'b> T: X<'b, T>` is not satisfied
|
||||
type U = str;
|
||||
//~^ ERROR the trait bound `for<'b> <T as X<'b, T>>::U: std::clone::Clone` is not satisfied
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<(i32,) as X<i32>>::f("abc");
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
error[E0277]: the trait bound `for<'b> <T as X<'b, T>>::U: std::clone::Clone` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-6.rs:14:14
|
||||
|
|
||||
LL | trait X<'a, T>
|
||||
| - required by a bound in this
|
||||
...
|
||||
LL | for<'b> <T as X<'b, T>>::U: Clone,
|
||||
| ----- required by this bound in `X`
|
||||
...
|
||||
LL | type U = str;
|
||||
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<T as X<'b, T>>::U`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::clone::Clone>
|
||||
<&mut T as std::clone::Clone>
|
||||
|
||||
error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied
|
||||
--> $DIR/hr-associated-type-bound-param-6.rs:12:12
|
||||
|
|
||||
LL | trait X<'a, T>
|
||||
| - required by a bound in this
|
||||
LL | where
|
||||
LL | for<'b> T: X<'b, T>,
|
||||
| -------- required by this bound in `X`
|
||||
...
|
||||
LL | impl<S, T> X<'_, T> for (S,) {
|
||||
| ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
trait UnsafeCopy<'a, T: Copy>
|
||||
where
|
||||
for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
|
||||
{
|
||||
type Item;
|
||||
|
||||
fn bug(item: &Self::Item) -> () {
|
||||
let x: T = **item;
|
||||
&x as *const _;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
||||
//~^ ERROR the trait bound `<T as UnsafeCopy<'b, T>>::Item: std::ops::Deref` is not satisfied
|
||||
type Item = T;
|
||||
//~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: std::ops::Deref
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<&'static str>::bug(&"");
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
error[E0277]: the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: std::ops::Deref` is not satisfied
|
||||
--> $DIR/hr-associated-type-projection-1.rs:15:17
|
||||
|
|
||||
LL | trait UnsafeCopy<'a, T: Copy>
|
||||
| ---------- required by a bound in this
|
||||
LL | where
|
||||
LL | for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
|
||||
| --------------------------- required by this bound in `UnsafeCopy`
|
||||
...
|
||||
LL | type Item = T;
|
||||
| ^ the trait `for<'b> std::ops::Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&T as std::ops::Deref>
|
||||
<&mut T as std::ops::Deref>
|
||||
|
||||
error[E0277]: the trait bound `<T as UnsafeCopy<'b, T>>::Item: std::ops::Deref` is not satisfied
|
||||
--> $DIR/hr-associated-type-projection-1.rs:13:33
|
||||
|
|
||||
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
|
||||
|
|
||||
help: consider further restricting the associated type
|
||||
|
|
||||
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where <T as UnsafeCopy<'b, T>>::Item: std::ops::Deref {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -3,11 +3,9 @@ use std::ops::Deref;
|
||||
trait PointerFamily<U> {
|
||||
type Pointer<T>: Deref<Target = T>;
|
||||
//~^ ERROR generic associated types are unstable
|
||||
//~| ERROR type-generic associated types are not yet implemented
|
||||
type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
//~^ ERROR generic associated types are unstable
|
||||
//~| ERROR where clauses on associated types are unstable
|
||||
//~| ERROR type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
@ -8,7 +8,7 @@ LL | type Pointer<T>: Deref<Target = T>;
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: generic associated types are unstable
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:7:5
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:6:5
|
||||
|
|
||||
LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -17,7 +17,7 @@ LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: where clauses on associated types are unstable
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:7:5
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:6:5
|
||||
|
|
||||
LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -26,7 +26,7 @@ LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: generic associated types are unstable
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:16:5
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:14:5
|
||||
|
|
||||
LL | type Pointer<Usize> = Box<Usize>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -35,7 +35,7 @@ LL | type Pointer<Usize> = Box<Usize>;
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: generic associated types are unstable
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:18:5
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:16:5
|
||||
|
|
||||
LL | type Pointer2<U32> = Box<U32>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -44,7 +44,7 @@ LL | type Pointer2<U32> = Box<U32>;
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: where clauses on associated types are unstable
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:23:5
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:21:5
|
||||
|
|
||||
LL | type Assoc where Self: Sized;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -53,7 +53,7 @@ LL | type Assoc where Self: Sized;
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: where clauses on associated types are unstable
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:28:5
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:26:5
|
||||
|
|
||||
LL | type Assoc where Self: Sized = Foo;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -61,22 +61,6 @@ LL | type Assoc where Self: Sized = Foo;
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:4:5
|
||||
|
|
||||
LL | type Pointer<T>: Deref<Target = T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/feature-gate-generic_associated_types.rs:7:5
|
||||
|
|
||||
LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -0,0 +1,72 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
// A Collection trait and collection families. Based on
|
||||
// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
|
||||
// associated-type-constructors-part-2-family-traits/
|
||||
|
||||
// check that we don't normalize with trait defaults.
|
||||
|
||||
trait Collection<T> {
|
||||
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
|
||||
type Family: CollectionFamily;
|
||||
// Test associated type defaults with parameters
|
||||
type Sibling<U>: Collection<U> =
|
||||
<<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
|
||||
|
||||
fn empty() -> Self;
|
||||
|
||||
fn add(&mut self, value: T);
|
||||
|
||||
fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
|
||||
}
|
||||
|
||||
trait CollectionFamily {
|
||||
type Member<T>: Collection<T, Family = Self>;
|
||||
}
|
||||
|
||||
struct VecFamily;
|
||||
|
||||
impl CollectionFamily for VecFamily {
|
||||
type Member<T> = Vec<T>;
|
||||
}
|
||||
|
||||
impl<T> Collection<T> for Vec<T> {
|
||||
type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
|
||||
type Family = VecFamily;
|
||||
|
||||
fn empty() -> Self {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn add(&mut self, value: T) {
|
||||
self.push(value)
|
||||
}
|
||||
|
||||
fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
|
||||
where
|
||||
C: Collection<i32>,
|
||||
{
|
||||
let mut res = <C::Family as CollectionFamily>::Member::<f32>::empty();
|
||||
for &v in ints.iterate() {
|
||||
res.add(v as f32);
|
||||
}
|
||||
res
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn use_floatify() {
|
||||
let a = vec![1i32, 2, 3];
|
||||
let c = floatify_sibling(&a);
|
||||
assert_eq!(Some(&1.0), c.iterate().next());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use_floatify();
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/collections-project-default.rs:60:5
|
||||
|
|
||||
LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
|
||||
| ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type
|
||||
...
|
||||
LL | res
|
||||
| ^^^ expected Collection::Sibling, found CollectionFamily::Member
|
||||
|
|
||||
= note: expected associated type `<C as Collection<i32>>::Sibling<f32>`
|
||||
found associated type `<<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -6,13 +6,14 @@
|
||||
// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
|
||||
// associated-type-constructors-part-2-family-traits/
|
||||
|
||||
// run-pass
|
||||
|
||||
trait Collection<T> {
|
||||
type Iter<'iter>: Iterator<Item=&'iter T>;
|
||||
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
|
||||
type Family: CollectionFamily;
|
||||
// Test associated type defaults with parameters
|
||||
type Sibling<U>: Collection<U> =
|
||||
<<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
|
||||
//~^^ ERROR type-generic associated types are not yet implemented
|
||||
|
||||
fn empty() -> Self;
|
||||
|
||||
@ -23,7 +24,6 @@ trait Collection<T> {
|
||||
|
||||
trait CollectionFamily {
|
||||
type Member<T>: Collection<T, Family = Self>;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
struct VecFamily;
|
||||
@ -33,7 +33,7 @@ impl CollectionFamily for VecFamily {
|
||||
}
|
||||
|
||||
impl<T> Collection<T> for Vec<T> {
|
||||
type Iter<'iter> = std::slice::Iter<'iter, T>;
|
||||
type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
|
||||
type Family = VecFamily;
|
||||
|
||||
fn empty() -> Self {
|
||||
@ -53,18 +53,7 @@ fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>
|
||||
where
|
||||
C: Collection<i32>,
|
||||
{
|
||||
let mut res = C::Family::Member::<f32>::empty();
|
||||
for &v in ints.iterate() {
|
||||
res.add(v as f32);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
|
||||
where
|
||||
C: Collection<i32>,
|
||||
{
|
||||
let mut res = C::Family::Member::<f32>::empty();
|
||||
let mut res = <C::Family as CollectionFamily>::Member::<f32>::empty();
|
||||
for &v in ints.iterate() {
|
||||
res.add(v as f32);
|
||||
}
|
||||
@ -72,11 +61,11 @@ where
|
||||
}
|
||||
|
||||
fn use_floatify() {
|
||||
let a = vec![1i32, 2, 3];
|
||||
let b = floatify(a);
|
||||
println!("{}", b.iterate().next());
|
||||
let c = floatify_sibling(a);
|
||||
println!("{}", c.iterate().next());
|
||||
let a = vec![1, 2, 3];
|
||||
let b = floatify(&a);
|
||||
assert_eq!(Some(&1.0), b.iterate().next());
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
fn main() {
|
||||
use_floatify();
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/collections.rs:13:5
|
||||
|
|
||||
LL | / type Sibling<U>: Collection<U> =
|
||||
LL | | <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
|
||||
| |_________________________________________________________________________^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/collections.rs:25:5
|
||||
|
|
||||
LL | type Member<T>: Collection<T, Family = Self>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
// FIXME(#30472) normalize enough to handle this.
|
||||
// check-pass
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
@ -17,7 +17,6 @@ trait Baz {
|
||||
}
|
||||
|
||||
impl<T> Baz for T where T: Foo {
|
||||
//~^ ERROR type mismatch resolving
|
||||
type Quux<'a> where T: 'a = T;
|
||||
|
||||
type Baa<'a> where T: 'a = &'a <T as Foo>::Bar<'a, 'static>;
|
||||
|
@ -1,18 +0,0 @@
|
||||
error[E0271]: type mismatch resolving `for<'a> <<T as Baz>::Baa<'a> as std::ops::Deref>::Target == <<T as Baz>::Quux<'a> as Foo>::Bar<'a, 'static>`
|
||||
--> $DIR/construct_with_other_type.rs:19:9
|
||||
|
|
||||
LL | impl<T> Baz for T where T: Foo {
|
||||
| - ^^^ expected type parameter `T`, found associated type
|
||||
| |
|
||||
| this type parameter
|
||||
|
|
||||
= note: expected associated type `<T as Foo>::Bar<'_, 'static>`
|
||||
found associated type `<<T as Baz>::Quux<'_> as Foo>::Bar<'_, 'static>`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | impl<T> Baz for T where T: Foo + Baz<Quux = T> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -6,7 +6,6 @@ struct Foo;
|
||||
trait MyTrait {
|
||||
type Item<T>;
|
||||
//~^ ERROR generic associated types are unstable [E0658]
|
||||
//~| ERROR type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
impl MyTrait for Foo {
|
||||
|
@ -8,7 +8,7 @@ LL | type Item<T>;
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: generic associated types are unstable
|
||||
--> $DIR/gat-dont-ice-on-absent-feature-2.rs:13:5
|
||||
--> $DIR/gat-dont-ice-on-absent-feature-2.rs:12:5
|
||||
|
|
||||
LL | type Item<T> = T;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -16,14 +16,6 @@ LL | type Item<T> = T;
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/gat-dont-ice-on-absent-feature-2.rs:7:5
|
||||
|
|
||||
LL | type Item<T>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -9,11 +9,8 @@ use std::fmt::{Display, Debug};
|
||||
trait Foo {
|
||||
type Assoc where Self: Sized;
|
||||
type Assoc2<T> where T: Display;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
type Assoc3<T>;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
type WithDefault<'a, T: Debug + 'a> = dyn Iterator<Item=T>;
|
||||
//~^ ERROR type-generic associated types are not yet implemented
|
||||
type WithDefault<'a, T: Debug + 'a>: ?Sized = dyn Iterator<Item=T>;
|
||||
type NoGenerics;
|
||||
}
|
||||
|
||||
@ -23,6 +20,7 @@ impl Foo for Bar {
|
||||
type Assoc = usize;
|
||||
type Assoc2<T> = Vec<T>;
|
||||
type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
//~^ impl has stricter requirements than trait
|
||||
type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>;
|
||||
type NoGenerics = ::std::cell::Cell<i32>;
|
||||
}
|
||||
|
@ -1,26 +1,12 @@
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/generic-associated-types-where.rs:11:5
|
||||
|
|
||||
LL | type Assoc2<T> where T: Display;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/generic-associated-types-where.rs:13:5
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/generic-associated-types-where.rs:22:5
|
||||
|
|
||||
LL | type Assoc3<T>;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
| --------------- definition of `Assoc3` from trait
|
||||
...
|
||||
LL | type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator`
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/generic-associated-types-where.rs:15:5
|
||||
|
|
||||
LL | type WithDefault<'a, T: Debug + 'a> = dyn Iterator<Item=T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0276`.
|
||||
|
@ -5,13 +5,13 @@
|
||||
|
||||
trait Foo {
|
||||
type Assoc3<T>;
|
||||
//~^ type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for Bar {
|
||||
type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
//~^ ERROR impl has stricter requirements than trait
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,10 +1,12 @@
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/issue-47206-where-clause.rs:7:5
|
||||
error[E0276]: impl has stricter requirements than trait
|
||||
--> $DIR/issue-47206-where-clause.rs:13:5
|
||||
|
|
||||
LL | type Assoc3<T>;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
| --------------- definition of `Assoc3` from trait
|
||||
...
|
||||
LL | type Assoc3<T> where T: Iterator = Vec<T>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0276`.
|
||||
|
@ -1,11 +1,14 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
// FIXME(generic-associated-types) Investigate why this doesn't compile.
|
||||
// check-pass
|
||||
|
||||
trait Iterator {
|
||||
type Item<'a>: 'a;
|
||||
//~^ ERROR the requirement `for<'a> <Self as Iterator>::Item<'a>: 'a` is not satisfied
|
||||
}
|
||||
|
||||
impl Iterator for () {
|
||||
type Item<'a> = &'a ();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,10 +0,0 @@
|
||||
error[E0280]: the requirement `for<'a> <Self as Iterator>::Item<'a>: 'a` is not satisfied
|
||||
--> $DIR/issue-62326-parameter-out-of-range.rs:7:20
|
||||
|
|
||||
LL | trait Iterator {
|
||||
| -------- required by a bound in this
|
||||
LL | type Item<'a>: 'a;
|
||||
| ^^ required by this bound in `Iterator`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -7,7 +7,6 @@ trait Trait1 {
|
||||
trait Trait2 {
|
||||
type Type1<B>: Trait1<A=B>;
|
||||
//~^ ERROR: generic associated types are unstable
|
||||
//~| ERROR: type-generic associated types are not yet implemented
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -7,14 +7,6 @@ LL | type Type1<B>: Trait1<A=B>;
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
|
||||
|
||||
error: type-generic associated types are not yet implemented
|
||||
--> $DIR/issue-67424.rs:8:5
|
||||
|
|
||||
LL | type Type1<B>: Trait1<A=B>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -0,0 +1,32 @@
|
||||
// Regression test for #68641
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait UnsafeCopy {
|
||||
type Item<'a>: Copy;
|
||||
|
||||
fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> {
|
||||
*item
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UnsafeCopy for T {
|
||||
type Item<'a> = T;
|
||||
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut s = String::from("Hello world!");
|
||||
|
||||
let copy = String::copy(&s);
|
||||
|
||||
// Do we indeed point to the samme memory?
|
||||
assert!(s.as_ptr() == copy.as_ptr());
|
||||
|
||||
// Any use of `copy` is certeinly UB after this
|
||||
drop(s);
|
||||
|
||||
// UB UB UB UB UB!!
|
||||
println!("{}", copy);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68641-check-gat-bounds.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-68641-check-gat-bounds.rs:15:5
|
||||
|
|
||||
LL | type Item<'a>: Copy;
|
||||
| -------------------- required by `UnsafeCopy::Item`
|
||||
...
|
||||
LL | type Item<'a> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::marker::Copy> UnsafeCopy for T {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68642
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<fn() -> usize>::callme(|| 1);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68642-broken-llvm-ir.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68642-broken-llvm-ir.rs:15:5
|
||||
|
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68643
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
<fn()>::callme(|| {});
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68643-broken-mir.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68643-broken-mir.rs:15:5
|
||||
|
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68644
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<u8>::callme(0);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68644-codegen-selection.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68644-codegen-selection.rs:15:5
|
||||
|
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,21 @@
|
||||
// Regression test for #68645
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait Fun {
|
||||
type F<'a>: Fn() -> u32;
|
||||
|
||||
fn callme<'a>(f: Self::F<'a>) -> u32 {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Fun for T {
|
||||
type F<'a> = Self;
|
||||
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<&dyn Iterator<Item = u8>>::callme(&std::iter::once(1));
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68645-codegen-fulfillment.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
|
||||
--> $DIR/issue-68645-codegen-fulfillment.rs:15:5
|
||||
|
|
||||
LL | type F<'a>: Fn() -> u32;
|
||||
| ------------------------ required by `Fun::F`
|
||||
...
|
||||
LL | type F<'a> = Self;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
||||
|
|
||||
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
|
||||
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | impl<T: std::ops::Fn<()>> Fun for T {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,22 @@
|
||||
// Regression test for #68656
|
||||
|
||||
#![feature(generic_associated_types)]
|
||||
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
|
||||
|
||||
trait UnsafeCopy<T: Copy> {
|
||||
type Item<'a>: std::ops::Deref<Target = T>;
|
||||
|
||||
fn bug<'a>(item: &Self::Item<'a>) -> () {
|
||||
let x: T = **item;
|
||||
&x as *const _;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
|
||||
type Item<'a> = T;
|
||||
//~^ ERROR type mismatch resolving `<T as std::ops::Deref>::Target == T`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<&'static str>::bug(&"");
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-68656-unsized-values.rs:3:12
|
||||
|
|
||||
LL | #![feature(generic_associated_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
|
||||
|
||||
error[E0271]: type mismatch resolving `<T as std::ops::Deref>::Target == T`
|
||||
--> $DIR/issue-68656-unsized-values.rs:16:5
|
||||
|
|
||||
LL | type Item<'a>: std::ops::Deref<Target = T>;
|
||||
| ------------------------------------------- required by `UnsafeCopy::Item`
|
||||
...
|
||||
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
|
||||
| - this type parameter
|
||||
LL | type Item<'a> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
|
||||
|
|
||||
= note: expected type parameter `T`
|
||||
found associated type `<T as std::ops::Deref>::Target`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | impl<T: Copy + std::ops::Deref + std::ops::Deref<Target = T>> UnsafeCopy<T> for T {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -1,7 +1,7 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_associated_types)]
|
||||
|
||||
// FIXME(#30472) normalize enough to handle this.
|
||||
// run-pass
|
||||
|
||||
trait Iterable {
|
||||
type Item<'a> where Self: 'a;
|
||||
@ -13,39 +13,35 @@ trait Iterable {
|
||||
// Impl for struct type
|
||||
impl<T> Iterable for Vec<T> {
|
||||
type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
|
||||
//~^ ERROR type mismatch resolving
|
||||
type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
|
||||
|
||||
fn iter<'a>(&'a self) -> Self::Iter<'a> {
|
||||
//~^ ERROR type mismatch resolving
|
||||
self.iter()
|
||||
self[..].iter()
|
||||
}
|
||||
}
|
||||
|
||||
// Impl for a primitive type
|
||||
impl<T> Iterable for [T] {
|
||||
type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
|
||||
//~^ ERROR type mismatch resolving
|
||||
type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
|
||||
|
||||
fn iter<'a>(&'a self) -> Self::Iter<'a> {
|
||||
//~^ ERROR type mismatch resolving
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
|
||||
fn make_iter<'a, I: Iterable + ?Sized>(it: &'a I) -> I::Iter<'a> {
|
||||
it.iter()
|
||||
}
|
||||
|
||||
fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
|
||||
fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> {
|
||||
it.iter().next()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = vec![1, 2, 3];
|
||||
assert_eq!(v, make_iter(&v).copied().collect());
|
||||
assert_eq!(v, make_iter(&*v).copied().collect());
|
||||
assert_eq!(1, get_first(&v));
|
||||
assert_eq!(1, get_first(&*v));
|
||||
assert_eq!(v, make_iter(&v).copied().collect::<Vec<_>>());
|
||||
assert_eq!(v, make_iter(&*v).copied().collect::<Vec<_>>());
|
||||
assert_eq!(Some(&1), get_first(&v));
|
||||
assert_eq!(Some(&1), get_first(&*v));
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:15:33
|
||||
|
|
||||
LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
|
||||
= help: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:27:33
|
||||
|
|
||||
LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
|
||||
|
|
||||
= note: expected reference `&T`
|
||||
found associated type `<[T] as Iterable>::Item<'_>`
|
||||
= help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:19:30
|
||||
|
|
||||
LL | trait Iterable {
|
||||
| -------- required by a bound in this
|
||||
LL | type Item<'a> where Self: 'a;
|
||||
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
|
||||
| --------------------- required by this bound in `Iterable`
|
||||
...
|
||||
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
|
||||
| ^^^^^^^^^^^^^^ expected associated type, found reference
|
||||
|
|
||||
= note: expected associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
|
||||
found reference `&T`
|
||||
= help: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` or calling a method that returns `<std::vec::Vec<T> as Iterable>::Item<'_>`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
|
||||
--> $DIR/iterable.rs:31:30
|
||||
|
|
||||
LL | trait Iterable {
|
||||
| -------- required by a bound in this
|
||||
LL | type Item<'a> where Self: 'a;
|
||||
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
|
||||
| --------------------- required by this bound in `Iterable`
|
||||
...
|
||||
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
|
||||
| ^^^^^^^^^^^^^^ expected associated type, found reference
|
||||
|
|
||||
= note: expected associated type `<[T] as Iterable>::Item<'_>`
|
||||
found reference `&T`
|
||||
= help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` or calling a method that returns `<[T] as Iterable>::Item<'_>`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
@ -34,12 +34,11 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
||||
|
||||
struct E<B>(B);
|
||||
|
||||
impl<B: Add> Add for E<B> where B: Add<Output = B>, B: std::ops::Add<Output = B> {
|
||||
//~^ ERROR equality constraints are not yet supported in `where` clauses
|
||||
impl<B: Add> Add for E<B> where B: Add<Output = B> {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
Self(self.0 + rhs.0) //~ ERROR mismatched types
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user